diff --git a/res/values/strings.xml b/res/values/strings.xml index 46467c26312..bff1beea019 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -754,6 +754,8 @@ Phone Transfer + + Input Device Connected to media audio @@ -761,6 +763,8 @@ Connected to phone audio Connected to phone and media audio + + Connected to input device %1$s options @@ -778,6 +782,8 @@ Connected to file transfer server Not connected to file transfer server + + Connected to input device Use for media audio @@ -785,6 +791,10 @@ Use for phone audio Use for file transfer + + Use for input Dock Settings diff --git a/src/com/android/settings/bluetooth/BluetoothEventRedirector.java b/src/com/android/settings/bluetooth/BluetoothEventRedirector.java index dbdf6c156e8..dc8ab780c1c 100644 --- a/src/com/android/settings/bluetooth/BluetoothEventRedirector.java +++ b/src/com/android/settings/bluetooth/BluetoothEventRedirector.java @@ -24,6 +24,7 @@ import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadset; +import android.bluetooth.BluetoothInputDevice; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -119,6 +120,19 @@ public class BluetoothEventRedirector { mManager.getCachedDeviceManager().onProfileStateChanged(device, Profile.A2DP, newState); + } else if (action.equals(BluetoothInputDevice.ACTION_INPUT_DEVICE_STATE_CHANGED)) { + final int newState = intent.getIntExtra( + BluetoothInputDevice.EXTRA_INPUT_DEVICE_STATE, 0); + final int oldState = intent.getIntExtra( + BluetoothInputDevice.EXTRA_PREVIOUS_INPUT_DEVICE_STATE, 0); + if (newState == BluetoothInputDevice.STATE_DISCONNECTED && + oldState == BluetoothInputDevice.STATE_CONNECTING) { + Log.i(TAG, "Failed to connect BT HID"); + } + + mManager.getCachedDeviceManager().onProfileStateChanged(device, + Profile.HID, newState); + } else if (action.equals(BluetoothDevice.ACTION_CLASS_CHANGED)) { mManager.getCachedDeviceManager().onBtClassChanged(device); diff --git a/src/com/android/settings/bluetooth/CachedBluetoothDevice.java b/src/com/android/settings/bluetooth/CachedBluetoothDevice.java index 48fd85d529e..7ab303011fe 100644 --- a/src/com/android/settings/bluetooth/CachedBluetoothDevice.java +++ b/src/com/android/settings/bluetooth/CachedBluetoothDevice.java @@ -540,6 +540,12 @@ public class CachedBluetoothDevice implements Comparable Log.v(TAG, "opp classbits != uuid"); printUuids = true; } + + if (bluetoothClass.doesClassMatch(BluetoothClass.PROFILE_HID) != + mProfiles.contains(Profile.HID)) { + Log.v(TAG, "hid classbits != uuid"); + printUuids = true; + } } if (printUuids) { @@ -629,7 +635,10 @@ public class CachedBluetoothDevice implements Comparable * @return A one-off summary that is applicable for the current state, or 0. */ private int getOneOffSummary() { - boolean isA2dpConnected = false, isHeadsetConnected = false, isConnecting = false; + boolean isA2dpConnected = false; + boolean isHeadsetConnected = false; + boolean isHidConnected = false; + boolean isConnecting = false; if (mProfiles.contains(Profile.A2DP)) { LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager @@ -647,6 +656,14 @@ public class CachedBluetoothDevice implements Comparable 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); + } + if (isConnecting) { // If any of these important profiles is connecting, prefer that return SettingsBtStatus.getConnectionStatusSummary( @@ -657,6 +674,8 @@ public class CachedBluetoothDevice implements Comparable 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 { return 0; } @@ -673,7 +692,8 @@ public class CachedBluetoothDevice implements Comparable } private boolean isConnectableProfile(Profile profile) { - return profile.equals(Profile.HEADSET) || profile.equals(Profile.A2DP); + return profile.equals(Profile.HEADSET) || profile.equals(Profile.A2DP) || + profile.equals(Profile.HID); } public void onCreateContextMenu(ContextMenu menu) { diff --git a/src/com/android/settings/bluetooth/ConnectSpecificProfilesActivity.java b/src/com/android/settings/bluetooth/ConnectSpecificProfilesActivity.java index 2a8af5fdec6..62c6f7952b5 100644 --- a/src/com/android/settings/bluetooth/ConnectSpecificProfilesActivity.java +++ b/src/com/android/settings/bluetooth/ConnectSpecificProfilesActivity.java @@ -299,6 +299,8 @@ public class ConnectSpecificProfilesActivity extends PreferenceActivity return R.string.bluetooth_a2dp_profile_summary_use_for; case HEADSET: return R.string.bluetooth_headset_profile_summary_use_for; + case HID: + return R.string.bluetooth_hid_profile_summary_use_for; default: return 0; } diff --git a/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java b/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java index 01714fe6029..b09e1443c05 100644 --- a/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java +++ b/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java @@ -21,6 +21,7 @@ import com.android.settings.R; import android.bluetooth.BluetoothA2dp; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadset; +import android.bluetooth.BluetoothInputDevice; import android.bluetooth.BluetoothUuid; import android.os.Handler; import android.os.ParcelUuid; @@ -55,6 +56,10 @@ public abstract class LocalBluetoothProfileManager { BluetoothUuid.ObexObjectPush }; + /* package */ static final ParcelUuid[] HID_PROFILE_UUIDS = new ParcelUuid[] { + BluetoothUuid.Hid + }; + /** * An interface for notifying BluetoothHeadset IPC clients when they have * been connected to the BluetoothHeadset service. @@ -97,6 +102,9 @@ public abstract class LocalBluetoothProfileManager { profileManager = new OppProfileManager(localManager); sProfileMap.put(Profile.OPP, profileManager); + + profileManager = new HidProfileManager(localManager); + sProfileMap.put(Profile.HID, profileManager); } } } @@ -161,6 +169,10 @@ public abstract class LocalBluetoothProfileManager { if (BluetoothUuid.containsAnyUuid(uuids, OPP_PROFILE_UUIDS)) { profiles.add(Profile.OPP); } + + if (BluetoothUuid.containsAnyUuid(uuids, HID_PROFILE_UUIDS)) { + profiles.add(Profile.HID); + } } protected LocalBluetoothProfileManager(LocalBluetoothManager localManager) { @@ -195,7 +207,8 @@ public abstract class LocalBluetoothProfileManager { public enum Profile { HEADSET(R.string.bluetooth_profile_headset), A2DP(R.string.bluetooth_profile_a2dp), - OPP(R.string.bluetooth_profile_opp); + OPP(R.string.bluetooth_profile_opp), + HID(R.string.bluetooth_profile_hid); public final int localizedString; @@ -518,4 +531,86 @@ public abstract class LocalBluetoothProfileManager { } } } + + private static class HidProfileManager extends LocalBluetoothProfileManager { + private BluetoothInputDevice mService; + + public HidProfileManager(LocalBluetoothManager localManager) { + super(localManager); + mService = new BluetoothInputDevice(localManager.getContext()); + } + + @Override + public boolean connect(BluetoothDevice device) { + return mService.connectInputDevice(device); + } + + @Override + public int convertState(int hidState) { + switch (hidState) { + case BluetoothInputDevice.STATE_CONNECTED: + return SettingsBtStatus.CONNECTION_STATUS_CONNECTED; + case BluetoothInputDevice.STATE_CONNECTING: + return SettingsBtStatus.CONNECTION_STATUS_CONNECTING; + case BluetoothInputDevice.STATE_DISCONNECTED: + return SettingsBtStatus.CONNECTION_STATUS_DISCONNECTED; + case BluetoothInputDevice.STATE_DISCONNECTING: + return SettingsBtStatus.CONNECTION_STATUS_DISCONNECTING; + default: + return SettingsBtStatus.CONNECTION_STATUS_UNKNOWN; + } + } + + @Override + public boolean disconnect(BluetoothDevice device) { + return mService.disconnectInputDevice(device); + } + + @Override + public Set getConnectedDevices() { + return mService.getConnectedInputDevices(); + } + + @Override + public int getConnectionStatus(BluetoothDevice device) { + return convertState(mService.getInputDeviceState(device)); + } + + @Override + public int getPreferred(BluetoothDevice device) { + return mService.getInputDevicePriority(device); + } + + @Override + public int getSummary(BluetoothDevice device) { + final int connectionStatus = getConnectionStatus(device); + + if (SettingsBtStatus.isConnectionStatusConnected(connectionStatus)) { + return R.string.bluetooth_hid_profile_summary_connected; + } else { + return SettingsBtStatus.getConnectionStatusSummary(connectionStatus); + } + } + + @Override + public boolean isPreferred(BluetoothDevice device) { + return mService.getInputDevicePriority(device) > BluetoothInputDevice.PRIORITY_OFF; + } + + @Override + public boolean isProfileReady() { + return true; + } + + @Override + public void setPreferred(BluetoothDevice device, boolean preferred) { + if (preferred) { + if (mService.getInputDevicePriority(device) < BluetoothInputDevice.PRIORITY_ON) { + mService.setInputDevicePriority(device, BluetoothInputDevice.PRIORITY_ON); + } + } else { + mService.setInputDevicePriority(device, BluetoothInputDevice.PRIORITY_OFF); + } + } + } }