diff --git a/res/values/strings.xml b/res/values/strings.xml index 241022e1b5b..52834142a99 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -764,6 +764,8 @@ Transfer Input Device + + Tethering Connected to media audio @@ -773,6 +775,8 @@ Connected to phone and media audio Connected to input device + + Tethered %1$s options @@ -792,6 +796,8 @@ Not connected to file transfer server Connected to input device + + Tethered Use for media audio @@ -1467,13 +1473,32 @@ Set up voicemail, call forwarding, call waiting, caller ID - Tethering + + USB tethering + Portable hotspot - Tethering & portable hotspot + + Bluetooth tethering + + Tethering + + Tethering & portable hotspot + + Share your phone\'s mobile data connection via USB + Share your phone\'s mobile connection as a portable Wi-Fi hotspot - Share your phone\'s mobile data connection via USB or as a portable Wi-Fi hotspot + + Share your phone\'s mobile connection via Bluetooth + + Share your phone\'s mobile data connection via USB or as a portable Wi-Fi hotspot + + Share your phone\'s mobile data connection via USB or Bluetooth + + Share your phone\'s mobile data connection via Bluetooth or as a portable Wi-Fi hotspot + + Share your phone\'s mobile data connection via USB, Wi-Fi, or Bluetooth USB @@ -1489,7 +1514,26 @@ USB tethering error - + + + Bluetooth tethering + + Bluetooth tethering on, but not connected + + Bluetooth tethering on and connected + + Bluetooth tethering off + + Bluetooth tethering error + + Cannot tether to more than %1$d devices + + %1$s will be untethered. + + Bluetooth tethering settings + Select Bluetooth devices to tether + + Help diff --git a/res/xml/tether_prefs.xml b/res/xml/tether_prefs.xml index 77fc7c6fa4a..95dfaf81c54 100644 --- a/res/xml/tether_prefs.xml +++ b/res/xml/tether_prefs.xml @@ -36,6 +36,21 @@ android:targetClass="com.android.settings.wifi.WifiApSettings" /> + + + + + + diff --git a/res/xml/wireless_settings.xml b/res/xml/wireless_settings.xml index 13b8344ab4d..8573ed07808 100644 --- a/res/xml/wireless_settings.xml +++ b/res/xml/wireless_settings.xml @@ -58,8 +58,8 @@ + android:title="@string/tether_settings_title_all" + android:summary="@string/tether_settings_summary_all"> errored = intent.getStringArrayListExtra( ConnectivityManager.EXTRA_ERRORED_TETHER); - updateState((String[]) available.toArray(), (String[]) active.toArray(), - (String[]) errored.toArray()); + updateState(available.toArray(new String[available.size()]), + active.toArray(new String[active.size()]), + errored.toArray(new String[errored.size()])); } else if (intent.getAction().equals(Intent.ACTION_MEDIA_SHARED) || intent.getAction().equals(Intent.ACTION_MEDIA_UNSHARED)) { updateState(); + } else if (intent.getAction().equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { + updateState(); } } } @@ -170,8 +221,8 @@ public class TetherSettings extends PreferenceActivity { protected void onResume() { super.onResume(); - IntentFilter filter = new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED); mTetherChangeReceiver = new TetherChangeReceiver(); + IntentFilter filter = new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED); Intent intent = registerReceiver(mTetherChangeReceiver, filter); filter = new IntentFilter(); @@ -180,6 +231,10 @@ public class TetherSettings extends PreferenceActivity { filter.addDataScheme("file"); registerReceiver(mTetherChangeReceiver, filter); + filter = new IntentFilter(); + filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); + registerReceiver(mTetherChangeReceiver, filter); + if (intent != null) mTetherChangeReceiver.onReceive(this, intent); mWifiApEnabler.resume(); } @@ -204,6 +259,13 @@ public class TetherSettings extends PreferenceActivity { private void updateState(String[] available, String[] tethered, String[] errored) { + updateUsbState(available, tethered, errored); + updateBluetoothState(available, tethered, errored); + } + + + private void updateUsbState(String[] available, String[] tethered, + String[] errored) { ConnectivityManager cm = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE); boolean usbTethered = false; @@ -260,6 +322,66 @@ public class TetherSettings extends PreferenceActivity { } } + private void updateBluetoothState(String[] available, String[] tethered, + String[] errored) { + ConnectivityManager cm = + (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE); + boolean bluetoothTethered = false; + boolean bluetoothAvailable = false; + int bluetoothError = ConnectivityManager.TETHER_ERROR_NO_ERROR; + boolean bluetoothErrored = false; + for (String s : available) { + for (String regex : mBluetoothRegexs) { + if (s.matches(regex)) { + bluetoothAvailable = true; + if (bluetoothError == ConnectivityManager.TETHER_ERROR_NO_ERROR) { + bluetoothError = cm.getLastTetherError(s); + } + } + } + } + for (String s : tethered) { + for (String regex : mBluetoothRegexs) { + if (s.matches(regex)) bluetoothTethered = true; + } + } + for (String s: errored) { + for (String regex : mBluetoothRegexs) { + if (s.matches(regex)) bluetoothErrored = true; + } + } + + BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); + int btState = adapter.getState(); + if (btState == BluetoothAdapter.STATE_TURNING_OFF) { + mBluetoothTether.setEnabled(false); + mBluetoothSettings.setEnabled(false); + mBluetoothTether.setSummary(R.string.wifi_stopping); + } else if (btState == BluetoothAdapter.STATE_TURNING_ON) { + mBluetoothTether.setEnabled(false); + mBluetoothSettings.setEnabled(false); + mBluetoothTether.setSummary(R.string.bluetooth_turning_on); + } else if (mBluetoothPan.isTetheringOn()) { + mBluetoothTether.setChecked(true); + if (btState == BluetoothAdapter.STATE_ON) { + mBluetoothTether.setEnabled(true); + mBluetoothSettings.setEnabled(true); + if (bluetoothTethered) { + mBluetoothTether.setSummary(R.string.bluetooth_tethering_connected_subtext); + } else if (bluetoothErrored) { + mBluetoothTether.setSummary(R.string.bluetooth_tethering_errored_subtext); + } else { + mBluetoothTether.setSummary(R.string.bluetooth_tethering_available_subtext); + } + } + } else { + mBluetoothTether.setEnabled(true); + mBluetoothTether.setChecked(false); + mBluetoothSettings.setEnabled(false); + mBluetoothTether.setSummary(R.string.bluetooth_tethering_off_subtext); + } + } + @Override public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { if (preference == mUsbTether) { @@ -296,8 +418,47 @@ public class TetherSettings extends PreferenceActivity { } mUsbTether.setSummary(""); } - } else if (preference == mTetherHelp) { + } else if(preference == mBluetoothTether) { + boolean bluetoothTetherState = mBluetoothTether.isChecked(); + if (bluetoothTetherState) { + // turn on Bluetooth first + BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); + if (adapter.getState() == BluetoothAdapter.STATE_OFF) { + adapter.enable(); + mBluetoothTether.setSummary(R.string.bluetooth_turning_on); + mBluetoothTether.setEnabled(false); + mBluetoothSettings.setEnabled(false); + } else { + mBluetoothSettings.setEnabled(true); + } + + mBluetoothPan.setBluetoothTethering(true, + BluetoothPan.NAP_ROLE, BluetoothPan.NAP_BRIDGE); + mBluetoothTether.setSummary(R.string.bluetooth_tethering_available_subtext); + } else { + boolean errored = false; + + ConnectivityManager cm = + (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE); + String [] tethered = cm.getTetheredIfaces(); + String bluetoothIface = findIface(tethered, mBluetoothRegexs); + if (bluetoothIface != null && + cm.untether(bluetoothIface) != ConnectivityManager.TETHER_ERROR_NO_ERROR) { + errored = true; + } + + mBluetoothPan.setBluetoothTethering(false, + BluetoothPan.NAP_ROLE, BluetoothPan.NAP_BRIDGE); + + mBluetoothSettings.setEnabled(false); + if (errored) { + mBluetoothTether.setSummary(R.string.bluetooth_tethering_errored_subtext); + } else { + mBluetoothTether.setSummary(R.string.bluetooth_tethering_off_subtext); + } + } + } else if (preference == mTetherHelp) { showDialog(DIALOG_TETHER_HELP); } return false; diff --git a/src/com/android/settings/WirelessSettings.java b/src/com/android/settings/WirelessSettings.java index 853fe851d3f..60ae20da03d 100644 --- a/src/com/android/settings/WirelessSettings.java +++ b/src/com/android/settings/WirelessSettings.java @@ -133,18 +133,34 @@ public class WirelessSettings extends PreferenceActivity { } else { String[] usbRegexs = cm.getTetherableUsbRegexs(); String[] wifiRegexs = cm.getTetherableWifiRegexs(); + String[] bluetoothRegexs = cm.getTetherableBluetoothRegexs(); + + boolean usbAvailable = usbRegexs.length != 0; + boolean wifiAvailable = wifiRegexs.length != 0; + boolean bluetoothAvailable = bluetoothRegexs.length != 0; + Preference p = findPreference(KEY_TETHER_SETTINGS); - if (wifiRegexs.length == 0) { + if (wifiAvailable && usbAvailable && bluetoothAvailable) { + p.setTitle(R.string.tether_settings_title_all); + p.setSummary(R.string.tether_settings_summary_all); + } else if (wifiAvailable && usbAvailable) { + p.setTitle(R.string.tether_settings_title_all); + p.setSummary(R.string.tether_settings_summary_usb_wifi); + } else if (wifiAvailable && bluetoothAvailable) { + p.setTitle(R.string.tether_settings_title_all); + p.setSummary(R.string.tether_settings_summary_wifi_bluetooth); + } else if (wifiAvailable) { + p.setTitle(R.string.tether_settings_title_wifi); + p.setSummary(R.string.tether_settings_summary_wifi); + } else if (usbAvailable && bluetoothAvailable) { + p.setTitle(R.string.tether_settings_title_usb_bluetooth); + p.setSummary(R.string.tether_settings_summary_usb_bluetooth); + } else if (usbAvailable) { p.setTitle(R.string.tether_settings_title_usb); p.setSummary(R.string.tether_settings_summary_usb); } else { - if (usbRegexs.length == 0) { - p.setTitle(R.string.tether_settings_title_wifi); - p.setSummary(R.string.tether_settings_summary_wifi); - } else { - p.setTitle(R.string.tether_settings_title_both); - p.setSummary(R.string.tether_settings_summary_both); - } + p.setTitle(R.string.tether_settings_title_bluetooth); + p.setSummary(R.string.tether_settings_summary_bluetooth); } } } @@ -152,21 +168,21 @@ public class WirelessSettings extends PreferenceActivity { @Override protected void onResume() { super.onResume(); - + mAirplaneModeEnabler.resume(); mWifiEnabler.resume(); mBtEnabler.resume(); } - + @Override protected void onPause() { super.onPause(); - + mAirplaneModeEnabler.pause(); mWifiEnabler.pause(); mBtEnabler.pause(); } - + @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_CODE_EXIT_ECM) { diff --git a/src/com/android/settings/bluetooth/BluetoothDevicePreference.java b/src/com/android/settings/bluetooth/BluetoothDevicePreference.java index 5b0218fd801..f0b1705b3a0 100644 --- a/src/com/android/settings/bluetooth/BluetoothDevicePreference.java +++ b/src/com/android/settings/bluetooth/BluetoothDevicePreference.java @@ -34,6 +34,7 @@ public class BluetoothDevicePreference extends Preference implements CachedBluet private static int sDimAlpha = Integer.MIN_VALUE; private CachedBluetoothDevice mCachedDevice; + private int mAccessibleProfile; /** * Cached local copy of whether the device is busy. This is only updated @@ -41,7 +42,8 @@ public class BluetoothDevicePreference extends Preference implements CachedBluet */ private boolean mIsBusy; - public BluetoothDevicePreference(Context context, CachedBluetoothDevice cachedDevice) { + public BluetoothDevicePreference(Context context, CachedBluetoothDevice cachedDevice, + int accessibleProfile) { super(context); if (sDimAlpha == Integer.MIN_VALUE) { @@ -51,6 +53,7 @@ public class BluetoothDevicePreference extends Preference implements CachedBluet } mCachedDevice = cachedDevice; + mAccessibleProfile = accessibleProfile; setLayoutResource(R.layout.preference_bluetooth); @@ -83,7 +86,7 @@ public class BluetoothDevicePreference extends Preference implements CachedBluet * related to BluetoothHeadset not bound to the actual * BluetoothHeadsetService when we got here. */ - setSummary(mCachedDevice.getSummary()); + setSummary(mCachedDevice.getSummary(mAccessibleProfile)); // Used to gray out the item mIsBusy = mCachedDevice.isBusy(); diff --git a/src/com/android/settings/bluetooth/BluetoothEventRedirector.java b/src/com/android/settings/bluetooth/BluetoothEventRedirector.java index dc8ab780c1c..f3a404f39b7 100644 --- a/src/com/android/settings/bluetooth/BluetoothEventRedirector.java +++ b/src/com/android/settings/bluetooth/BluetoothEventRedirector.java @@ -25,6 +25,7 @@ import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadset; import android.bluetooth.BluetoothInputDevice; +import android.bluetooth.BluetoothPan; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -133,6 +134,18 @@ public class BluetoothEventRedirector { mManager.getCachedDeviceManager().onProfileStateChanged(device, Profile.HID, newState); + } else if (action.equals(BluetoothPan.ACTION_PAN_STATE_CHANGED)) { + final int newState = intent.getIntExtra( + BluetoothPan.EXTRA_PAN_STATE, 0); + final int oldState = intent.getIntExtra( + BluetoothPan.EXTRA_PREVIOUS_PAN_STATE, 0); + if (newState == BluetoothPan.STATE_DISCONNECTED && + oldState == BluetoothPan.STATE_CONNECTING) { + Log.i(TAG, "Failed to connect BT PAN"); + } + mManager.getCachedDeviceManager().onProfileStateChanged(device, + Profile.PAN, newState); + } else if (action.equals(BluetoothDevice.ACTION_CLASS_CHANGED)) { mManager.getCachedDeviceManager().onBtClassChanged(device); @@ -180,6 +193,7 @@ public class BluetoothEventRedirector { // Fine-grained state broadcasts filter.addAction(BluetoothA2dp.ACTION_SINK_STATE_CHANGED); filter.addAction(BluetoothHeadset.ACTION_STATE_CHANGED); + filter.addAction(BluetoothPan.ACTION_PAN_STATE_CHANGED); filter.addAction(BluetoothDevice.ACTION_CLASS_CHANGED); filter.addAction(BluetoothDevice.ACTION_UUID); diff --git a/src/com/android/settings/bluetooth/BluetoothSettings.java b/src/com/android/settings/bluetooth/BluetoothSettings.java index 1e73b2d433e..82caa465cf2 100644 --- a/src/com/android/settings/bluetooth/BluetoothSettings.java +++ b/src/com/android/settings/bluetooth/BluetoothSettings.java @@ -18,22 +18,33 @@ package com.android.settings.bluetooth; import com.android.settings.ProgressCategory; import com.android.settings.R; +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.bluetooth.BluetoothDevicePicker; +import android.bluetooth.BluetoothPan; import android.bluetooth.BluetoothUuid; +import android.bluetooth.IBluetooth; import android.content.BroadcastReceiver; import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; +import android.os.IBinder; import android.os.ParcelUuid; +import android.os.RemoteException; +import android.os.ServiceManager; import android.preference.CheckBoxPreference; import android.preference.Preference; import android.preference.PreferenceActivity; import android.preference.PreferenceScreen; +import android.server.BluetoothService; +import android.text.TextUtils; +import android.util.Log; import android.view.ContextMenu; import android.view.MenuItem; import android.view.View; @@ -60,6 +71,10 @@ public class BluetoothSettings extends PreferenceActivity private static final int SCREEN_TYPE_SETTINGS = 0; private static final int SCREEN_TYPE_DEVICEPICKER = 1; + private static final int SCREEN_TYPE_TETHERING = 2; + + public static final String ACTION_LAUNCH_TETHER_PICKER = + "com.android.settings.bluetooth.action.LAUNCH_TETHER_PICKER"; private int mScreenType; private int mFilterType; @@ -88,16 +103,19 @@ public class BluetoothSettings extends PreferenceActivity if (intent.getAction().equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { onBluetoothStateChanged(mLocalManager.getBluetoothState()); - } else if (intent.getAction().equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED) - && mScreenType == SCREEN_TYPE_DEVICEPICKER) { + } else if (intent.getAction().equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) { int bondState = intent .getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR); if (bondState == BluetoothDevice.BOND_BONDED) { BluetoothDevice device = intent .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); if (device.equals(mSelectedDevice)) { - sendDevicePickedIntent(device); - finish(); + if (mScreenType == SCREEN_TYPE_DEVICEPICKER) { + sendDevicePickedIntent(device); + finish(); + } else if (mScreenType == SCREEN_TYPE_TETHERING) { + onPanDevicePicked(); + } } } } @@ -132,6 +150,12 @@ public class BluetoothSettings extends PreferenceActivity mLaunchPackage = intent.getStringExtra(BluetoothDevicePicker.EXTRA_LAUNCH_PACKAGE); mLaunchClass = intent.getStringExtra(BluetoothDevicePicker.EXTRA_LAUNCH_CLASS); + setTitle(getString(R.string.device_picker)); + addPreferencesFromResource(R.xml.device_picker); + } else if (action.equals(ACTION_LAUNCH_TETHER_PICKER)){ + mScreenType = SCREEN_TYPE_TETHERING; + mFilterType = BluetoothDevicePicker.FILTER_TYPE_PANU; + setTitle(getString(R.string.device_picker)); addPreferencesFromResource(R.xml.device_picker); } else { @@ -239,6 +263,18 @@ public class BluetoothSettings extends PreferenceActivity } else { btPreference.getCachedDevice().onClicked(); } + } else if (mScreenType == SCREEN_TYPE_TETHERING){ + CachedBluetoothDevice device = btPreference.getCachedDevice(); + + mSelectedDevice = device.getDevice(); + mLocalManager.stopScanning(); + mLocalManager.persistSelectedDeviceInPicker(mSelectedDevice.getAddress()); + if ((device.getBondState() == BluetoothDevice.BOND_BONDED)) { + onPanDevicePicked(); + // don't call finish so that users can see it connecting + } else { + btPreference.getCachedDevice().onClicked(); + } } return true; } @@ -321,6 +357,19 @@ public class BluetoothSettings extends PreferenceActivity if (bluetoothClass.doesClassMatch(BluetoothClass.PROFILE_HEADSET)) return true; } break; + case BluetoothDevicePicker.FILTER_TYPE_PANU: + if (uuids != null) { + if (BluetoothUuid.containsAnyUuid(uuids, + LocalBluetoothProfileManager.PANU_PROFILE_UUIDS)) return true; + + } + break; + case BluetoothDevicePicker.FILTER_TYPE_NAP: + if (uuids != null) { + if (BluetoothUuid.containsAnyUuid(uuids, + LocalBluetoothProfileManager.NAP_PROFILE_UUIDS)) return true; + } + break; default: return true; } @@ -328,7 +377,14 @@ public class BluetoothSettings extends PreferenceActivity } private void createDevicePreference(CachedBluetoothDevice cachedDevice) { - BluetoothDevicePreference preference = new BluetoothDevicePreference(this, cachedDevice); + BluetoothDevicePreference preference; + if (mScreenType == SCREEN_TYPE_TETHERING) { + preference = new BluetoothDevicePreference( + this, cachedDevice, CachedBluetoothDevice.PAN_PROFILE); + } else { + preference = new BluetoothDevicePreference( + this, cachedDevice, CachedBluetoothDevice.OTHER_PROFILES); + } mDeviceList.addPreference(preference); mDevicePreferenceMap.put(cachedDevice, preference); } @@ -354,12 +410,52 @@ public class BluetoothSettings extends PreferenceActivity } } + private void onPanDevicePicked() { + final LocalBluetoothProfileManager profileManager = + LocalBluetoothProfileManager.getProfileManager(mLocalManager, Profile.PAN); + int status = profileManager.getConnectionStatus(mSelectedDevice); + if (SettingsBtStatus.isConnectionStatusConnected(status)) { + String name = mSelectedDevice.getName(); + if (TextUtils.isEmpty(name)) { + name = getString(R.string.bluetooth_device); + } + String message = getString(R.string.bluetooth_untether_blank, name); + DialogInterface.OnClickListener disconnectListener = + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + profileManager.disconnect(mSelectedDevice); + } + }; + new AlertDialog.Builder(this) + .setTitle(name) + .setMessage(message) + .setPositiveButton(android.R.string.ok, disconnectListener) + .setNegativeButton(android.R.string.cancel, null) + .create() + .show(); + } else if (status == SettingsBtStatus.CONNECTION_STATUS_DISCONNECTED) { + if (profileManager.getConnectedDevices().size() >= BluetoothPan.MAX_CONNECTIONS) { + new AlertDialog.Builder(this) + .setIcon(android.R.drawable.ic_dialog_alert) + .setTitle(R.string.bluetooth_error_title) + .setMessage(getString(R.string.bluetooth_tethering_overflow_error, + BluetoothPan.MAX_CONNECTIONS)) + .setNegativeButton(android.R.string.ok, null) + .create() + .show(); + return; + } + profileManager.connect(mSelectedDevice); + } + } + private void sendDevicePickedIntent(BluetoothDevice device) { Intent intent = new Intent(BluetoothDevicePicker.ACTION_DEVICE_SELECTED); - if (mLaunchPackage != null && mLaunchClass != null) { + intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); + if (mScreenType == SCREEN_TYPE_DEVICEPICKER && + mLaunchPackage != null && mLaunchClass != null) { intent.setClassName(mLaunchPackage, mLaunchClass); } - intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); sendBroadcast(intent); } } diff --git a/src/com/android/settings/bluetooth/CachedBluetoothDevice.java b/src/com/android/settings/bluetooth/CachedBluetoothDevice.java index bdaffcae9d8..5f374a5e749 100644 --- a/src/com/android/settings/bluetooth/CachedBluetoothDevice.java +++ b/src/com/android/settings/bluetooth/CachedBluetoothDevice.java @@ -56,6 +56,9 @@ public class CachedBluetoothDevice implements Comparable 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; + private final BluetoothDevice mDevice; private String mName; private short mRssi; @@ -625,9 +628,9 @@ public class CachedBluetoothDevice implements Comparable } } - public int getSummary() { + public int getSummary(int accessibleProfile) { // TODO: clean up - int oneOffSummary = getOneOffSummary(); + int oneOffSummary = getOneOffSummary(accessibleProfile); if (oneOffSummary != 0) { return oneOffSummary; } @@ -653,34 +656,43 @@ public class CachedBluetoothDevice implements Comparable * * @return A one-off summary that is applicable for the current state, or 0. */ - private int getOneOffSummary() { + private int getOneOffSummary(int accessibleProfile) { boolean isA2dpConnected = false; boolean isHeadsetConnected = false; boolean isHidConnected = false; + boolean isPanConnected = false; boolean isConnecting = false; - 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 (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)) { + 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.HEADSET); + .getProfileManager(mLocalManager, Profile.PAN); 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); + isPanConnected = profileManager.isConnected(mDevice); } if (isConnecting) { @@ -695,6 +707,8 @@ public class CachedBluetoothDevice implements Comparable 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; } diff --git a/src/com/android/settings/bluetooth/ConnectSpecificProfilesActivity.java b/src/com/android/settings/bluetooth/ConnectSpecificProfilesActivity.java index 62c6f7952b5..ab769a72fe9 100644 --- a/src/com/android/settings/bluetooth/ConnectSpecificProfilesActivity.java +++ b/src/com/android/settings/bluetooth/ConnectSpecificProfilesActivity.java @@ -232,7 +232,8 @@ public class ConnectSpecificProfilesActivity extends PreferenceActivity * If the device is online, show status. Otherwise, show a summary that * describes what the checkbox does. */ - mOnlineModePreference.setSummary(mOnlineMode ? mCachedDevice.getSummary() + mOnlineModePreference.setSummary(mOnlineMode ? + mCachedDevice.getSummary(CachedBluetoothDevice.OTHER_PROFILES) : R.string.bluetooth_device_advanced_online_mode_summary); } diff --git a/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java b/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java index b09e1443c05..6193a4e87e7 100644 --- a/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java +++ b/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java @@ -22,6 +22,7 @@ import android.bluetooth.BluetoothA2dp; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadset; import android.bluetooth.BluetoothInputDevice; +import android.bluetooth.BluetoothPan; import android.bluetooth.BluetoothUuid; import android.os.Handler; import android.os.ParcelUuid; @@ -60,6 +61,14 @@ public abstract class LocalBluetoothProfileManager { BluetoothUuid.Hid }; + /* package */ static final ParcelUuid[] PANU_PROFILE_UUIDS = new ParcelUuid[] { + BluetoothUuid.PANU + }; + + /* package */ static final ParcelUuid[] NAP_PROFILE_UUIDS = new ParcelUuid[] { + BluetoothUuid.NAP + }; + /** * An interface for notifying BluetoothHeadset IPC clients when they have * been connected to the BluetoothHeadset service. @@ -105,6 +114,9 @@ public abstract class LocalBluetoothProfileManager { profileManager = new HidProfileManager(localManager); sProfileMap.put(Profile.HID, profileManager); + + profileManager = new PanProfileManager(localManager); + sProfileMap.put(Profile.PAN, profileManager); } } } @@ -173,6 +185,10 @@ public abstract class LocalBluetoothProfileManager { if (BluetoothUuid.containsAnyUuid(uuids, HID_PROFILE_UUIDS)) { profiles.add(Profile.HID); } + + if (BluetoothUuid.containsAnyUuid(uuids, PANU_PROFILE_UUIDS)) { + profiles.add(Profile.PAN); + } } protected LocalBluetoothProfileManager(LocalBluetoothManager localManager) { @@ -208,7 +224,8 @@ public abstract class LocalBluetoothProfileManager { HEADSET(R.string.bluetooth_profile_headset), A2DP(R.string.bluetooth_profile_a2dp), OPP(R.string.bluetooth_profile_opp), - HID(R.string.bluetooth_profile_hid); + HID(R.string.bluetooth_profile_hid), + PAN(R.string.bluetooth_profile_pan); public final int localizedString; @@ -613,4 +630,80 @@ public abstract class LocalBluetoothProfileManager { } } } + + private static class PanProfileManager extends LocalBluetoothProfileManager { + private BluetoothPan mService; + + public PanProfileManager(LocalBluetoothManager localManager) { + super(localManager); + mService = new BluetoothPan(localManager.getContext()); + } + + @Override + public boolean connect(BluetoothDevice device) { + return mService.connect(device); + } + + @Override + public int convertState(int panState) { + switch (panState) { + case BluetoothPan.STATE_CONNECTED: + return SettingsBtStatus.CONNECTION_STATUS_CONNECTED; + case BluetoothPan.STATE_CONNECTING: + return SettingsBtStatus.CONNECTION_STATUS_CONNECTING; + case BluetoothPan.STATE_DISCONNECTED: + return SettingsBtStatus.CONNECTION_STATUS_DISCONNECTED; + case BluetoothPan.STATE_DISCONNECTING: + return SettingsBtStatus.CONNECTION_STATUS_DISCONNECTING; + default: + return SettingsBtStatus.CONNECTION_STATUS_UNKNOWN; + } + } + + @Override + public boolean disconnect(BluetoothDevice device) { + return mService.disconnect(device); + } + + @Override + public int getSummary(BluetoothDevice device) { + final int connectionStatus = getConnectionStatus(device); + + if (SettingsBtStatus.isConnectionStatusConnected(connectionStatus)) { + return R.string.bluetooth_pan_profile_summary_connected; + } else { + return SettingsBtStatus.getConnectionStatusSummary(connectionStatus); + } + } + + @Override + public boolean isProfileReady() { + return true; + } + + @Override + public Set getConnectedDevices() { + return mService.getConnectedDevices(); + } + + @Override + public int getConnectionStatus(BluetoothDevice device) { + return convertState(mService.getPanDeviceState(device)); + } + + @Override + public int getPreferred(BluetoothDevice device) { + return -1; + } + + @Override + public boolean isPreferred(BluetoothDevice device) { + return false; + } + + @Override + public void setPreferred(BluetoothDevice device, boolean preferred) { + return; + } + } }