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);
+ }
+ }
+ }
}