diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 6a773a4bcf7..5b9af25dd6c 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -659,9 +659,6 @@ - - - - - - - - - - + + + + + + + + + + + + + + + + + diff --git a/res/layout/preference_bluetooth_profile.xml b/res/layout/preference_bluetooth_profile.xml new file mode 100644 index 00000000000..5ec0a479f99 --- /dev/null +++ b/res/layout/preference_bluetooth_profile.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/layout/profile_icon_small.xml b/res/layout/profile_icon_small.xml new file mode 100644 index 00000000000..b0a9f4bdd26 --- /dev/null +++ b/res/layout/profile_icon_small.xml @@ -0,0 +1,23 @@ + + + diff --git a/res/values/strings.xml b/res/values/strings.xml index d6221fe0480..da54e9d3523 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -782,7 +782,14 @@ Scan for devices - + + Find nearby devices + + Device settings + + Paired devices + + Found devices Connect @@ -823,12 +830,18 @@ %1$s options + + Device actions Connect Connect to Bluetooth device Profiles + + Rename device + + Allow incoming file transfers Connected to media audio diff --git a/res/xml/bluetooth_device_advanced.xml b/res/xml/bluetooth_device_advanced.xml index 561159529b7..b4a097860cf 100644 --- a/res/xml/bluetooth_device_advanced.xml +++ b/res/xml/bluetooth_device_advanced.xml @@ -18,15 +18,32 @@ xmlns:android="http://schemas.android.com/apk/res/android"> - - + + - + + + + + diff --git a/res/xml/bluetooth_settings.xml b/res/xml/bluetooth_settings.xml index 131f7a01ee5..b7a0edcd77b 100644 --- a/res/xml/bluetooth_settings.xml +++ b/res/xml/bluetooth_settings.xml @@ -18,6 +18,9 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:title="@string/bluetooth_settings" > + + - - - + + diff --git a/res/xml/device_picker.xml b/res/xml/device_picker.xml index 7dd5b6887f1..43b58296cd3 100644 --- a/res/xml/device_picker.xml +++ b/res/xml/device_picker.xml @@ -23,7 +23,7 @@ diff --git a/src/com/android/settings/bluetooth/BluetoothDevicePreference.java b/src/com/android/settings/bluetooth/BluetoothDevicePreference.java index f0b1705b3a0..1f9408d12e4 100644 --- a/src/com/android/settings/bluetooth/BluetoothDevicePreference.java +++ b/src/com/android/settings/bluetooth/BluetoothDevicePreference.java @@ -19,16 +19,22 @@ package com.android.settings.bluetooth; import com.android.settings.R; import android.content.Context; +import android.graphics.drawable.Drawable; import android.preference.Preference; import android.util.TypedValue; +import android.view.LayoutInflater; import android.view.View; +import android.view.ViewGroup; +import android.view.View.OnClickListener; import android.widget.ImageView; +import android.widget.LinearLayout; /** * BluetoothDevicePreference is the preference type used to display each remote * Bluetooth device in the Bluetooth Settings screen. */ -public class BluetoothDevicePreference extends Preference implements CachedBluetoothDevice.Callback { +public class BluetoothDevicePreference extends Preference implements + CachedBluetoothDevice.Callback, OnClickListener { private static final String TAG = "BluetoothDevicePreference"; private static int sDimAlpha = Integer.MIN_VALUE; @@ -36,6 +42,9 @@ public class BluetoothDevicePreference extends Preference implements CachedBluet private CachedBluetoothDevice mCachedDevice; private int mAccessibleProfile; + private ImageView mDeviceSettings; + private OnClickListener mOnSettingsClickListener; + /** * Cached local copy of whether the device is busy. This is only updated * from {@link #onDeviceAttributesChanged(CachedBluetoothDevice)}. @@ -66,6 +75,10 @@ public class BluetoothDevicePreference extends Preference implements CachedBluet return mCachedDevice; } + public void setOnSettingsClickListener(OnClickListener listener) { + mOnSettingsClickListener = listener; + } + @Override protected void onPrepareForRemoval() { super.onPrepareForRemoval(); @@ -117,6 +130,34 @@ public class BluetoothDevicePreference extends Preference implements CachedBluet ImageView btClass = (ImageView) view.findViewById(R.id.btClass); btClass.setImageResource(mCachedDevice.getBtClassDrawable()); btClass.setAlpha(isEnabled() ? 255 : sDimAlpha); + + mDeviceSettings = (ImageView) view.findViewById(R.id.deviceDetails); + if (mOnSettingsClickListener != null) { + mDeviceSettings.setOnClickListener(this); + mDeviceSettings.setTag(mCachedDevice); + } else { // Hide the settings icon and divider + mDeviceSettings.setVisibility(View.GONE); + ImageView divider = (ImageView) view.findViewById(R.id.divider); + if (divider != null) { + divider.setVisibility(View.GONE); + } + } + + LayoutInflater inflater = (LayoutInflater) + getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + ViewGroup profilesGroup = (ViewGroup) view.findViewById(R.id.profileIcons); + for (Drawable icon : mCachedDevice.getProfileIcons()) { + inflater.inflate(R.layout.profile_icon_small, profilesGroup, true); + ImageView imageView = + (ImageView) profilesGroup.getChildAt(profilesGroup.getChildCount() - 1); + imageView.setImageDrawable(icon); + } + } + + public void onClick(View v) { + if (v == mDeviceSettings) { + if (mOnSettingsClickListener != null) mOnSettingsClickListener.onClick(v); + } } @Override diff --git a/src/com/android/settings/bluetooth/BluetoothProfilePreference.java b/src/com/android/settings/bluetooth/BluetoothProfilePreference.java new file mode 100644 index 00000000000..c0df8a74140 --- /dev/null +++ b/src/com/android/settings/bluetooth/BluetoothProfilePreference.java @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.bluetooth; + +import com.android.settings.bluetooth.LocalBluetoothProfileManager.Profile; +import com.android.settings.R; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.preference.Preference; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.View.OnClickListener; +import android.widget.ImageView; + +/** + * BluetoothProfilePreference is the preference type used to display each profile for a + * particular bluetooth device. + */ +public class BluetoothProfilePreference extends Preference implements OnClickListener { + + private static final String TAG = "BluetoothProfilePreference"; + + private Drawable mProfileDrawable; + private boolean mExpanded; + private ImageView mProfileExpandView; + private Profile mProfile; + + private OnClickListener mOnExpandClickListener; + + public BluetoothProfilePreference(Context context, Profile profile) { + super(context); + + mProfile = profile; + + setLayoutResource(R.layout.preference_bluetooth_profile); + setExpanded(false); + } + + public void setOnExpandClickListener(OnClickListener listener) { + mOnExpandClickListener = listener; + } + + public void setExpanded(boolean expanded) { + mExpanded = expanded; + notifyChanged(); + } + + public boolean isExpanded() { + return mExpanded; + } + + public void setProfileDrawable(Drawable drawable) { + mProfileDrawable = drawable; + } + + @Override + protected void onBindView(View view) { + super.onBindView(view); + + ImageView btProfile = (ImageView) view.findViewById(R.id.profileIcon); + btProfile.setImageDrawable(mProfileDrawable); + + mProfileExpandView = (ImageView) view.findViewById(R.id.profileExpand); + mProfileExpandView.setOnClickListener(this); + mProfileExpandView.setTag(mProfile); + + mProfileExpandView.setImageResource(mExpanded ? R.drawable.ic_preferences_expanded + : R.drawable.ic_preferences_collapsed); + } + + public void onClick(View v) { + if (v == mProfileExpandView) { + if (mOnExpandClickListener != null) { + setExpanded(!mExpanded); + mOnExpandClickListener.onClick(v); + } + } + } +} diff --git a/src/com/android/settings/bluetooth/BluetoothSettings.java b/src/com/android/settings/bluetooth/BluetoothSettings.java index 0de3bfa96ad..841c9abc4c9 100644 --- a/src/com/android/settings/bluetooth/BluetoothSettings.java +++ b/src/com/android/settings/bluetooth/BluetoothSettings.java @@ -16,11 +16,11 @@ package com.android.settings.bluetooth; +import com.android.settings.bluetooth.LocalBluetoothProfileManager.Profile; import com.android.settings.ProgressCategory; import com.android.settings.R; import com.android.settings.SettingsPreferenceFragment; import com.android.settings.UserLeaveHintListener; -import com.android.settings.bluetooth.LocalBluetoothProfileManager.Profile; import android.app.Activity; import android.app.AlertDialog; @@ -39,6 +39,7 @@ import android.os.Bundle; import android.os.ParcelUuid; import android.preference.CheckBoxPreference; import android.preference.Preference; +import android.preference.PreferenceCategory; import android.preference.PreferenceScreen; import android.text.TextUtils; import android.view.ContextMenu; @@ -55,7 +56,7 @@ import java.util.WeakHashMap; * connection management. */ public class BluetoothSettings extends SettingsPreferenceFragment - implements LocalBluetoothManager.Callback, UserLeaveHintListener { + implements LocalBluetoothManager.Callback, UserLeaveHintListener, View.OnClickListener { private static final String TAG = "BluetoothSettings"; @@ -64,14 +65,18 @@ public class BluetoothSettings extends SettingsPreferenceFragment private static final String KEY_BT_DEVICE_LIST = "bt_device_list"; private static final String KEY_BT_NAME = "bt_name"; private static final String KEY_BT_SCAN = "bt_scan"; + private static final String KEY_BT_FIND_NEARBY = "bt_find_nearby"; private static final int SCREEN_TYPE_SETTINGS = 0; private static final int SCREEN_TYPE_DEVICEPICKER = 1; private static final int SCREEN_TYPE_TETHERING = 2; + private static final int SCREEN_TYPE_SCAN = 3; public static final String ACTION = "bluetooth_action"; public static final String ACTION_LAUNCH_TETHER_PICKER = - "com.android.settings.bluetooth.action.LAUNCH_TETHER_PICKER"; + "com.android.settings.bluetooth.action.LAUNCH_TETHER_PICKER"; + public static final String ACTION_LAUNCH_SCAN_MODE = + "com.android.settings.bluetooth.action.LAUNCH_SCAN_MODE"; private int mScreenType; private int mFilterType; @@ -88,7 +93,7 @@ public class BluetoothSettings extends SettingsPreferenceFragment private BluetoothNamePreference mNamePreference; - private ProgressCategory mDeviceList; + private PreferenceCategory mDeviceList; private WeakHashMap mDevicePreferenceMap = new WeakHashMap(); @@ -96,11 +101,11 @@ public class BluetoothSettings extends SettingsPreferenceFragment private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - // TODO: put this in callback instead of receiving - if (intent.getAction().equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { onBluetoothStateChanged(mLocalManager.getBluetoothState()); } else if (intent.getAction().equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) { + // TODO: If this is a scanning screen, maybe return on successful pairing + int bondState = intent .getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR); if (bondState == BluetoothDevice.BOND_BONDED) { @@ -153,6 +158,8 @@ public class BluetoothSettings extends SettingsPreferenceFragment action = intent.getAction(); } + if (getPreferenceScreen() != null) getPreferenceScreen().removeAll(); + if (action.equals(BluetoothDevicePicker.ACTION_LAUNCH)) { mScreenType = SCREEN_TYPE_DEVICEPICKER; mNeedAuth = intent.getBooleanExtra(BluetoothDevicePicker.EXTRA_NEED_AUTH, false); @@ -168,6 +175,10 @@ public class BluetoothSettings extends SettingsPreferenceFragment mFilterType = BluetoothDevicePicker.FILTER_TYPE_PANU; activity.setTitle(activity.getString(R.string.device_picker)); + addPreferencesFromResource(R.xml.device_picker); + } else if (action.equals(ACTION_LAUNCH_SCAN_MODE)) { + mScreenType = SCREEN_TYPE_SCAN; + addPreferencesFromResource(R.xml.device_picker); } else { addPreferencesFromResource(R.xml.bluetooth_settings); @@ -182,10 +193,9 @@ public class BluetoothSettings extends SettingsPreferenceFragment mNamePreference = (BluetoothNamePreference) findPreference(KEY_BT_NAME); - mDeviceList = (ProgressCategory) findPreference(KEY_BT_DEVICE_LIST); } - mDeviceList = (ProgressCategory) findPreference(KEY_BT_DEVICE_LIST); + mDeviceList = (PreferenceCategory) findPreference(KEY_BT_DEVICE_LIST); registerForContextMenu(getListView()); @@ -200,7 +210,9 @@ public class BluetoothSettings extends SettingsPreferenceFragment // bluetooth manager mDevicePreferenceMap.clear(); mDeviceList.removeAll(); - addDevices(); + if (mScreenType != SCREEN_TYPE_SCAN) { + addDevices(); + } if (mScreenType == SCREEN_TYPE_SETTINGS) { mEnabler.resume(); @@ -210,8 +222,11 @@ public class BluetoothSettings extends SettingsPreferenceFragment mLocalManager.registerCallback(this); - mDeviceList.setProgress(mLocalManager.getBluetoothAdapter().isDiscovering()); - mLocalManager.startScanning(false); + updateProgressUi(mLocalManager.getBluetoothAdapter().isDiscovering()); + + if (mScreenType != SCREEN_TYPE_SETTINGS) { + mLocalManager.startScanning(true); + } IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); @@ -249,6 +264,13 @@ public class BluetoothSettings extends SettingsPreferenceFragment } } + public void onClick(View v) { + if (v.getTag() instanceof CachedBluetoothDevice) { + CachedBluetoothDevice device = (CachedBluetoothDevice) v.getTag(); + device.onClickedAdvancedOptions(this); + } + } + @Override public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { @@ -260,7 +282,7 @@ public class BluetoothSettings extends SettingsPreferenceFragment if (preference instanceof BluetoothDevicePreference) { BluetoothDevicePreference btPreference = (BluetoothDevicePreference)preference; - if (mScreenType == SCREEN_TYPE_SETTINGS) { + if (mScreenType == SCREEN_TYPE_SETTINGS || mScreenType == SCREEN_TYPE_SCAN) { btPreference.getCachedDevice().onClicked(); } else if (mScreenType == SCREEN_TYPE_DEVICEPICKER) { CachedBluetoothDevice device = btPreference.getCachedDevice(); @@ -312,7 +334,7 @@ public class BluetoothSettings extends SettingsPreferenceFragment CachedBluetoothDevice cachedDevice = getDeviceFromMenuInfo(item.getMenuInfo()); if (cachedDevice == null) return false; - cachedDevice.onContextItemSelected(item); + cachedDevice.onContextItemSelected(item, this); return true; } @@ -337,8 +359,11 @@ public class BluetoothSettings extends SettingsPreferenceFragment throw new IllegalStateException("Got onDeviceAdded, but cachedDevice already exists"); } - if (addDevicePreference(cachedDevice)) { - createDevicePreference(cachedDevice); + if (mScreenType != SCREEN_TYPE_SETTINGS + || cachedDevice.getBondState() == BluetoothDevice.BOND_BONDED) { + if (addDevicePreference(cachedDevice)) { + createDevicePreference(cachedDevice); + } } } @@ -406,6 +431,9 @@ public class BluetoothSettings extends SettingsPreferenceFragment preference = new BluetoothDevicePreference( getActivity(), cachedDevice, CachedBluetoothDevice.OTHER_PROFILES); } + if (mScreenType == SCREEN_TYPE_SETTINGS) { + preference.setOnSettingsClickListener(this); + } mDeviceList.addPreference(preference); mDevicePreferenceMap.put(cachedDevice, preference); } @@ -418,16 +446,23 @@ public class BluetoothSettings extends SettingsPreferenceFragment } public void onScanningStateChanged(boolean started) { - mDeviceList.setProgress(started); + updateProgressUi(started); } + private void updateProgressUi(boolean start) { + if (mDeviceList instanceof ProgressCategory) { + ((ProgressCategory) mDeviceList).setProgress(start); + } + } private void onBluetoothStateChanged(int bluetoothState) { // When bluetooth is enabled (and we are in the activity, which we are), // we should start a scan if (bluetoothState == BluetoothAdapter.STATE_ON) { - mLocalManager.startScanning(false); + if (mScreenType != SCREEN_TYPE_SETTINGS) { + mLocalManager.startScanning(false); + } } else if (bluetoothState == BluetoothAdapter.STATE_OFF) { - mDeviceList.setProgress(false); + updateProgressUi(false); } } @@ -480,4 +515,22 @@ public class BluetoothSettings extends SettingsPreferenceFragment } getActivity().sendBroadcast(intent); } + + public static class FindNearby extends BluetoothSettings { + + public FindNearby() { + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + Bundle args = super.getArguments(); + if (args == null) { + args = new Bundle(); + setArguments(args); + } + args.putString(ACTION, ACTION_LAUNCH_SCAN_MODE); + super.onActivityCreated(savedInstanceState); + } + } } + diff --git a/src/com/android/settings/bluetooth/CachedBluetoothDevice.java b/src/com/android/settings/bluetooth/CachedBluetoothDevice.java index c0fa105d82d..22fa0055ede 100644 --- a/src/com/android/settings/bluetooth/CachedBluetoothDevice.java +++ b/src/com/android/settings/bluetooth/CachedBluetoothDevice.java @@ -16,28 +16,31 @@ package com.android.settings.bluetooth; +import com.android.settings.R; + +import com.android.settings.SettingsPreferenceFragment; +import com.android.settings.bluetooth.LocalBluetoothProfileManager.Profile; + import android.app.AlertDialog; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothDevice; import android.content.Context; import android.content.DialogInterface; -import android.content.Intent; import android.content.res.Resources; +import android.graphics.drawable.Drawable; import android.os.ParcelUuid; import android.os.SystemClock; +import android.preference.Preference; +import android.preference.PreferenceActivity; import android.text.TextUtils; import android.util.Log; import android.view.ContextMenu; import android.view.Menu; import android.view.MenuItem; -import com.android.settings.R; -import com.android.settings.bluetooth.LocalBluetoothProfileManager.Profile; - import java.util.ArrayList; import java.util.List; -import java.util.Set; /** * CachedBluetoothDevice represents a remote Bluetooth device. It contains @@ -63,6 +66,7 @@ public class CachedBluetoothDevice implements Comparable private String mName; private short mRssi; private BluetoothClass mBtClass; + private Context mContext; private List mProfiles = new ArrayList(); @@ -138,6 +142,7 @@ public class CachedBluetoothDevice implements Comparable } mDevice = device; + mContext = context; fillData(); } @@ -655,6 +660,20 @@ public class CachedBluetoothDevice implements Comparable return SettingsBtStatus.getPairingStatusSummary(getBondState()); } + public List getProfileIcons() { + ArrayList drawables = new ArrayList(); + + for (Profile profile : mProfiles) { + LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager + .getProfileManager(mLocalManager, profile); + int iconResource = profileManager.getDrawableResource(); + if (iconResource != 0) { + drawables.add(mContext.getResources().getDrawable(iconResource)); + } + } + + return drawables; + } /** * We have special summaries when particular profiles are connected. This * checks for those states and returns an applicable summary. @@ -781,7 +800,7 @@ public class CachedBluetoothDevice implements Comparable * * @param item The item that was clicked. */ - public void onContextItemSelected(MenuItem item) { + public void onContextItemSelected(MenuItem item, SettingsPreferenceFragment fragment) { switch (item.getItemId()) { case CONTEXT_ITEM_DISCONNECT: disconnect(); @@ -796,21 +815,34 @@ public class CachedBluetoothDevice implements Comparable break; case CONTEXT_ITEM_CONNECT_ADVANCED: - Intent intent = new Intent(); - // Need an activity context to open this in our task - Context context = mLocalManager.getForegroundActivity(); - if (context == null) { - // Fallback on application context, and open in a new task - context = mLocalManager.getContext(); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - } - intent.setClass(context, ConnectSpecificProfilesActivity.class); - intent.putExtra(ConnectSpecificProfilesActivity.EXTRA_DEVICE, mDevice); - context.startActivity(intent); + onClickedAdvancedOptions(fragment); break; } } + public void onClickedAdvancedOptions(SettingsPreferenceFragment fragment) { + // TODO: Verify if there really is a case when there's no foreground + // activity + + // Intent intent = new Intent(); + // // Need an activity context to open this in our task + // Context context = mLocalManager.getForegroundActivity(); + // if (context == null) { + // // Fallback on application context, and open in a new task + // context = mLocalManager.getContext(); + // intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + // } + // intent.setClass(context, ConnectSpecificProfilesActivity.class); + // intent.putExtra(ConnectSpecificProfilesActivity.EXTRA_DEVICE, + // mDevice); + // context.startActivity(intent); + Preference pref = new Preference(fragment.getActivity()); + pref.setTitle(getName()); + pref.setFragment(DeviceProfilesSettings.class.getName()); + pref.getExtras().putParcelable(DeviceProfilesSettings.EXTRA_DEVICE, mDevice); + ((PreferenceActivity) fragment.getActivity()).onPreferenceStartFragment(fragment, pref); + } + public void registerCallback(Callback callback) { synchronized (mCallbacks) { mCallbacks.add(callback); diff --git a/src/com/android/settings/bluetooth/ConnectSpecificProfilesActivity.java b/src/com/android/settings/bluetooth/DeviceProfilesSettings.java similarity index 54% rename from src/com/android/settings/bluetooth/ConnectSpecificProfilesActivity.java rename to src/com/android/settings/bluetooth/DeviceProfilesSettings.java index ac2b4d81ab8..f8a66f68063 100644 --- a/src/com/android/settings/bluetooth/ConnectSpecificProfilesActivity.java +++ b/src/com/android/settings/bluetooth/DeviceProfilesSettings.java @@ -16,31 +16,41 @@ package com.android.settings.bluetooth; +import com.android.settings.R; +import com.android.settings.SettingsPreferenceFragment; +import com.android.settings.bluetooth.LocalBluetoothProfileManager.Profile; + import android.bluetooth.BluetoothDevice; -import android.content.Intent; +import android.content.Context; import android.os.Bundle; import android.preference.CheckBoxPreference; +import android.preference.EditTextPreference; import android.preference.Preference; -import android.preference.PreferenceActivity; import android.preference.PreferenceGroup; +import android.preference.PreferenceScreen; import android.text.TextUtils; import android.util.Log; +import android.view.View; -import com.android.settings.R; -import com.android.settings.bluetooth.LocalBluetoothProfileManager.Profile; +import java.util.HashMap; /** * ConnectSpecificProfilesActivity presents the user with all of the profiles * for a particular device, and allows him to choose which should be connected * (or disconnected). */ -public class ConnectSpecificProfilesActivity extends PreferenceActivity - implements CachedBluetoothDevice.Callback, Preference.OnPreferenceChangeListener { - private static final String TAG = "ConnectSpecificProfilesActivity"; +public class DeviceProfilesSettings extends SettingsPreferenceFragment + implements CachedBluetoothDevice.Callback, Preference.OnPreferenceChangeListener, + View.OnClickListener { + private static final String TAG = "DeviceProfilesSettings"; - private static final String KEY_ONLINE_MODE = "online_mode"; private static final String KEY_TITLE = "title"; + private static final String KEY_RENAME_DEVICE = "rename_device"; private static final String KEY_PROFILE_CONTAINER = "profile_container"; + private static final String KEY_UNPAIR = "unpair"; + private static final String KEY_ALLOW_INCOMING = "allow_incoming"; + + private static final String AUTO_CONNECT_KEY_SUFFIX = "X"; public static final String EXTRA_DEVICE = "device"; @@ -48,27 +58,21 @@ public class ConnectSpecificProfilesActivity extends PreferenceActivity private CachedBluetoothDevice mCachedDevice; private PreferenceGroup mProfileContainer; - private CheckBoxPreference mOnlineModePreference; - - /** - * The current mode of this activity and its checkboxes (either online mode - * or offline mode). In online mode, user interactions with the profile - * checkboxes will also toggle the profile's connectivity. In offline mode, - * they will not, and only the preferred state will be saved for the - * profile. - */ - private boolean mOnlineMode; + private CheckBoxPreference mAllowIncomingPref; + private EditTextPreference mDeviceNamePref; + private HashMap mAutoConnectPrefs + = new HashMap(); @Override - protected void onCreate(Bundle savedInstanceState) { + public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); BluetoothDevice device; if (savedInstanceState != null) { device = savedInstanceState.getParcelable(EXTRA_DEVICE); } else { - Intent intent = getIntent(); - device = intent.getParcelableExtra(EXTRA_DEVICE); + Bundle args = getArguments(); + device = args.getParcelable(EXTRA_DEVICE); } if (device == null) { @@ -76,7 +80,7 @@ public class ConnectSpecificProfilesActivity extends PreferenceActivity finish(); } - mManager = LocalBluetoothManager.getInstance(this); + mManager = LocalBluetoothManager.getInstance(getActivity()); mCachedDevice = mManager.getCachedDeviceManager().findDevice(device); if (mCachedDevice == null) { Log.w(TAG, "Device not found, cannot connect to it"); @@ -84,39 +88,43 @@ public class ConnectSpecificProfilesActivity extends PreferenceActivity } addPreferencesFromResource(R.xml.bluetooth_device_advanced); + getPreferenceScreen().setOrderingAsAdded(false); + mProfileContainer = (PreferenceGroup) findPreference(KEY_PROFILE_CONTAINER); + mAllowIncomingPref = (CheckBoxPreference) findPreference(KEY_ALLOW_INCOMING); + mAllowIncomingPref.setChecked(isIncomingFileTransfersAllowed()); + + mDeviceNamePref = (EditTextPreference) findPreference(KEY_RENAME_DEVICE); + mDeviceNamePref.setSummary(mCachedDevice.getName()); + mDeviceNamePref.setText(mCachedDevice.getName()); // Set the title of the screen - findPreference(KEY_TITLE).setTitle( - getString(R.string.bluetooth_device_advanced_title, mCachedDevice.getName())); - - // Listen for check/uncheck of the online mode checkbox - mOnlineModePreference = (CheckBoxPreference) findPreference(KEY_ONLINE_MODE); - mOnlineModePreference.setOnPreferenceChangeListener(this); + findPreference(KEY_TITLE).setTitle(getResources() + .getString(R.string.bluetooth_device_advanced_title, mCachedDevice.getName())); // Add a preference for each profile addPreferencesForProfiles(); } @Override - protected void onSaveInstanceState(Bundle outState) { + public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putParcelable(EXTRA_DEVICE, mCachedDevice.getDevice()); } @Override - protected void onResume() { + public void onResume() { super.onResume(); - mManager.setForegroundActivity(this); + mManager.setForegroundActivity(getActivity()); mCachedDevice.registerCallback(this); refresh(); } @Override - protected void onPause() { + public void onPause() { super.onPause(); mCachedDevice.unregisterCallback(this); @@ -138,18 +146,20 @@ public class ConnectSpecificProfilesActivity extends PreferenceActivity * @return A preference that allows the user to choose whether this profile * will be connected to. */ - private CheckBoxPreference createProfilePreference(Profile profile) { - CheckBoxPreference pref = new CheckBoxPreference(this); + private Preference createProfilePreference(Profile profile) { + BluetoothProfilePreference pref = new BluetoothProfilePreference(getActivity(), profile); pref.setKey(profile.toString()); pref.setTitle(profile.localizedString); + pref.setExpanded(false); pref.setPersistent(false); - pref.setOnPreferenceChangeListener(this); + pref.setOrder(getProfilePreferenceIndex(profile)); + pref.setOnExpandClickListener(this); LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager .getProfileManager(mManager, profile); /** - * Gray out checkbox while connecting and disconnecting + * Gray out profile while connecting and disconnecting */ pref.setEnabled(!mCachedDevice.isBusy()); @@ -158,37 +168,46 @@ public class ConnectSpecificProfilesActivity extends PreferenceActivity return pref; } - public boolean onPreferenceChange(Preference preference, Object newValue) { + @Override + public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) { String key = preference.getKey(); - if (TextUtils.isEmpty(key) || newValue == null) return true; + if (preference instanceof BluetoothProfilePreference) { + onProfileClicked(preference, Profile.valueOf(key)); + return true; + } else if (key.equals(KEY_UNPAIR)) { + unpairDevice(); + finish(); + return true; + } - if (key.equals(KEY_ONLINE_MODE)) { - onOnlineModeCheckedStateChanged((Boolean) newValue); + return false; + } + public boolean onPreferenceChange(Preference preference, Object newValue) { + if (preference == mAllowIncomingPref) { + setIncomingFileTransfersAllowed(mAllowIncomingPref.isChecked()); + } else if (preference == mDeviceNamePref) { + // TODO: Verify and check for error conditions + mCachedDevice.setName(mDeviceNamePref.getText()); } else { - Profile profile = getProfileOf(preference); - if (profile == null) return false; - onProfileCheckedStateChanged(profile, (Boolean) newValue); + return false; } return true; } - private void onOnlineModeCheckedStateChanged(boolean checked) { - setOnlineMode(checked, true); - } - - private void onProfileCheckedStateChanged(Profile profile, boolean checked) { + private void onProfileClicked(Preference preference, Profile profile) { LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager .getProfileManager(mManager, profile); - profileManager.setPreferred(mCachedDevice.getDevice(), checked); - if (mOnlineMode) { - if (checked) { - mCachedDevice.connect(profile); - } else { - mCachedDevice.disconnect(profile); - } - } + // TODO: Get the current state and flip it, updating the summary for the preference + +// profileManager.setPreferred(mCachedDevice.getDevice(), checked); +// +// if (checked) { +// mCachedDevice.connect(profile); +// } else { +// mCachedDevice.disconnect(profile); +// } } public void onDeviceAttributesChanged(CachedBluetoothDevice cachedDevice) { @@ -196,51 +215,12 @@ public class ConnectSpecificProfilesActivity extends PreferenceActivity } private void refresh() { - // We are in 'online mode' if we are connected, connecting, or disconnecting - setOnlineMode(mCachedDevice.isConnected() || mCachedDevice.isBusy(), false); refreshProfiles(); } - /** - * Switches between online/offline mode. - * - * @param onlineMode Whether to be in online mode, or offline mode. - * @param takeAction Whether to take action (i.e., connect or disconnect) - * based on the new online mode. - */ - private void setOnlineMode(boolean onlineMode, boolean takeAction) { - mOnlineMode = onlineMode; - - if (takeAction) { - if (onlineMode) { - mCachedDevice.connect(); - } else { - mCachedDevice.disconnect(); - } - } - - refreshOnlineModePreference(); - } - - private void refreshOnlineModePreference() { - mOnlineModePreference.setChecked(mOnlineMode); - - /* Gray out checkbox while connecting and disconnecting */ - mOnlineModePreference.setEnabled(!mCachedDevice.isBusy()); - - /** - * If the device is online, show status. Otherwise, show a summary that - * describes what the checkbox does. - */ - mOnlineModePreference.setSummary(mOnlineMode ? - mCachedDevice.getSummary(CachedBluetoothDevice.OTHER_PROFILES) - : R.string.bluetooth_device_advanced_online_mode_summary); - } - private void refreshProfiles() { for (Profile profile : mCachedDevice.getConnectableProfiles()) { - CheckBoxPreference profilePref = - (CheckBoxPreference) findPreference(profile.toString()); + Preference profilePref = findPreference(profile.toString()); if (profilePref == null) { profilePref = createProfilePreference(profile); mProfileContainer.addPreference(profilePref); @@ -250,7 +230,7 @@ public class ConnectSpecificProfilesActivity extends PreferenceActivity } } - private void refreshProfilePreference(CheckBoxPreference profilePref, Profile profile) { + private void refreshProfilePreference(Preference profilePref, Profile profile) { BluetoothDevice device = mCachedDevice.getDevice(); LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager .getProfileManager(mManager, profile); @@ -262,9 +242,9 @@ public class ConnectSpecificProfilesActivity extends PreferenceActivity */ profilePref.setEnabled(!mCachedDevice.isBusy()); profilePref.setSummary(getProfileSummary(profileManager, profile, device, - connectionStatus, mOnlineMode)); - - profilePref.setChecked(profileManager.isPreferred(device)); + connectionStatus, isDeviceOnline())); + // TODO: + //profilePref.setChecked(profileManager.isPreferred(device)); } private Profile getProfileOf(Preference pref) { @@ -307,4 +287,60 @@ public class ConnectSpecificProfilesActivity extends PreferenceActivity } } + public void onClick(View v) { + if (v.getTag() instanceof Profile) { + Profile prof = (Profile) v.getTag(); + CheckBoxPreference autoConnectPref = mAutoConnectPrefs.get(prof.toString()); + if (autoConnectPref == null) { + autoConnectPref = new CheckBoxPreference(getActivity()); + autoConnectPref.setKey(prof.toString() + AUTO_CONNECT_KEY_SUFFIX); + autoConnectPref.setTitle(getCheckBoxTitle(prof)); + autoConnectPref.setOrder(getProfilePreferenceIndex(prof) + 1); + autoConnectPref.setChecked(getAutoConnect(prof)); + mAutoConnectPrefs.put(prof.name(), autoConnectPref); + } + BluetoothProfilePreference profilePref = + (BluetoothProfilePreference) findPreference(prof.toString()); + if (profilePref != null) { + if (profilePref.isExpanded()) { + mProfileContainer.addPreference(autoConnectPref); + } else { + mProfileContainer.removePreference(autoConnectPref); + } + } + } + } + + private int getProfilePreferenceIndex(Profile prof) { + return mProfileContainer.getOrder() + prof.ordinal() * 10; + } + + private void unpairDevice() { + mCachedDevice.unpair(); + } + + private boolean isDeviceOnline() { + // TODO: Verify + return mCachedDevice.isConnected() || mCachedDevice.isBusy(); + } + + private void setIncomingFileTransfersAllowed(boolean allow) { + // TODO: + Log.d(TAG, "Set allow incoming = " + allow); + } + + private boolean isIncomingFileTransfersAllowed() { + // TODO: + return true; + } + + private String getCheckBoxTitle(Profile prof) { + // TODO: Use resources and base it on profile if necessary + return "Auto connect"; + } + + private boolean getAutoConnect(Profile prof) { + // TODO: Get the auto connect toggle state for the profile + return true; + } } diff --git a/src/com/android/settings/bluetooth/LocalBluetoothManager.java b/src/com/android/settings/bluetooth/LocalBluetoothManager.java index 613ee258676..b46cc96d2f1 100644 --- a/src/com/android/settings/bluetooth/LocalBluetoothManager.java +++ b/src/com/android/settings/bluetooth/LocalBluetoothManager.java @@ -47,7 +47,7 @@ public class LocalBluetoothManager { private static final String SHARED_PREFERENCES_NAME = "bluetooth_settings"; /** Singleton instance. */ - private static LocalBluetoothManager INSTANCE; + private static LocalBluetoothManager sInstance; private boolean mInitialized; private Context mContext; @@ -87,17 +87,17 @@ public class LocalBluetoothManager { public static LocalBluetoothManager getInstance(Context context) { synchronized (LocalBluetoothManager.class) { - if (INSTANCE == null) { - INSTANCE = new LocalBluetoothManager(); + if (sInstance == null) { + sInstance = new LocalBluetoothManager(); } - if (!INSTANCE.init(context)) { + if (!sInstance.init(context)) { return null; } - LocalBluetoothProfileManager.init(INSTANCE); + LocalBluetoothProfileManager.init(sInstance); - return INSTANCE; + return sInstance; } } diff --git a/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java b/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java index 1480b163e4f..f7ad3d3c4b5 100644 --- a/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java +++ b/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java @@ -31,12 +31,10 @@ import android.os.ParcelUuid; import android.util.Log; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Set; /** * LocalBluetoothProfileManager is an abstract class defining the basic @@ -123,7 +121,8 @@ public abstract class LocalBluetoothProfileManager { } } - private static LinkedList mServiceListeners = new LinkedList(); + private static LinkedList mServiceListeners = + new LinkedList(); public static void addServiceListener(ServiceListener l) { mServiceListeners.add(l); @@ -221,6 +220,10 @@ public abstract class LocalBluetoothProfileManager { public abstract boolean isProfileReady(); + public int getDrawableResource() { + return R.drawable.ic_bt_headphones_a2dp; + } + // TODO: int instead of enum public enum Profile { HEADSET(R.string.bluetooth_profile_headset), @@ -347,6 +350,11 @@ public abstract class LocalBluetoothProfileManager { public boolean isProfileReady() { return true; } + + @Override + public int getDrawableResource() { + return R.drawable.ic_bt_headphones_a2dp; + } } /** @@ -489,6 +497,11 @@ public abstract class LocalBluetoothProfileManager { return SettingsBtStatus.CONNECTION_STATUS_UNKNOWN; } } + + @Override + public int getDrawableResource() { + return R.drawable.ic_bt_headset_hfp; + } } /** @@ -563,6 +576,12 @@ public abstract class LocalBluetoothProfileManager { return SettingsBtStatus.CONNECTION_STATUS_UNKNOWN; } } + + @Override + public int getDrawableResource() { + // TODO: + return 0; + } } private static class HidProfileManager extends LocalBluetoothProfileManager { @@ -645,6 +664,12 @@ public abstract class LocalBluetoothProfileManager { mService.setInputDevicePriority(device, BluetoothInputDevice.PRIORITY_OFF); } } + + @Override + public int getDrawableResource() { + // TODO: + return 0; + } } private static class PanProfileManager extends LocalBluetoothProfileManager { @@ -721,5 +746,11 @@ public abstract class LocalBluetoothProfileManager { public void setPreferred(BluetoothDevice device, boolean preferred) { return; } + + @Override + public int getDrawableResource() { + // TODO: + return 0; + } } }