Implement BT settings functionality for new UI.

- Removed context menu logic for long press (no longer used).
- Converted device picker to run in its own Activity, using a dialog
  theme on large screen devices and full-screen on phones.
- Removed unused resources.
- Add device to "Paired devices" list when pairing is initiated by the
  remote device.
- Return to Bluetooth settings pane after successfully pairing a new
  device from the "Find nearby device" pane.
- Add support for renaming devices (TODO: persist the custom name and
  update the "bread crumb" in the action bar to the new device name).
- Add support for incoming file transfer and auto connect checkboxes
  in DeviceProfilesSettings.
- Show available and connected device profiles as icons instead of
  summary text. Available but disconnected profiles are drawn in gray.
- Fixed bluetooth_notif_message to include the device name as a parameter
  instead of appending the name to the end of the localized string.
- Changed some fields from private to package scope for more efficient
  access from inner classes.

Bug: 3137982

Change-Id: Ic2d6ee5be60c9c5b3f3a8a58846d58efedfa5c93
This commit is contained in:
Jake Hamby
2010-12-07 16:27:21 -08:00
parent 97c01af22b
commit c090feb64f
16 changed files with 195 additions and 309 deletions

View File

@@ -206,16 +206,22 @@
<category android:name="com.android.settings.SHORTCUT" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.bluetooth.devicepicker.action.LAUNCH" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.bluetooth.BluetoothSettings" />
<meta-data android:name="com.android.settings.TOP_LEVEL_HEADER_ID"
android:resource="@id/wireless_settings" />
</activity>
<activity android:name=".bluetooth.DevicePickerActivity"
android:theme="@android:style/Theme.Holo.DialogWhenLarge"
android:label="@string/device_picker"
android:clearTaskOnLaunch="true">
<intent-filter>
<action android:name="android.bluetooth.devicepicker.action.LAUNCH" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name="Settings$TetherSettingsActivity"
android:theme="@android:style/Theme.Holo"
android:clearTaskOnLaunch="true">

View File

@@ -1,51 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/* //device/apps/Settings/assets/res/layout/bluetooth.xml
**
** Copyright 2006, 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.
*/
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="2dip"
android:paddingRight="2dip">
<Button android:id="@+id/enable"
android:textStyle="bold"
android:text="@string/bluetooth_enable_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<Button android:id="@+id/scan"
android:textStyle="bold"
android:text="@string/bluetooth_scan_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<Button android:id="@+id/settings"
android:textStyle="bold"
android:text="@string/bluetooth_settings_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<ListView android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:drawSelectorOnTop="false">
</ListView>
</LinearLayout>

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="600dip"
android:layout_height="match_parent">
<fragment
android:id="@+id/bluetooth_device_picker_fragment"
android:name="com.android.settings.bluetooth.BluetoothSettings"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1" />
</LinearLayout>

View File

@@ -205,7 +205,7 @@
<string name="bluetooth_scan_for_devices">Scan for devices</string>
<!-- Bluetooth settings. Message for disconnecting from a bluetooth device -->
<string name="bluetooth_disconnect_blank"><xliff:g id="device_name">%1$s</xliff:g> will be disconnected.</string>
<!-- Bluetooth settings. Message when cnonected to a device -->
<!-- Bluetooth settings. Message when connected to a device -->
<string name="bluetooth_connected">Connected</string>
<!-- Bluetooth settings. Message when a device is disconnected -->
<string name="bluetooth_disconnected">Disconnected</string>
@@ -230,7 +230,7 @@
<!-- Notification title when a Bluetooth device wants to pair with us -->
<string name="bluetooth_notif_title">Pairing request</string>
<!-- Notification message when a Bluetooth device wants to pair with us -->
<string name="bluetooth_notif_message">Select to pair with\u0020</string>
<string name="bluetooth_notif_message">Select to pair with <xliff:g id="device_name">%1$s</xliff:g></string>
<!-- Strings for BluetoothDevicePicker -->
<string name="device_picker">Bluetooth device picker</string>
@@ -254,13 +254,6 @@
<!-- Strings for msg to display to user while bluetooth is turning on -->
<string name="bluetooth_turning_on">"Turning on Bluetooth\u2026"</string>
<!-- Do not translate. Used for diagnostic screens, precise translation is not necessary -->
<string name="bluetooth_scan_text">Empty button\u2026</string>
<!-- Do not translate. Used for diagnostic screens, precise translation is not necessary -->
<string name="bluetooth_settings_text">Empty button\u2026</string>
<!-- Do not translate. Used for diagnostic screens, precise translation is not necessary -->
<string name="bluetooth_enable_text">Empty button\u2026</string>
<!-- Do not translate. Used for diagnostic screens, precise translation is not necessary -->
<string name="bluetooth_device_info_connectButton_text">Turn on Bluetooth</string>
<!-- Do not translate. Used for diagnostic screens, precise translation is not necessary -->
@@ -824,9 +817,7 @@
<!-- Bluetooth settings. The user-visible string that is used whenever referring to the A2DP profile. -->
<string name="bluetooth_profile_a2dp">Media</string>
<!-- Bluetooth settings. The user-visible string that is used whenever referring to the headset or handsfree profile. -->
<string name="bluetooth_profile_headset" product="tablet">Tablet</string>
<!-- Bluetooth settings. The user-visible string that is used whenever referring to the headset or handsfree profile. -->
<string name="bluetooth_profile_headset" product="default">Phone</string>
<string name="bluetooth_profile_headset">Handsfree</string>
<!-- Bluetooth settings. The user-visible string that is used whenever referring to the OPP profile. -->
<string name="bluetooth_profile_opp">Transfer</string>
<!-- Bluetooth settings. The user-visible string that is used whenever referring to the HID profile. -->
@@ -850,9 +841,7 @@
<!-- Bluetooth settings. Message for disconnecting from the A2DP profile. -->
<string name="bluetooth_disconnect_a2dp_profile"><xliff:g id="device_name">%1$s</xliff:g> will be disconnected from media audio.</string>
<!-- Bluetooth settings. Message for disconnecting from the headset profile. -->
<string name="bluetooth_disconnect_headset_profile" product="tablet"><xliff:g id="device_name">%1$s</xliff:g> will be disconnected from tablet audio.</string>
<!-- Bluetooth settings. Message for disconnecting from the headset profile. -->
<string name="bluetooth_disconnect_headset_profile" product="default"><xliff:g id="device_name">%1$s</xliff:g> will be disconnected from phone audio.</string>
<string name="bluetooth_disconnect_headset_profile"><xliff:g id="device_name">%1$s</xliff:g> will be disconnected from handsfree audio.</string>
<!-- Bluetooth settings. Message for disconnecting from the HID profile. -->
<string name="bluetooth_disconnect_hid_profile"><xliff:g id="device_name">%1$s</xliff:g> will be disconnected from input device.</string>
<!-- Bluetooth settings. Message for disconnecting from the PAN profile. -->

View File

@@ -75,8 +75,6 @@ public class DeviceAdminAdd extends Activity {
Button mActionButton;
Button mCancelButton;
View mSelectLayout;
final ArrayList<View> mAddingPolicies = new ArrayList<View>();
final ArrayList<View> mActivePolicies = new ArrayList<View>();

View File

@@ -27,7 +27,10 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.LinearLayout;
import com.android.settings.bluetooth.LocalBluetoothProfileManager.Profile;
import java.util.Map;
/**
* BluetoothDevicePreference is the preference type used to display each remote
@@ -43,11 +46,12 @@ public class BluetoothDevicePreference extends Preference implements
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)}.
* from {@link #onDeviceAttributesChanged()}.
*/
private boolean mIsBusy;
@@ -68,7 +72,7 @@ public class BluetoothDevicePreference extends Preference implements
cachedDevice.registerCallback(this);
onDeviceAttributesChanged(cachedDevice);
onDeviceAttributesChanged();
}
public CachedBluetoothDevice getCachedDevice() {
@@ -85,7 +89,7 @@ public class BluetoothDevicePreference extends Preference implements
mCachedDevice.unregisterCallback(this);
}
public void onDeviceAttributesChanged(CachedBluetoothDevice cachedDevice) {
public void onDeviceAttributesChanged() {
/*
* The preference framework takes care of making sure the value has
@@ -99,7 +103,7 @@ public class BluetoothDevicePreference extends Preference implements
* related to BluetoothHeadset not bound to the actual
* BluetoothHeadsetService when we got here.
*/
setSummary(mCachedDevice.getSummary(mAccessibleProfile));
setSummary(mCachedDevice.getSummary());
// Used to gray out the item
mIsBusy = mCachedDevice.isBusy();
@@ -121,7 +125,7 @@ public class BluetoothDevicePreference extends Preference implements
@Override
protected void onBindView(View view) {
// Disable this view if the bluetooth enable/disable preference view is off
if (null != findPreferenceInHierarchy("bt_checkbox")){
if (null != findPreferenceInHierarchy("bt_checkbox")) {
setDependency("bt_checkbox");
}
@@ -129,12 +133,13 @@ public class BluetoothDevicePreference extends Preference implements
ImageView btClass = (ImageView) view.findViewById(android.R.id.icon);
btClass.setImageResource(mCachedDevice.getBtClassDrawable());
btClass.setAlpha(isEnabled() ? 255 : sDimAlpha);
btClass.setAlpha(!mIsBusy ? 255 : sDimAlpha);
mDeviceSettings = (ImageView) view.findViewById(R.id.deviceDetails);
if (mOnSettingsClickListener != null) {
mDeviceSettings.setOnClickListener(this);
mDeviceSettings.setTag(mCachedDevice);
mDeviceSettings.setAlpha(!mIsBusy ? 255 : sDimAlpha);
} else { // Hide the settings icon and divider
mDeviceSettings.setVisibility(View.GONE);
ImageView divider = (ImageView) view.findViewById(R.id.divider);
@@ -146,11 +151,15 @@ public class BluetoothDevicePreference extends Preference implements
LayoutInflater inflater = (LayoutInflater)
getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ViewGroup profilesGroup = (ViewGroup) view.findViewById(R.id.profileIcons);
for (Drawable icon : mCachedDevice.getProfileIcons()) {
Map<Profile, Drawable> profileIcons = mCachedDevice.getProfileIcons();
for (Profile profile : profileIcons.keySet()) {
Drawable icon = profileIcons.get(profile);
inflater.inflate(R.layout.profile_icon_small, profilesGroup, true);
ImageView imageView =
(ImageView) profilesGroup.getChildAt(profilesGroup.getChildCount() - 1);
imageView.setImageDrawable(icon);
boolean profileEnabled = mCachedDevice.isConnectedProfile(profile);
imageView.setAlpha(profileEnabled ? 255 : sDimAlpha);
}
}

View File

@@ -32,7 +32,7 @@ import android.widget.Toast;
/**
* BluetoothEnabler is a helper to manage the Bluetooth on/off checkbox
* preference. It is turns on/off Bluetooth and ensures the summary of the
* preference. It turns on/off Bluetooth and ensures the summary of the
* preference reflects the current state.
*/
public class BluetoothEnabler implements Preference.OnPreferenceChangeListener {
@@ -103,7 +103,7 @@ public class BluetoothEnabler implements Preference.OnPreferenceChangeListener {
return false;
}
private void handleStateChanged(int state) {
/* package */ void handleStateChanged(int state) {
switch (state) {
case BluetoothAdapter.STATE_TURNING_ON:
mCheckBox.setSummary(R.string.wifi_starting);

View File

@@ -47,7 +47,7 @@ import java.util.concurrent.TimeUnit;
public class BluetoothEventRedirector {
private static final String TAG = "BluetoothEventRedirector";
private final LocalBluetoothManager mManager;
/* package */ final LocalBluetoothManager mManager;
private final ThreadPoolExecutor mSerialExecutor = new ThreadPoolExecutor(
0, 1, 1000L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
@@ -215,7 +215,7 @@ public class BluetoothEventRedirector {
}
// This can't be called from a broadcast receiver where the filter is set in the Manifest.
private String getDockedDeviceAddress(Context context) {
/* package */ String getDockedDeviceAddress(Context context) {
// This works only because these broadcast intents are "sticky"
Intent i = context.registerReceiver(null, new IntentFilter(Intent.ACTION_DOCK_EVENT));
if (i != null) {
@@ -230,7 +230,7 @@ public class BluetoothEventRedirector {
return null;
}
private void persistDiscoveringTimestamp(
/* package */ void persistDiscoveringTimestamp(
final BroadcastReceiver.PendingResult pr, final boolean newState) {
// Load the shared preferences and edit it on a background
// thread (but serialized!), but then post back to the main

View File

@@ -85,12 +85,13 @@ public class BluetoothPairingRequest extends BroadcastReceiver {
String name = intent.getStringExtra(BluetoothDevice.EXTRA_NAME);
if (TextUtils.isEmpty(name)) {
name = device.getName();
name = (device != null ? device.getName() :
context.getString(android.R.string.unknownName));
}
notification.setLatestEventInfo(context,
res.getString(R.string.bluetooth_notif_title),
res.getString(R.string.bluetooth_notif_message) + name,
res.getString(R.string.bluetooth_notif_message, name),
pending);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notification.defaults |= Notification.DEFAULT_SOUND;

View File

@@ -42,11 +42,7 @@ import android.preference.Preference;
import android.preference.PreferenceCategory;
import android.preference.PreferenceScreen;
import android.text.TextUtils;
import android.view.ContextMenu;
import android.view.MenuItem;
import android.view.View;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.AdapterView.AdapterContextMenuInfo;
import java.util.List;
import java.util.WeakHashMap;
@@ -117,6 +113,8 @@ public class BluetoothSettings extends SettingsPreferenceFragment
finish();
} else if (mScreenType == SCREEN_TYPE_TETHERING) {
onPanDevicePicked();
} else if (mScreenType == SCREEN_TYPE_SCAN) {
finish();
}
}
}
@@ -140,9 +138,9 @@ public class BluetoothSettings extends SettingsPreferenceFragment
}
// Note:
// If an application wish to show the BT device list, it can send an
// intent to Settings application with below extra data:
// -DEVICE_PICKER_FILTER_TYPE: the type of BT devices that want to show.
// If an application wishes to show the BT device list, it can send an
// intent to Settings application with the following extra data:
// -DEVICE_PICKER_FILTER_TYPE: the type of BT devices to show.
// -DEVICE_PICKER_LAUNCH_PACKAGE: the package which the application belongs to.
// -DEVICE_PICKER_LAUNCH_CLASS: the class which will receive user's selected
// result from the BT list.
@@ -170,7 +168,7 @@ public class BluetoothSettings extends SettingsPreferenceFragment
activity.setTitle(activity.getString(R.string.device_picker));
addPreferencesFromResource(R.xml.device_picker);
} else if (action.equals(ACTION_LAUNCH_TETHER_PICKER)){
} else if (action.equals(ACTION_LAUNCH_TETHER_PICKER)) {
mScreenType = SCREEN_TYPE_TETHERING;
mFilterType = BluetoothDevicePicker.FILTER_TYPE_PANU;
@@ -197,8 +195,6 @@ public class BluetoothSettings extends SettingsPreferenceFragment
mDeviceList = (PreferenceCategory) findPreference(KEY_BT_DEVICE_LIST);
registerForContextMenu(getListView());
super.onActivityCreated(savedInstanceState);
}
@@ -207,7 +203,7 @@ public class BluetoothSettings extends SettingsPreferenceFragment
super.onResume();
// Repopulate (which isn't too bad since it's cached in the settings
// bluetooth manager
// bluetooth manager)
mDevicePreferenceMap.clear();
mDeviceList.removeAll();
if (mScreenType != SCREEN_TYPE_SCAN) {
@@ -264,6 +260,7 @@ public class BluetoothSettings extends SettingsPreferenceFragment
}
public void onClick(View v) {
// User clicked on advanced options icon for a device in the list
if (v.getTag() instanceof CachedBluetoothDevice) {
CachedBluetoothDevice device = (CachedBluetoothDevice) v.getTag();
device.onClickedAdvancedOptions(this);
@@ -281,12 +278,12 @@ public class BluetoothSettings extends SettingsPreferenceFragment
if (preference instanceof BluetoothDevicePreference) {
BluetoothDevicePreference btPreference = (BluetoothDevicePreference)preference;
CachedBluetoothDevice device = btPreference.getCachedDevice();
mSelectedDevice = device.getDevice();
if (mScreenType == SCREEN_TYPE_SETTINGS || mScreenType == SCREEN_TYPE_SCAN) {
btPreference.getCachedDevice().onClicked();
} else if (mScreenType == SCREEN_TYPE_DEVICEPICKER) {
CachedBluetoothDevice device = btPreference.getCachedDevice();
mSelectedDevice = device.getDevice();
mLocalManager.stopScanning();
mLocalManager.persistSelectedDeviceInPicker(mSelectedDevice.getAddress());
if ((device.getBondState() == BluetoothDevice.BOND_BONDED) ||
@@ -296,10 +293,7 @@ public class BluetoothSettings extends SettingsPreferenceFragment
} else {
btPreference.getCachedDevice().onClicked();
}
} else if (mScreenType == SCREEN_TYPE_TETHERING){
CachedBluetoothDevice device = btPreference.getCachedDevice();
mSelectedDevice = device.getDevice();
} else if (mScreenType == SCREEN_TYPE_TETHERING) {
mLocalManager.stopScanning();
mLocalManager.persistSelectedDeviceInPicker(mSelectedDevice.getAddress());
if ((device.getBondState() == BluetoothDevice.BOND_BONDED)) {
@@ -315,43 +309,6 @@ public class BluetoothSettings extends SettingsPreferenceFragment
return super.onPreferenceTreeClick(preferenceScreen, preference);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
//For device picker, disable Context Menu
if (mScreenType != SCREEN_TYPE_SETTINGS) {
return;
}
CachedBluetoothDevice cachedDevice = getDeviceFromMenuInfo(menuInfo);
if (cachedDevice == null) return;
cachedDevice.onCreateContextMenu(menu);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
CachedBluetoothDevice cachedDevice = getDeviceFromMenuInfo(item.getMenuInfo());
if (cachedDevice == null) return false;
cachedDevice.onContextItemSelected(item, this);
return true;
}
private CachedBluetoothDevice getDeviceFromMenuInfo(ContextMenuInfo menuInfo) {
if ((menuInfo == null) || !(menuInfo instanceof AdapterContextMenuInfo)) {
return null;
}
AdapterContextMenuInfo adapterMenuInfo = (AdapterContextMenuInfo) menuInfo;
Preference pref = (Preference) getPreferenceScreen().getRootAdapter().getItem(
adapterMenuInfo.position);
if (pref == null || !(pref instanceof BluetoothDevicePreference)) {
return null;
}
return ((BluetoothDevicePreference) pref).getCachedDevice();
}
public void onDeviceAdded(CachedBluetoothDevice cachedDevice) {
if (mDevicePreferenceMap.get(cachedDevice) != null) {
@@ -366,6 +323,18 @@ public class BluetoothSettings extends SettingsPreferenceFragment
}
}
public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice,
int bondState) {
// add to "Paired devices" list after remote-initiated pairing
if (mDevicePreferenceMap.get(cachedDevice) == null &&
mScreenType == SCREEN_TYPE_SETTINGS &&
bondState == BluetoothDevice.BOND_BONDED) {
if (addDevicePreference(cachedDevice)) {
createDevicePreference(cachedDevice);
}
}
}
private boolean addDevicePreference(CachedBluetoothDevice cachedDevice) {
ParcelUuid[] uuids = cachedDevice.getDevice().getUuids();
BluetoothClass bluetoothClass = cachedDevice.getDevice().getBluetoothClass();
@@ -532,4 +501,3 @@ public class BluetoothSettings extends SettingsPreferenceFragment
}
}
}

View File

@@ -36,12 +36,13 @@ 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 java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* CachedBluetoothDevice represents a remote Bluetooth device. It contains
@@ -55,11 +56,6 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
private static final boolean V = LocalBluetoothManager.V;
private static final boolean DEBUG = false;
private static final int CONTEXT_ITEM_CONNECT = Menu.FIRST + 1;
private static final int CONTEXT_ITEM_DISCONNECT = Menu.FIRST + 2;
private static final int CONTEXT_ITEM_UNPAIR = Menu.FIRST + 3;
private static final int CONTEXT_ITEM_CONNECT_ADVANCED = Menu.FIRST + 4;
public static final int PAN_PROFILE = 1;
public static final int OTHER_PROFILES = 2;
@@ -331,7 +327,7 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
if (isConnectableProfile(profile)) {
LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager
.getProfileManager(mLocalManager, profile);
profileManager.setPreferred(mDevice, false);
profileManager.setPreferred(mDevice, true);
disconnectConnected(this, profile);
connectInt(this, profile);
}
@@ -458,10 +454,12 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
public void setName(String name) {
if (!mName.equals(name)) {
if (TextUtils.isEmpty(name)) {
// TODO: use friendly name for unknown device (bug 1181856)
mName = mDevice.getAddress();
} else {
mName = name;
}
// TODO: save custom device name in preferences
dispatchAttributesChanged();
}
}
@@ -523,6 +521,16 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
return false;
}
public boolean isConnectedProfile(Profile profile) {
int status = LocalBluetoothProfileManager.getProfileManager(mLocalManager, profile)
.getConnectionStatus(mDevice);
if (SettingsBtStatus.isConnectionStatusConnected(status)) {
return true;
}
return false;
}
public boolean isBusy() {
for (Profile profile : mProfiles) {
int status = LocalBluetoothProfileManager.getProfileManager(mLocalManager, profile)
@@ -653,13 +661,7 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
}
}
public int getSummary(int accessibleProfile) {
// TODO: clean up
int oneOffSummary = getOneOffSummary(accessibleProfile);
if (oneOffSummary != 0) {
return oneOffSummary;
}
public int getSummary() {
for (Profile profile : mProfiles) {
LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager
.getProfileManager(mLocalManager, profile);
@@ -675,83 +677,20 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
return SettingsBtStatus.getPairingStatusSummary(getBondState());
}
public List<Drawable> getProfileIcons() {
ArrayList<Drawable> drawables = new ArrayList<Drawable>();
public Map<Profile, Drawable> getProfileIcons() {
Map<Profile, Drawable> drawables = new HashMap<Profile, Drawable>();
for (Profile profile : mProfiles) {
LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager
.getProfileManager(mLocalManager, profile);
int iconResource = profileManager.getDrawableResource();
if (iconResource != 0) {
drawables.add(mContext.getResources().getDrawable(iconResource));
drawables.put(profile, 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.
*
* @return A one-off summary that is applicable for the current state, or 0.
*/
private int getOneOffSummary(int accessibleProfile) {
boolean isA2dpConnected = false;
boolean isHeadsetConnected = false;
boolean isHidConnected = false;
boolean isPanConnected = false;
boolean isConnecting = false;
if (accessibleProfile == OTHER_PROFILES) {
if (mProfiles.contains(Profile.A2DP)) {
LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager
.getProfileManager(mLocalManager, Profile.A2DP);
isConnecting = profileManager.getConnectionStatus(mDevice) ==
SettingsBtStatus.CONNECTION_STATUS_CONNECTING;
isA2dpConnected = profileManager.isConnected(mDevice);
}
if (mProfiles.contains(Profile.HEADSET)) {
LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager
.getProfileManager(mLocalManager, Profile.HEADSET);
isConnecting |= profileManager.getConnectionStatus(mDevice) ==
SettingsBtStatus.CONNECTION_STATUS_CONNECTING;
isHeadsetConnected = profileManager.isConnected(mDevice);
}
if (mProfiles.contains(Profile.HID)) {
LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager
.getProfileManager(mLocalManager, Profile.HID);
isConnecting |= profileManager.getConnectionStatus(mDevice) ==
SettingsBtStatus.CONNECTION_STATUS_CONNECTING;
isHidConnected = profileManager.isConnected(mDevice);
}
} else if (accessibleProfile == PAN_PROFILE && mProfiles.contains(Profile.PAN)) {
LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager
.getProfileManager(mLocalManager, Profile.PAN);
isConnecting |= profileManager.getConnectionStatus(mDevice) ==
SettingsBtStatus.CONNECTION_STATUS_CONNECTING;
isPanConnected = profileManager.isConnected(mDevice);
}
if (isConnecting) {
// If any of these important profiles is connecting, prefer that
return SettingsBtStatus.getConnectionStatusSummary(
SettingsBtStatus.CONNECTION_STATUS_CONNECTING);
} else if (isA2dpConnected && isHeadsetConnected) {
return R.string.bluetooth_summary_connected_to_a2dp_headset;
} else if (isA2dpConnected) {
return R.string.bluetooth_summary_connected_to_a2dp;
} else if (isHeadsetConnected) {
return R.string.bluetooth_summary_connected_to_headset;
} else if (isHidConnected) {
return R.string.bluetooth_summary_connected_to_hid;
} else if (isPanConnected) {
return R.string.bluetooth_summary_connected_to_pan;
} else {
return 0;
}
}
public List<Profile> getConnectableProfiles() {
ArrayList<Profile> connectableProfiles = new ArrayList<Profile>();
@@ -768,73 +707,6 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
profile.equals(Profile.HID);
}
public void onCreateContextMenu(ContextMenu menu) {
// No context menu if it is busy (none of these items are applicable if busy)
if (mLocalManager.getBluetoothState() != BluetoothAdapter.STATE_ON || isBusy()) {
return;
}
int bondState = getBondState();
boolean isConnected = isConnected();
boolean hasConnectableProfiles = false;
for (Profile profile : mProfiles) {
if (isConnectableProfile(profile)) {
hasConnectableProfiles = true;
break;
}
}
menu.setHeaderTitle(getName());
if (bondState == BluetoothDevice.BOND_NONE) { // Not paired and not connected
menu.add(0, CONTEXT_ITEM_CONNECT, 0, R.string.bluetooth_device_context_pair_connect);
} else { // Paired
if (isConnected) { // Paired and connected
menu.add(0, CONTEXT_ITEM_DISCONNECT, 0,
R.string.bluetooth_device_context_disconnect);
menu.add(0, CONTEXT_ITEM_UNPAIR, 0,
R.string.bluetooth_device_context_disconnect_unpair);
} else { // Paired but not connected
if (hasConnectableProfiles) {
menu.add(0, CONTEXT_ITEM_CONNECT, 0, R.string.bluetooth_device_context_connect);
}
menu.add(0, CONTEXT_ITEM_UNPAIR, 0, R.string.bluetooth_device_context_unpair);
}
// Show the connection options item
if (hasConnectableProfiles) {
menu.add(0, CONTEXT_ITEM_CONNECT_ADVANCED, 0,
R.string.bluetooth_device_context_connect_advanced);
}
}
}
/**
* Called when a context menu item is clicked.
*
* @param item The item that was clicked.
*/
public void onContextItemSelected(MenuItem item, SettingsPreferenceFragment fragment) {
switch (item.getItemId()) {
case CONTEXT_ITEM_DISCONNECT:
disconnect();
break;
case CONTEXT_ITEM_CONNECT:
connect();
break;
case CONTEXT_ITEM_UNPAIR:
unpair();
break;
case CONTEXT_ITEM_CONNECT_ADVANCED:
onClickedAdvancedOptions(fragment);
break;
}
}
public void onClickedAdvancedOptions(SettingsPreferenceFragment fragment) {
// TODO: Verify if there really is a case when there's no foreground
// activity
@@ -873,7 +745,7 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
private void dispatchAttributesChanged() {
synchronized (mCallbacks) {
for (Callback callback : mCallbacks) {
callback.onDeviceAttributesChanged(this);
callback.onDeviceAttributesChanged();
}
}
}
@@ -922,6 +794,6 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
}
public interface Callback {
void onDeviceAttributesChanged(CachedBluetoothDevice cachedDevice);
void onDeviceAttributesChanged();
}
}

View File

@@ -165,6 +165,15 @@ public class CachedBluetoothDeviceManager {
}
}
private void dispatchDeviceBondStateChanged(
CachedBluetoothDevice cachedDevice, int bondState) {
synchronized (mCallbacks) {
for (Callback callback : mCallbacks) {
callback.onDeviceBondStateChanged(cachedDevice, bondState);
}
}
}
public synchronized void onBondingStateChanged(BluetoothDevice device, int bondState) {
CachedBluetoothDevice cachedDevice = findDevice(device);
if (cachedDevice == null) {
@@ -176,11 +185,12 @@ public class CachedBluetoothDeviceManager {
cachedDevice = findDevice(device);
if (cachedDevice == null) {
Log.e(TAG, "Got bonding state changed for " + device +
"but device not added in cache");
", but device not added in cache.");
return;
}
}
dispatchDeviceBondStateChanged(cachedDevice, bondState);
cachedDevice.onBondingStateChanged(bondState);
}

View File

@@ -0,0 +1,35 @@
/*
* 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.R;
import android.app.Activity;
import android.os.Bundle;
/**
* Activity for Bluetooth device picker dialog. The device picker logic
* is implemented in the {@link BluetoothSettings} fragment.
*/
public class DevicePickerActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.bluetooth_device_picker);
}
}

View File

@@ -20,7 +20,9 @@ import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.bluetooth.LocalBluetoothProfileManager.Profile;
import android.app.FragmentTransaction;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.EditTextPreference;
@@ -49,8 +51,6 @@ public class DeviceProfilesSettings extends SettingsPreferenceFragment
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";
private LocalBluetoothManager mManager;
@@ -92,10 +92,12 @@ public class DeviceProfilesSettings extends SettingsPreferenceFragment
mProfileContainer = (PreferenceGroup) findPreference(KEY_PROFILE_CONTAINER);
mAllowIncomingPref = (CheckBoxPreference) findPreference(KEY_ALLOW_INCOMING);
mAllowIncomingPref.setChecked(isIncomingFileTransfersAllowed());
mAllowIncomingPref.setOnPreferenceChangeListener(this);
mDeviceNamePref = (EditTextPreference) findPreference(KEY_RENAME_DEVICE);
mDeviceNamePref.setSummary(mCachedDevice.getName());
mDeviceNamePref.setText(mCachedDevice.getName());
mDeviceNamePref.setOnPreferenceChangeListener(this);
// Set the title of the screen
findPreference(KEY_TITLE).setTitle(getResources()
@@ -181,10 +183,17 @@ public class DeviceProfilesSettings extends SettingsPreferenceFragment
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (preference == mAllowIncomingPref) {
setIncomingFileTransfersAllowed(mAllowIncomingPref.isChecked());
setIncomingFileTransfersAllowed((Boolean) newValue);
} else if (preference == mDeviceNamePref) {
// TODO: Verify and check for error conditions
mCachedDevice.setName(mDeviceNamePref.getText());
mCachedDevice.setName((String) newValue);
} else if (preference instanceof CheckBoxPreference) {
boolean autoConnect = (Boolean) newValue;
Profile prof = getProfileOf(preference);
LocalBluetoothProfileManager
.getProfileManager(mManager, prof)
.setPreferred(mCachedDevice.getDevice(),
autoConnect);
return true;
} else {
return false;
}
@@ -201,10 +210,6 @@ public class DeviceProfilesSettings extends SettingsPreferenceFragment
boolean isConnected =
SettingsBtStatus.isConnectionStatusConnected(status);
// TODO: only change the preference on disconnect if user confirms
// TODO: add method to change priority of individual profiles
// profileManager.setPreferred(device, !isConnected);
if (isConnected) {
mCachedDevice.askDisconnect(profile);
} else {
@@ -212,11 +217,24 @@ public class DeviceProfilesSettings extends SettingsPreferenceFragment
}
}
public void onDeviceAttributesChanged(CachedBluetoothDevice cachedDevice) {
public void onDeviceAttributesChanged() {
refresh();
}
private void refresh() {
String deviceName = mCachedDevice.getName();
// TODO: figure out how to update "bread crumb" title in action bar
// FragmentTransaction transaction = getFragmentManager().openTransaction();
// transaction.setBreadCrumbTitle(deviceName);
// transaction.commit();
findPreference(KEY_TITLE).setTitle(getResources().getString(
R.string.bluetooth_device_advanced_title,
deviceName));
mDeviceNamePref = (EditTextPreference) findPreference(KEY_RENAME_DEVICE);
mDeviceNamePref.setSummary(deviceName);
mDeviceNamePref.setText(deviceName);
refreshProfiles();
}
@@ -296,10 +314,11 @@ public class DeviceProfilesSettings extends SettingsPreferenceFragment
if (autoConnectPref == null) {
autoConnectPref = new CheckBoxPreference(getActivity());
autoConnectPref.setLayoutResource(com.android.internal.R.layout.preference_child);
autoConnectPref.setKey(prof.toString() + AUTO_CONNECT_KEY_SUFFIX);
autoConnectPref.setKey(prof.toString());
autoConnectPref.setTitle(getCheckBoxTitle(prof));
autoConnectPref.setOrder(getProfilePreferenceIndex(prof) + 1);
autoConnectPref.setChecked(getAutoConnect(prof));
autoConnectPref.setOnPreferenceChangeListener(this);
mAutoConnectPrefs.put(prof.name(), autoConnectPref);
}
BluetoothProfilePreference profilePref =
@@ -328,12 +347,12 @@ public class DeviceProfilesSettings extends SettingsPreferenceFragment
}
private void setIncomingFileTransfersAllowed(boolean allow) {
// TODO:
// TODO: make an IPC call into BluetoothOpp to update
Log.d(TAG, "Set allow incoming = " + allow);
}
private boolean isIncomingFileTransfersAllowed() {
// TODO:
// TODO: get this value from BluetoothOpp ???
return true;
}
@@ -343,7 +362,7 @@ public class DeviceProfilesSettings extends SettingsPreferenceFragment
}
private boolean getAutoConnect(Profile prof) {
// TODO: Get the auto connect toggle state for the profile
return true;
return LocalBluetoothProfileManager.getProfileManager(mManager, prof)
.isPreferred(mCachedDevice.getDevice());
}
}

View File

@@ -84,6 +84,8 @@ public class LocalBluetoothManager {
private long mLastScan;
private LocalBluetoothManager() { }
public static LocalBluetoothManager getInstance(Context context) {
synchronized (LocalBluetoothManager.class) {
if (sInstance == null) {
@@ -316,6 +318,7 @@ public class LocalBluetoothManager {
void onScanningStateChanged(boolean started);
void onDeviceAdded(CachedBluetoothDevice cachedDevice);
void onDeviceDeleted(CachedBluetoothDevice cachedDevice);
void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState);
}
public boolean shouldShowDialogInForeground(String deviceAddress) {

View File

@@ -253,7 +253,6 @@ public abstract class LocalBluetoothProfileManager {
return R.drawable.ic_bt_headphones_a2dp;
}
// TODO: int instead of enum
public static enum Profile {
HEADSET(R.string.bluetooth_profile_headset),
A2DP(R.string.bluetooth_profile_a2dp),