Merge "Fix multiple BT settings bugs."

This commit is contained in:
Jake Hamby
2011-08-08 14:07:34 -07:00
committed by Android (Google) Code Review
18 changed files with 157 additions and 314 deletions

View File

@@ -19,13 +19,6 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center_vertical"> android:gravity="center_vertical">
<LinearLayout android:id="@+id/profileIcons"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_alignParentRight="true"
/>
<!-- Divider --> <!-- Divider -->
<ImageView <ImageView
android:id="@+id/divider" android:id="@+id/divider"

View File

@@ -350,10 +350,10 @@
<!-- Discoverable mode timeout options --> <!-- Discoverable mode timeout options -->
<string-array name="bluetooth_visibility_timeout_entries"> <string-array name="bluetooth_visibility_timeout_entries">
<item>2 Minutes</item> <item>2 minutes</item>
<item>5 Minutes</item> <item>5 minutes</item>
<item>1 Hour</item> <item>1 hour</item>
<item>Never</item> <item>Never time out</item>
</string-array> </string-array>
<!-- Match this with drawable.wifi_signal. --> <skip /> <!-- Match this with drawable.wifi_signal. --> <skip />

View File

@@ -230,10 +230,20 @@
<string name="bluetooth_disconnect_title">Disconnect?</string> <string name="bluetooth_disconnect_title">Disconnect?</string>
<!-- Bluetooth settings. Message for disconnecting from all profiles of a bluetooth device. [CHAR LIMIT=NONE] --> <!-- Bluetooth settings. Message for disconnecting from all profiles of a bluetooth device. [CHAR LIMIT=NONE] -->
<string name="bluetooth_disconnect_all_profiles">This will end your connection with:&lt;br>&lt;b><xliff:g id="device_name">%1$s</xliff:g>&lt;/b></string> <string name="bluetooth_disconnect_all_profiles">This will end your connection with:&lt;br>&lt;b><xliff:g id="device_name">%1$s</xliff:g>&lt;/b></string>
<!-- Bluetooth settings. Message for disconnecting from all profiles of a bluetooth device. [CHAR LIMIT=NONE] -->
<string name="bluetooth_disconnect_blank">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> will be disconnected."</string> <!-- Bluetooth settings. Dialog title to disable a single profile of a device. [CHAR LIMIT=40] -->
<!-- Bluetooth settings. Message when connected to a device --> <string name="bluetooth_disable_profile_title">Disable profile?</string>
<!-- Bluetooth settings. Message for disabling a profile of a bluetooth device. [CHAR LIMIT=NONE] -->
<string name="bluetooth_disable_profile_message">This will disable:&lt;br>&lt;b><xliff:g id="profile_name">%1$s</xliff:g>&lt;/b>&lt;br>&lt;br>From:&lt;br>&lt;b><xliff:g id="device_name">%2$s</xliff:g>&lt;/b></string>
<!-- Bluetooth settings. Message when connected to a device. [CHAR LIMIT=40] -->
<string name="bluetooth_connected">Connected</string> <string name="bluetooth_connected">Connected</string>
<!-- Bluetooth settings. Message when connected to a device, except for phone audio. [CHAR LIMIT=40] -->
<string name="bluetooth_connected_no_headset">Connected (no phone)</string>
<!-- Bluetooth settings. Message when connected to a device, except for media audio. [CHAR LIMIT=40] -->
<string name="bluetooth_connected_no_a2dp">Connected (no media)</string>
<!-- Bluetooth settings. Message when connected to a device, except for phone/media audio. [CHAR LIMIT=40] -->
<string name="bluetooth_connected_no_headset_no_a2dp">Connected (no phone or media)</string>
<!-- Bluetooth settings. Message when a device is disconnected --> <!-- Bluetooth settings. Message when a device is disconnected -->
<string name="bluetooth_disconnected">Disconnected</string> <string name="bluetooth_disconnected">Disconnected</string>
<!-- Bluetooth settings. Message when disconnecting from a device --> <!-- Bluetooth settings. Message when disconnecting from a device -->
@@ -242,12 +252,8 @@
<string name="bluetooth_connecting">Connecting\u2026</string> <string name="bluetooth_connecting">Connecting\u2026</string>
<!-- Bluetooth settings. Message when the device state is unknown --> <!-- Bluetooth settings. Message when the device state is unknown -->
<string name="bluetooth_unknown" /> <string name="bluetooth_unknown" />
<!--Bluetooth settings screen, summary text under individual Bluetooth devices when not paired yet -->
<string name="bluetooth_not_connected">Pair with this device</string>
<!--Bluetooth settings screen, summary text under individual Bluetooth devices when pairing --> <!--Bluetooth settings screen, summary text under individual Bluetooth devices when pairing -->
<string name="bluetooth_pairing">Pairing\u2026</string> <string name="bluetooth_pairing">Pairing\u2026</string>
<!--Bluetooth settings screen, summary text under individual Bluetooth devices when paired with one -->
<string name="bluetooth_paired">Paired but not connected</string>
<!--Bluetooth settings screen, summary text for Bluetooth device with no name --> <!--Bluetooth settings screen, summary text for Bluetooth device with no name -->
<string name="bluetooth_device">Unnamed Bluetooth device</string> <string name="bluetooth_device">Unnamed Bluetooth device</string>
<!--Bluetooth settings screen, text that appears in heading bar when scanning for devices --> <!--Bluetooth settings screen, text that appears in heading bar when scanning for devices -->
@@ -1011,15 +1017,17 @@
<string name="bluetooth_connect_specific_profiles_title">Connect to\u2026</string> <string name="bluetooth_connect_specific_profiles_title">Connect to\u2026</string>
<!-- Bluetooth settings. The user-visible string that is used whenever referring to the A2DP profile. --> <!-- Bluetooth settings. The user-visible string that is used whenever referring to the A2DP profile. -->
<string name="bluetooth_profile_a2dp">Media</string> <string name="bluetooth_profile_a2dp">Media audio</string>
<!-- Bluetooth settings. The user-visible string that is used whenever referring to the headset or handsfree profile. --> <!-- Bluetooth settings. The user-visible string that is used whenever referring to the headset or handsfree profile. -->
<string name="bluetooth_profile_headset">Handsfree</string> <string name="bluetooth_profile_headset">Phone audio</string>
<!-- Bluetooth settings. The user-visible string that is used whenever referring to the OPP profile. --> <!-- Bluetooth settings. The user-visible string that is used whenever referring to the OPP profile. -->
<string name="bluetooth_profile_opp">Transfer</string> <string name="bluetooth_profile_opp">File transfer</string>
<!-- Bluetooth settings. The user-visible string that is used whenever referring to the HID profile. --> <!-- Bluetooth settings. The user-visible string that is used whenever referring to the HID profile. -->
<string name="bluetooth_profile_hid">Input Device</string> <string name="bluetooth_profile_hid">Input device</string>
<!-- Bluetooth settings. The user-visible string that is used whenever referring to the PAN profile. [CHAR LIMIT=25]--> <!-- Bluetooth settings. The user-visible string that is used whenever referring to the PAN profile (accessing Internet through remote device). [CHAR LIMIT=40]-->
<string name="bluetooth_profile_pan">Internet access</string> <string name="bluetooth_profile_pan">Internet access</string>
<!-- Bluetooth settings. The user-visible string that is used whenever referring to the PAN profile (sharing this device's Internet connection). [CHAR LIMIT=40]-->
<string name="bluetooth_profile_pan_nap">Internet connection sharing</string>
<!-- Bluetooth settings. Message for disconnecting from the A2DP profile. [CHAR LIMIT=80] --> <!-- Bluetooth settings. Message for disconnecting from the A2DP profile. [CHAR LIMIT=80] -->
<string name="bluetooth_disconnect_a2dp_profile"><xliff:g id="device_name">%1$s</xliff:g> will be disconnected from media audio.</string> <string name="bluetooth_disconnect_a2dp_profile"><xliff:g id="device_name">%1$s</xliff:g> will be disconnected from media audio.</string>
@@ -1034,10 +1042,8 @@
<!-- Bluetooth settings. Message for disconnecting from the PAN profile (NAP role). [CHAR LIMIT=80] --> <!-- Bluetooth settings. Message for disconnecting from the PAN profile (NAP role). [CHAR LIMIT=80] -->
<string name="bluetooth_disconnect_pan_nap_profile" product="default"><xliff:g id="device_name">%1$s</xliff:g> will be disconnected from sharing this phone\'s Internet connection.</string> <string name="bluetooth_disconnect_pan_nap_profile" product="default"><xliff:g id="device_name">%1$s</xliff:g> will be disconnected from sharing this phone\'s Internet connection.</string>
<!-- Bluetooth settings. Connection options screen. The title of the screen. --> <!-- Bluetooth settings. Connection options screen. The title of the screen. [CHAR LIMIT=40] -->
<string name="bluetooth_device_advanced_title"><xliff:g id="device_name">%1$s</xliff:g> options</string> <string name="bluetooth_device_advanced_title">Paired Bluetooth device</string>
<!-- Bluetooth settings. Connection options screen. Title of device actions section. [CHAR LIMIT=30] -->
<string name="bluetooth_device_advanced_device_actions_title">Device actions</string>
<!-- Bluetooth settings. Connection options screen. The title of the checkbox that controls whether the device is in "online" mode or "offline" mode. This essentially is the checkbox that controls whether any checks / unchecks on a profile should be applied immediately, or next time the device is connected. --> <!-- Bluetooth settings. Connection options screen. The title of the checkbox that controls whether the device is in "online" mode or "offline" mode. This essentially is the checkbox that controls whether any checks / unchecks on a profile should be applied immediately, or next time the device is connected. -->
<string name="bluetooth_device_advanced_online_mode_title">Connect</string> <string name="bluetooth_device_advanced_online_mode_title">Connect</string>
<!-- Bluetooth settings. Connection options screen. The summary of the online mode checkbox. This describes what the setting does in the context of the screen. --> <!-- Bluetooth settings. Connection options screen. The summary of the online mode checkbox. This describes what the setting does in the context of the screen. -->
@@ -1045,7 +1051,7 @@
<!-- Bluetooth settings. Connection options screen. The title of the header that is above all of the profiles. --> <!-- Bluetooth settings. Connection options screen. The title of the header that is above all of the profiles. -->
<string name="bluetooth_device_advanced_profile_header_title">Profiles</string> <string name="bluetooth_device_advanced_profile_header_title">Profiles</string>
<!-- Bluetooth settings. Connection options screen. Title for option to rename the device. [CHAR LIMIT=30] --> <!-- Bluetooth settings. Connection options screen. Title for option to rename the device. [CHAR LIMIT=30] -->
<string name="bluetooth_device_advanced_rename_device">Rename device</string> <string name="bluetooth_device_advanced_rename_device">Rename</string>
<!-- Bluetooth settings. Connection options screen. Title for checkbox to enable incoming file transfers [CHAR LIMIT=30] --> <!-- Bluetooth settings. Connection options screen. Title for checkbox to enable incoming file transfers [CHAR LIMIT=30] -->
<string name="bluetooth_device_advanced_enable_opp_title">Allow incoming file transfers</string> <string name="bluetooth_device_advanced_enable_opp_title">Allow incoming file transfers</string>
<!-- Bluetooth settings. Connection options screen. The summary for the A2DP checkbox preference when A2DP is connected. --> <!-- Bluetooth settings. Connection options screen. The summary for the A2DP checkbox preference when A2DP is connected. -->

View File

@@ -15,12 +15,8 @@
--> -->
<PreferenceScreen <PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"> xmlns:android="http://schemas.android.com/apk/res/android"
android:title="@string/bluetooth_device_advanced_title">
<PreferenceCategory
android:key="title"
android:order="10"
android:title="@string/bluetooth_device_advanced_device_actions_title" />
<EditTextPreference <EditTextPreference
android:key="rename_device" android:key="rename_device"

View File

@@ -138,14 +138,10 @@ final class A2dpProfile implements LocalBluetoothProfile {
return ORDINAL; return ORDINAL;
} }
public int getNameResource() { public int getNameResource(BluetoothDevice device) {
return R.string.bluetooth_profile_a2dp; return R.string.bluetooth_profile_a2dp;
} }
public int getDisconnectResource(BluetoothDevice device) {
return R.string.bluetooth_disconnect_a2dp_profile;
}
public int getSummaryResourceForDevice(BluetoothDevice device) { public int getSummaryResourceForDevice(BluetoothDevice device) {
int state = mService.getConnectionState(device); int state = mService.getConnectionState(device);
switch (state) { switch (state) {

View File

@@ -65,7 +65,9 @@ public final class BluetoothDevicePreference extends Preference implements
mCachedDevice = cachedDevice; mCachedDevice = cachedDevice;
setWidgetLayoutResource(R.layout.preference_bluetooth); if (cachedDevice.getBondState() == BluetoothDevice.BOND_BONDED) {
setWidgetLayoutResource(R.layout.preference_bluetooth);
}
mCachedDevice.registerCallback(this); mCachedDevice.registerCallback(this);
@@ -98,7 +100,17 @@ public final class BluetoothDevicePreference extends Preference implements
*/ */
setTitle(mCachedDevice.getName()); setTitle(mCachedDevice.getName());
setSummary(getConnectionSummary()); int summaryResId = getConnectionSummary();
if (summaryResId != 0) {
setSummary(summaryResId);
} else {
setSummary(null); // empty summary for unpaired devices
}
int iconResId = getBtClassDrawable();
if (iconResId != 0) {
setIcon(iconResId);
}
// Used to gray out the item // Used to gray out the item
setEnabled(!mCachedDevice.isBusy()); setEnabled(!mCachedDevice.isBusy());
@@ -114,40 +126,16 @@ public final class BluetoothDevicePreference extends Preference implements
setDependency("bt_checkbox"); setDependency("bt_checkbox");
} }
if (mCachedDevice.getBondState() == BluetoothDevice.BOND_BONDED) {
ImageView deviceDetails = (ImageView) view.findViewById(R.id.deviceDetails);
if (deviceDetails != null) {
deviceDetails.setOnClickListener(this);
deviceDetails.setTag(mCachedDevice);
deviceDetails.setAlpha(isEnabled() ? 255 : sDimAlpha);
}
}
super.onBindView(view); super.onBindView(view);
ImageView btClass = (ImageView) view.findViewById(android.R.id.icon);
btClass.setImageResource(getBtClassDrawable());
btClass.setAlpha(isEnabled() ? 255 : sDimAlpha);
btClass.setVisibility(View.VISIBLE);
ImageView deviceDetails = (ImageView) view.findViewById(R.id.deviceDetails);
if (mOnSettingsClickListener != null) {
deviceDetails.setOnClickListener(this);
deviceDetails.setTag(mCachedDevice);
deviceDetails.setAlpha(isEnabled() ? 255 : sDimAlpha);
} else { // Hide the settings icon and divider
deviceDetails.setVisibility(View.GONE);
View divider = 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 (LocalBluetoothProfile profile : mCachedDevice.getProfiles()) {
int iconResource = profile.getDrawableResource(mCachedDevice.getBtClass());
if (iconResource != 0) {
Drawable icon = getContext().getResources().getDrawable(iconResource);
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);
}
}
} }
public void onClick(View v) { public void onClick(View v) {
@@ -224,22 +212,52 @@ public final class BluetoothDevicePreference extends Preference implements
private int getConnectionSummary() { private int getConnectionSummary() {
final CachedBluetoothDevice cachedDevice = mCachedDevice; final CachedBluetoothDevice cachedDevice = mCachedDevice;
// if any profiles are connected or busy, return that status boolean profileConnected = false; // at least one profile is connected
boolean a2dpNotConnected = false; // A2DP is preferred but not connected
boolean headsetNotConnected = false; // Headset is preferred but not connected
for (LocalBluetoothProfile profile : cachedDevice.getProfiles()) { for (LocalBluetoothProfile profile : cachedDevice.getProfiles()) {
int connectionStatus = cachedDevice.getProfileConnectionState(profile); int connectionStatus = cachedDevice.getProfileConnectionState(profile);
if (connectionStatus != BluetoothProfile.STATE_DISCONNECTED) { switch (connectionStatus) {
return Utils.getConnectionStateSummary(connectionStatus); case BluetoothProfile.STATE_CONNECTING:
case BluetoothProfile.STATE_DISCONNECTING:
return Utils.getConnectionStateSummary(connectionStatus);
case BluetoothProfile.STATE_CONNECTED:
profileConnected = true;
break;
case BluetoothProfile.STATE_DISCONNECTED:
if (profile.isProfileReady() && profile.isPreferred(cachedDevice.getDevice())) {
if (profile instanceof A2dpProfile) {
a2dpNotConnected = true;
} else if (profile instanceof HeadsetProfile) {
headsetNotConnected = true;
}
}
break;
}
}
if (profileConnected) {
if (a2dpNotConnected && headsetNotConnected) {
return R.string.bluetooth_connected_no_headset_no_a2dp;
} else if (a2dpNotConnected) {
return R.string.bluetooth_connected_no_a2dp;
} else if (headsetNotConnected) {
return R.string.bluetooth_connected_no_headset;
} else {
return R.string.bluetooth_connected;
} }
} }
switch (cachedDevice.getBondState()) { switch (cachedDevice.getBondState()) {
case BluetoothDevice.BOND_BONDED:
return R.string.bluetooth_paired;
case BluetoothDevice.BOND_BONDING: case BluetoothDevice.BOND_BONDING:
return R.string.bluetooth_pairing; return R.string.bluetooth_pairing;
case BluetoothDevice.BOND_BONDED:
case BluetoothDevice.BOND_NONE: case BluetoothDevice.BOND_NONE:
return R.string.bluetooth_not_connected;
default: default:
return 0; return 0;
} }

View File

@@ -225,7 +225,7 @@ final class BluetoothEventManager {
Log.w(TAG, "received ACTION_DISAPPEARED for an unknown device: " + device); Log.w(TAG, "received ACTION_DISAPPEARED for an unknown device: " + device);
return; return;
} }
if (mDeviceManager.onDeviceDisappeared(cachedDevice)) { if (CachedBluetoothDeviceManager.onDeviceDisappeared(cachedDevice)) {
synchronized (mCallbacks) { synchronized (mCallbacks) {
for (BluetoothCallback callback : mCallbacks) { for (BluetoothCallback callback : mCallbacks) {
callback.onDeviceDeleted(cachedDevice); callback.onDeviceDeleted(cachedDevice);
@@ -283,7 +283,7 @@ final class BluetoothEventManager {
// if the device is undocked, remove it from the list as well // if the device is undocked, remove it from the list as well
if (!device.getAddress().equals(getDockedDeviceAddress(context))) { if (!device.getAddress().equals(getDockedDeviceAddress(context))) {
mDeviceManager.onDeviceDisappeared(cachedDevice); cachedDevice.setVisible(false);
} }
} }
int reason = intent.getIntExtra(BluetoothDevice.EXTRA_REASON, int reason = intent.getIntExtra(BluetoothDevice.EXTRA_REASON,
@@ -361,7 +361,7 @@ final class BluetoothEventManager {
if (device != null && device.getBondState() == BluetoothDevice.BOND_NONE) { if (device != null && device.getBondState() == BluetoothDevice.BOND_NONE) {
CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device); CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
if (cachedDevice != null) { if (cachedDevice != null) {
mDeviceManager.onDeviceDisappeared(cachedDevice); cachedDevice.setVisible(false);
} }
} }
} }

View File

@@ -1,96 +0,0 @@
/*
* 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 android.content.Context;
import android.graphics.drawable.Drawable;
import android.preference.Preference;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import com.android.settings.R;
/**
* BluetoothProfilePreference is the preference type used to display each profile for a
* particular bluetooth device.
*/
final class BluetoothProfilePreference extends Preference implements OnClickListener {
// private static final String TAG = "BluetoothProfilePreference";
private Drawable mProfileDrawable;
private boolean mExpanded;
private ImageView mProfileExpandView;
private final LocalBluetoothProfile mProfile;
private OnClickListener mOnExpandClickListener;
BluetoothProfilePreference(Context context, LocalBluetoothProfile profile) {
super(context);
mProfile = profile;
setWidgetLayoutResource(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(android.R.id.icon);
btProfile.setImageDrawable(mProfileDrawable);
mProfileExpandView = (ImageView) view.findViewById(R.id.profileExpand);
if (mProfile.isAutoConnectable()) {
mProfileExpandView.setOnClickListener(this);
mProfileExpandView.setTag(mProfile);
mProfileExpandView.setImageResource(mExpanded
? com.android.internal.R.drawable.expander_close_holo_dark
: com.android.internal.R.drawable.expander_open_holo_dark);
} else {
mProfileExpandView.setVisibility(View.GONE);
}
}
public void onClick(View v) {
if (v == mProfileExpandView) {
if (mOnExpandClickListener != null) {
setExpanded(!mExpanded);
mOnExpandClickListener.onClick(v);
}
}
}
}

View File

@@ -142,9 +142,11 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment {
@Override @Override
public void onResume() { public void onResume() {
// resume BluetoothEnabler before calling super.onResume() so we don't get
// any onDeviceAdded() callbacks before setting up view in updateContent()
mBluetoothEnabler.resume();
super.onResume(); super.onResume();
mBluetoothEnabler.resume();
if (mDiscoverableEnabler != null) { if (mDiscoverableEnabler != null) {
mDiscoverableEnabler.resume(); mDiscoverableEnabler.resume();
} }
@@ -246,6 +248,11 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment {
mMyDevicePreference = new Preference(getActivity()); mMyDevicePreference = new Preference(getActivity());
} }
mMyDevicePreference.setTitle(mLocalAdapter.getName()); mMyDevicePreference.setTitle(mLocalAdapter.getName());
if (getResources().getBoolean(com.android.internal.R.bool.config_voice_capable)) {
mMyDevicePreference.setIcon(R.drawable.ic_bt_cellphone); // for phones
} else {
mMyDevicePreference.setIcon(R.drawable.ic_bt_laptop); // for tablets, etc.
}
mMyDevicePreference.setPersistent(false); mMyDevicePreference.setPersistent(false);
mMyDevicePreference.setEnabled(true); mMyDevicePreference.setEnabled(true);
preferenceScreen.addPreference(mMyDevicePreference); preferenceScreen.addPreference(mMyDevicePreference);
@@ -337,13 +344,12 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment {
if (v.getTag() instanceof CachedBluetoothDevice) { if (v.getTag() instanceof CachedBluetoothDevice) {
CachedBluetoothDevice device = (CachedBluetoothDevice) v.getTag(); CachedBluetoothDevice device = (CachedBluetoothDevice) v.getTag();
Preference pref = new Preference(getActivity()); Bundle args = new Bundle(1);
pref.setTitle(device.getName()); args.putParcelable(DeviceProfilesSettings.EXTRA_DEVICE, device.getDevice());
pref.setFragment(DeviceProfilesSettings.class.getName());
pref.getExtras().putParcelable(DeviceProfilesSettings.EXTRA_DEVICE, ((PreferenceActivity) getActivity()).startPreferencePanel(
device.getDevice()); DeviceProfilesSettings.class.getName(), args,
((PreferenceActivity) getActivity()).onPreferenceStartFragment( R.string.bluetooth_device_advanced_title, null, null, 0);
BluetoothSettings.this, pref);
} else { } else {
Log.w(TAG, "onClick() called for other View: " + v); // TODO remove Log.w(TAG, "onClick() called for other View: " + v); // TODO remove
} }

View File

@@ -53,7 +53,6 @@ final class BluetoothVisibilityTimeoutFragment extends DialogFragment
@Override @Override
public Dialog onCreateDialog(Bundle savedInstanceState) { public Dialog onCreateDialog(Bundle savedInstanceState) {
return new AlertDialog.Builder(getActivity()) return new AlertDialog.Builder(getActivity())
.setIcon(android.R.drawable.ic_dialog_info)
.setTitle(R.string.bluetooth_visibility_timeout) .setTitle(R.string.bluetooth_visibility_timeout)
.setSingleChoiceItems(R.array.bluetooth_visibility_timeout_entries, .setSingleChoiceItems(R.array.bluetooth_visibility_timeout_entries,
mDiscoverableEnabler.getDiscoverableTimeoutIndex(), this) mDiscoverableEnabler.getDiscoverableTimeoutIndex(), this)

View File

@@ -26,7 +26,6 @@ import java.util.List;
* CachedBluetoothDeviceManager manages the set of remote Bluetooth devices. * CachedBluetoothDeviceManager manages the set of remote Bluetooth devices.
*/ */
final class CachedBluetoothDeviceManager { final class CachedBluetoothDeviceManager {
// private static final String TAG = "CachedBluetoothDeviceManager";
private final List<CachedBluetoothDevice> mCachedDevices = private final List<CachedBluetoothDevice> mCachedDevices =
new ArrayList<CachedBluetoothDevice>(); new ArrayList<CachedBluetoothDevice>();
@@ -35,20 +34,9 @@ final class CachedBluetoothDeviceManager {
return new ArrayList<CachedBluetoothDevice>(mCachedDevices); return new ArrayList<CachedBluetoothDevice>(mCachedDevices);
} }
public boolean onDeviceDisappeared(CachedBluetoothDevice cachedDevice) { public static boolean onDeviceDisappeared(CachedBluetoothDevice cachedDevice) {
cachedDevice.setVisible(false); cachedDevice.setVisible(false);
return checkForDeviceRemoval(cachedDevice); return cachedDevice.getBondState() == BluetoothDevice.BOND_NONE;
}
private boolean checkForDeviceRemoval(
CachedBluetoothDevice cachedDevice) {
if (cachedDevice.getBondState() == BluetoothDevice.BOND_NONE &&
!cachedDevice.isVisible()) {
// If device isn't paired, remove it altogether
mCachedDevices.remove(cachedDevice);
return true; // dispatch device deleted
}
return false;
} }
public void onDeviceNameUpdated(BluetoothDevice device) { public void onDeviceNameUpdated(BluetoothDevice device) {
@@ -120,7 +108,6 @@ final class CachedBluetoothDeviceManager {
for (int i = mCachedDevices.size() - 1; i >= 0; i--) { for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
CachedBluetoothDevice cachedDevice = mCachedDevices.get(i); CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
cachedDevice.setVisible(false); cachedDevice.setVisible(false);
checkForDeviceRemoval(cachedDevice);
} }
} }

View File

@@ -128,7 +128,6 @@ public abstract class DeviceListPreferenceFragment extends
@Override @Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
Preference preference) { Preference preference) {
if (KEY_BT_SCAN.equals(preference.getKey())) { if (KEY_BT_SCAN.equals(preference.getKey())) {
mLocalAdapter.startScanning(true); mLocalAdapter.startScanning(true);
return true; return true;

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2008 The Android Open Source Project * Copyright (C) 2011 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -27,6 +27,7 @@ import android.preference.EditTextPreference;
import android.preference.Preference; import android.preference.Preference;
import android.preference.PreferenceGroup; import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen; import android.preference.PreferenceScreen;
import android.text.Html;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
@@ -46,15 +47,12 @@ import java.util.HashMap;
* (or disconnected). * (or disconnected).
*/ */
public final class DeviceProfilesSettings extends SettingsPreferenceFragment public final class DeviceProfilesSettings extends SettingsPreferenceFragment
implements CachedBluetoothDevice.Callback, Preference.OnPreferenceChangeListener, implements CachedBluetoothDevice.Callback, Preference.OnPreferenceChangeListener {
View.OnClickListener {
private static final String TAG = "DeviceProfilesSettings"; private static final String TAG = "DeviceProfilesSettings";
private static final String KEY_TITLE = "title";
private static final String KEY_RENAME_DEVICE = "rename_device"; private static final String KEY_RENAME_DEVICE = "rename_device";
private static final String KEY_PROFILE_CONTAINER = "profile_container"; private static final String KEY_PROFILE_CONTAINER = "profile_container";
private static final String KEY_UNPAIR = "unpair"; private static final String KEY_UNPAIR = "unpair";
//private static final String KEY_ALLOW_INCOMING = "allow_incoming";
public static final String EXTRA_DEVICE = "device"; public static final String EXTRA_DEVICE = "device";
private RenameEditTextPreference mRenameDeviceNamePref; private RenameEditTextPreference mRenameDeviceNamePref;
@@ -69,6 +67,8 @@ public final class DeviceProfilesSettings extends SettingsPreferenceFragment
= new HashMap<LocalBluetoothProfile, CheckBoxPreference>(); = new HashMap<LocalBluetoothProfile, CheckBoxPreference>();
private AlertDialog mDisconnectDialog; private AlertDialog mDisconnectDialog;
private boolean mProfileGroupIsRemoved;
private class RenameEditTextPreference implements TextWatcher{ private class RenameEditTextPreference implements TextWatcher{
public void afterTextChanged(Editable s) { public void afterTextChanged(Editable s) {
Dialog d = mDeviceNamePref.getDialog(); Dialog d = mDeviceNamePref.getDialog();
@@ -87,6 +87,7 @@ public final class DeviceProfilesSettings extends SettingsPreferenceFragment
// not used // not used
} }
} }
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@@ -126,11 +127,6 @@ public final class DeviceProfilesSettings extends SettingsPreferenceFragment
mDeviceNamePref.setText(deviceName); mDeviceNamePref.setText(deviceName);
mDeviceNamePref.setOnPreferenceChangeListener(this); mDeviceNamePref.setOnPreferenceChangeListener(this);
// Set the title of the screen
findPreference(KEY_TITLE).setTitle(
getString(R.string.bluetooth_device_advanced_title,
deviceName));
// Add a preference for each profile // Add a preference for each profile
addPreferencesForProfiles(); addPreferencesForProfiles();
} }
@@ -183,6 +179,18 @@ public final class DeviceProfilesSettings extends SettingsPreferenceFragment
Preference pref = createProfilePreference(profile); Preference pref = createProfilePreference(profile);
mProfileContainer.addPreference(pref); mProfileContainer.addPreference(pref);
} }
showOrHideProfileGroup();
}
private void showOrHideProfileGroup() {
int numProfiles = mProfileContainer.getPreferenceCount();
if (!mProfileGroupIsRemoved && numProfiles == 0) {
getPreferenceScreen().removePreference(mProfileContainer);
mProfileGroupIsRemoved = true;
} else if (mProfileGroupIsRemoved && numProfiles != 0) {
getPreferenceScreen().addPreference(mProfileContainer);
mProfileGroupIsRemoved = false;
}
} }
/** /**
@@ -193,18 +201,17 @@ public final class DeviceProfilesSettings extends SettingsPreferenceFragment
* @return A preference that allows the user to choose whether this profile * @return A preference that allows the user to choose whether this profile
* will be connected to. * will be connected to.
*/ */
private Preference createProfilePreference(LocalBluetoothProfile profile) { private CheckBoxPreference createProfilePreference(LocalBluetoothProfile profile) {
BluetoothProfilePreference pref = new BluetoothProfilePreference(getActivity(), profile); CheckBoxPreference pref = new CheckBoxPreference(getActivity());
pref.setKey(profile.toString()); pref.setKey(profile.toString());
pref.setTitle(profile.getNameResource()); pref.setTitle(profile.getNameResource(mCachedDevice.getDevice()));
pref.setExpanded(false);
pref.setPersistent(false); pref.setPersistent(false);
pref.setOrder(getProfilePreferenceIndex(profile.getOrdinal())); pref.setOrder(getProfilePreferenceIndex(profile.getOrdinal()));
pref.setOnExpandClickListener(this); pref.setOnPreferenceChangeListener(this);
int iconResource = profile.getDrawableResource(mCachedDevice.getBtClass()); int iconResource = profile.getDrawableResource(mCachedDevice.getBtClass());
if (iconResource != 0) { if (iconResource != 0) {
pref.setProfileDrawable(getResources().getDrawable(iconResource)); pref.setIcon(getResources().getDrawable(iconResource));
} }
/** /**
@@ -220,10 +227,7 @@ public final class DeviceProfilesSettings extends SettingsPreferenceFragment
@Override @Override
public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) { public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) {
String key = preference.getKey(); String key = preference.getKey();
if (preference instanceof BluetoothProfilePreference) { if (key.equals(KEY_UNPAIR)) {
onProfileClicked(mProfileManager.getProfileByName(key));
return true;
} else if (key.equals(KEY_UNPAIR)) {
unpairDevice(); unpairDevice();
finish(); finish();
return true; return true;
@@ -236,11 +240,9 @@ public final class DeviceProfilesSettings extends SettingsPreferenceFragment
if (preference == mDeviceNamePref) { if (preference == mDeviceNamePref) {
mCachedDevice.setName((String) newValue); mCachedDevice.setName((String) newValue);
} else if (preference instanceof CheckBoxPreference) { } else if (preference instanceof CheckBoxPreference) {
boolean autoConnect = (Boolean) newValue;
LocalBluetoothProfile prof = getProfileOf(preference); LocalBluetoothProfile prof = getProfileOf(preference);
prof.setPreferred(mCachedDevice.getDevice(), onProfileClicked(prof);
autoConnect); return false; // checkbox will update from onDeviceAttributesChanged() callback
return true;
} else { } else {
return false; return false;
} }
@@ -258,6 +260,7 @@ public final class DeviceProfilesSettings extends SettingsPreferenceFragment
if (isConnected) { if (isConnected) {
askDisconnect(getActivity(), profile); askDisconnect(getActivity(), profile);
} else { } else {
profile.setPreferred(device, true);
mCachedDevice.connectProfile(profile); mCachedDevice.connectProfile(profile);
} }
} }
@@ -270,22 +273,23 @@ public final class DeviceProfilesSettings extends SettingsPreferenceFragment
if (TextUtils.isEmpty(name)) { if (TextUtils.isEmpty(name)) {
name = context.getString(R.string.bluetooth_device); name = context.getString(R.string.bluetooth_device);
} }
int disconnectMessage = profile.getDisconnectResource(device.getDevice());
if (disconnectMessage == 0) { String profileName = context.getString(profile.getNameResource(device.getDevice()));
Log.w(TAG, "askDisconnect: unexpected profile " + profile);
disconnectMessage = R.string.bluetooth_disconnect_blank; String title = context.getString(R.string.bluetooth_disable_profile_title);
} String message = context.getString(R.string.bluetooth_disable_profile_message,
String message = context.getString(disconnectMessage, name); profileName, name);
DialogInterface.OnClickListener disconnectListener = DialogInterface.OnClickListener disconnectListener =
new DialogInterface.OnClickListener() { new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
device.disconnect(profile); device.disconnect(profile);
profile.setPreferred(device.getDevice(), false);
} }
}; };
mDisconnectDialog = Utils.showDisconnectDialog(context, mDisconnectDialog = Utils.showDisconnectDialog(context,
mDisconnectDialog, disconnectListener, name, message); mDisconnectDialog, disconnectListener, title, Html.fromHtml(message));
} }
public void onDeviceAttributesChanged() { public void onDeviceAttributesChanged() {
@@ -294,15 +298,6 @@ public final class DeviceProfilesSettings extends SettingsPreferenceFragment
private void refresh() { private void refresh() {
String deviceName = mCachedDevice.getName(); 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(getString(
R.string.bluetooth_device_advanced_title,
deviceName));
mDeviceNamePref = (EditTextPreference) findPreference(KEY_RENAME_DEVICE);
mDeviceNamePref.setSummary(deviceName); mDeviceNamePref.setSummary(deviceName);
mDeviceNamePref.setText(deviceName); mDeviceNamePref.setText(deviceName);
@@ -311,7 +306,7 @@ public final class DeviceProfilesSettings extends SettingsPreferenceFragment
private void refreshProfiles() { private void refreshProfiles() {
for (LocalBluetoothProfile profile : mCachedDevice.getConnectableProfiles()) { for (LocalBluetoothProfile profile : mCachedDevice.getConnectableProfiles()) {
Preference profilePref = findPreference(profile.toString()); CheckBoxPreference profilePref = (CheckBoxPreference)findPreference(profile.toString());
if (profilePref == null) { if (profilePref == null) {
profilePref = createProfilePreference(profile); profilePref = createProfilePreference(profile);
mProfileContainer.addPreference(profilePref); mProfileContainer.addPreference(profilePref);
@@ -326,15 +321,18 @@ public final class DeviceProfilesSettings extends SettingsPreferenceFragment
mProfileContainer.removePreference(profilePref); mProfileContainer.removePreference(profilePref);
} }
} }
showOrHideProfileGroup();
} }
private void refreshProfilePreference(Preference profilePref, LocalBluetoothProfile profile) { private void refreshProfilePreference(CheckBoxPreference profilePref,
LocalBluetoothProfile profile) {
BluetoothDevice device = mCachedDevice.getDevice(); BluetoothDevice device = mCachedDevice.getDevice();
/* /*
* Gray out checkbox while connecting and disconnecting * Gray out checkbox while connecting and disconnecting
*/ */
profilePref.setEnabled(!mCachedDevice.isBusy()); profilePref.setEnabled(!mCachedDevice.isBusy());
profilePref.setChecked(mCachedDevice.isConnectedProfile(profile));
profilePref.setSummary(profile.getSummaryResourceForDevice(device)); profilePref.setSummary(profile.getSummaryResourceForDevice(device));
} }
@@ -352,32 +350,6 @@ public final class DeviceProfilesSettings extends SettingsPreferenceFragment
} }
} }
public void onClick(View v) {
if (v.getTag() instanceof LocalBluetoothProfile) {
LocalBluetoothProfile prof = (LocalBluetoothProfile) v.getTag();
CheckBoxPreference autoConnectPref = mAutoConnectPrefs.get(prof);
if (autoConnectPref == null) {
autoConnectPref = new CheckBoxPreference(getActivity());
autoConnectPref.setLayoutResource(com.android.internal.R.layout.preference_child);
autoConnectPref.setKey(prof.toString());
autoConnectPref.setTitle(R.string.bluetooth_auto_connect);
autoConnectPref.setOrder(getProfilePreferenceIndex(prof.getOrdinal()) + 1);
autoConnectPref.setChecked(getAutoConnect(prof));
autoConnectPref.setOnPreferenceChangeListener(this);
mAutoConnectPrefs.put(prof, autoConnectPref);
}
BluetoothProfilePreference profilePref =
(BluetoothProfilePreference) findPreference(prof.toString());
if (profilePref != null) {
if (profilePref.isExpanded()) {
mProfileContainer.addPreference(autoConnectPref);
} else {
mProfileContainer.removePreference(autoConnectPref);
}
}
}
}
private int getProfilePreferenceIndex(int profIndex) { private int getProfilePreferenceIndex(int profIndex) {
return mProfileContainer.getOrder() + profIndex * 10; return mProfileContainer.getOrder() + profIndex * 10;
} }
@@ -386,18 +358,6 @@ public final class DeviceProfilesSettings extends SettingsPreferenceFragment
mCachedDevice.unpair(); mCachedDevice.unpair();
} }
/*
private void setIncomingFileTransfersAllowed(boolean allow) {
// TODO: make an IPC call into BluetoothOpp to update
Log.d(TAG, "Set allow incoming = " + allow);
}
private boolean isIncomingFileTransfersAllowed() {
// TODO: get this value from BluetoothOpp ???
return true;
}
*/
private boolean getAutoConnect(LocalBluetoothProfile prof) { private boolean getAutoConnect(LocalBluetoothProfile prof) {
return prof.isPreferred(mCachedDevice.getDevice()); return prof.isPreferred(mCachedDevice.getDevice());
} }

View File

@@ -170,14 +170,10 @@ final class HeadsetProfile implements LocalBluetoothProfile {
return ORDINAL; return ORDINAL;
} }
public int getNameResource() { public int getNameResource(BluetoothDevice device) {
return R.string.bluetooth_profile_headset; return R.string.bluetooth_profile_headset;
} }
public int getDisconnectResource(BluetoothDevice device) {
return R.string.bluetooth_disconnect_headset_profile;
}
public int getSummaryResourceForDevice(BluetoothDevice device) { public int getSummaryResourceForDevice(BluetoothDevice device) {
int state = mService.getConnectionState(device); int state = mService.getConnectionState(device);
switch (state) { switch (state) {

View File

@@ -112,14 +112,11 @@ final class HidProfile implements LocalBluetoothProfile {
return ORDINAL; return ORDINAL;
} }
public int getNameResource() { public int getNameResource(BluetoothDevice device) {
// TODO: distinguish between keyboard and mouse?
return R.string.bluetooth_profile_hid; return R.string.bluetooth_profile_hid;
} }
public int getDisconnectResource(BluetoothDevice device) {
return R.string.bluetooth_disconnect_hid_profile;
}
public int getSummaryResourceForDevice(BluetoothDevice device) { public int getSummaryResourceForDevice(BluetoothDevice device) {
int state = mService.getConnectionState(device); int state = mService.getConnectionState(device);
switch (state) { switch (state) {

View File

@@ -54,15 +54,9 @@ interface LocalBluetoothProfile {
/** /**
* Returns the string resource ID for the localized name for this profile. * Returns the string resource ID for the localized name for this profile.
* @param device the Bluetooth device (to distinguish between PAN roles)
*/ */
int getNameResource(); int getNameResource(BluetoothDevice device);
/**
* Returns the string resource ID for the disconnect confirmation text
* for this profile.
* @param device
*/
int getDisconnectResource(BluetoothDevice device);
/** /**
* Returns the string resource ID for the summary text for this profile * Returns the string resource ID for the summary text for this profile

View File

@@ -75,14 +75,10 @@ final class OppProfile implements LocalBluetoothProfile {
return ORDINAL; return ORDINAL;
} }
public int getNameResource() { public int getNameResource(BluetoothDevice device) {
return R.string.bluetooth_profile_opp; return R.string.bluetooth_profile_opp;
} }
public int getDisconnectResource(BluetoothDevice device) {
return 0; // user must use notification to disconnect OPP transfer.
}
public int getSummaryResourceForDevice(BluetoothDevice device) { public int getSummaryResourceForDevice(BluetoothDevice device) {
return 0; // OPP profile not displayed in UI return 0; // OPP profile not displayed in UI
} }

View File

@@ -112,15 +112,11 @@ final class PanProfile implements LocalBluetoothProfile {
return ORDINAL; return ORDINAL;
} }
public int getNameResource() { public int getNameResource(BluetoothDevice device) {
return R.string.bluetooth_profile_pan;
}
public int getDisconnectResource(BluetoothDevice device) {
if (isLocalRoleNap(device)) { if (isLocalRoleNap(device)) {
return R.string.bluetooth_disconnect_pan_nap_profile; return R.string.bluetooth_profile_pan_nap;
} else { } else {
return R.string.bluetooth_disconnect_pan_user_profile; return R.string.bluetooth_profile_pan;
} }
} }