diff options
author | Jaikumar Ganesh <jaikumar@google.com> | 2010-06-04 10:23:03 -0700 |
---|---|---|
committer | Jaikumar Ganesh <jaikumar@google.com> | 2010-06-17 13:49:25 -0700 |
commit | 545e6708adda6859932b55fd824794b1401f5318 (patch) | |
tree | ce35056656b208a19aca1edc98864f35935d4edf /core/java/android/server | |
parent | 4e74ae3d5b27d917ea26d0929015f9fdc64af412 (diff) | |
download | frameworks_base-545e6708adda6859932b55fd824794b1401f5318.zip frameworks_base-545e6708adda6859932b55fd824794b1401f5318.tar.gz frameworks_base-545e6708adda6859932b55fd824794b1401f5318.tar.bz2 |
HID profile.
Change-Id: I52e965a6537bce02c751ba26fe7b44dd03832510
Diffstat (limited to 'core/java/android/server')
-rw-r--r-- | core/java/android/server/BluetoothEventLoop.java | 52 | ||||
-rw-r--r-- | core/java/android/server/BluetoothService.java | 131 |
2 files changed, 176 insertions, 7 deletions
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java index 35a582d..9b7a73d 100644 --- a/core/java/android/server/BluetoothEventLoop.java +++ b/core/java/android/server/BluetoothEventLoop.java @@ -20,6 +20,7 @@ import android.bluetooth.BluetoothA2dp; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothInputDevice; import android.bluetooth.BluetoothUuid; import android.content.Context; import android.content.Intent; @@ -427,6 +428,20 @@ class BluetoothEventLoop { } } + private void onInputDevicePropertyChanged(String path, String[] propValues) { + String address = mBluetoothService.getAddressFromObjectPath(path); + if (address == null) { + Log.e(TAG, "onInputDevicePropertyChanged: Address of the remote device in null"); + return; + } + log(" Input Device : Name of Property is:" + propValues[0]); + boolean state = false; + if (propValues[1].equals("true")) { + state = true; + } + mBluetoothService.handleInputDevicePropertyChange(address, state); + } + private String checkPairingRequestAndGetAddress(String objectPath, int nativeData) { String address = mBluetoothService.getAddressFromObjectPath(objectPath); if (address == null) { @@ -573,6 +588,8 @@ class BluetoothEventLoop { } private boolean onAgentAuthorize(String objectPath, String deviceUuid) { + if (!mBluetoothService.isEnabled()) return false; + String address = mBluetoothService.getAddressFromObjectPath(objectPath); if (address == null) { Log.e(TAG, "Unable to get device address in onAuthAgentAuthorize"); @@ -581,15 +598,15 @@ class BluetoothEventLoop { boolean authorized = false; ParcelUuid uuid = ParcelUuid.fromString(deviceUuid); - BluetoothA2dp a2dp = new BluetoothA2dp(mContext); + BluetoothDevice device = mAdapter.getRemoteDevice(address); // Bluez sends the UUID of the local service being accessed, _not_ the // remote service - if (mBluetoothService.isEnabled() && - (BluetoothUuid.isAudioSource(uuid) || BluetoothUuid.isAvrcpTarget(uuid) - || BluetoothUuid.isAdvAudioDist(uuid)) && - !isOtherSinkInNonDisconnectingState(address)) { - BluetoothDevice device = mAdapter.getRemoteDevice(address); + if ((BluetoothUuid.isAudioSource(uuid) || BluetoothUuid.isAvrcpTarget(uuid) + || BluetoothUuid.isAdvAudioDist(uuid)) && + !isOtherSinkInNonDisconnectingState(address)) { + BluetoothA2dp a2dp = new BluetoothA2dp(mContext); + authorized = a2dp.getSinkPriority(device) > BluetoothA2dp.PRIORITY_OFF; if (authorized) { Log.i(TAG, "Allowing incoming A2DP / AVRCP connection from " + address); @@ -597,6 +614,15 @@ class BluetoothEventLoop { } else { Log.i(TAG, "Rejecting incoming A2DP / AVRCP connection from " + address); } + } else if (BluetoothUuid.isInputDevice(uuid) && !isOtherInputDeviceConnected(address)) { + BluetoothInputDevice inputDevice = new BluetoothInputDevice(mContext); + authorized = inputDevice.getInputDevicePriority(device) > + BluetoothInputDevice.PRIORITY_OFF; + if (authorized) { + Log.i(TAG, "Allowing incoming HID connection from " + address); + } else { + Log.i(TAG, "Rejecting incoming HID connection from " + address); + } } else { Log.i(TAG, "Rejecting incoming " + deviceUuid + " connection from " + address); } @@ -604,7 +630,19 @@ class BluetoothEventLoop { return authorized; } - boolean isOtherSinkInNonDisconnectingState(String address) { + private boolean isOtherInputDeviceConnected(String address) { + Set<BluetoothDevice> devices = + mBluetoothService.lookupInputDevicesMatchingStates(new int[] { + BluetoothInputDevice.STATE_CONNECTING, + BluetoothInputDevice.STATE_CONNECTED}); + + for (BluetoothDevice device : devices) { + if (!device.getAddress().equals(address)) return true; + } + return false; + } + + private boolean isOtherSinkInNonDisconnectingState(String address) { BluetoothA2dp a2dp = new BluetoothA2dp(mContext); Set<BluetoothDevice> devices = a2dp.getNonDisconnectedSinks(); if (devices.size() == 0) return false; diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java index 31e5a7b..e68632d 100644 --- a/core/java/android/server/BluetoothService.java +++ b/core/java/android/server/BluetoothService.java @@ -24,16 +24,19 @@ package android.server; +import android.bluetooth.BluetoothA2dp; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadset; import android.bluetooth.BluetoothDeviceProfileState; import android.bluetooth.BluetoothProfileState; +import android.bluetooth.BluetoothInputDevice; import android.bluetooth.BluetoothSocket; import android.bluetooth.BluetoothUuid; import android.bluetooth.IBluetooth; import android.bluetooth.IBluetoothCallback; +import android.bluetooth.IBluetoothHeadset; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; @@ -70,8 +73,10 @@ import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.Map; +import java.util.Set; public class BluetoothService extends IBluetooth.Stub { private static final String TAG = "BluetoothService"; @@ -129,6 +134,8 @@ public class BluetoothService extends IBluetooth.Stub { private final BluetoothProfileState mHfpProfileState; private BluetoothA2dpService mA2dpService; + private final HashMap<BluetoothDevice, Integer> mInputDevices; + private static String mDockAddress; private String mDockPin; @@ -198,6 +205,7 @@ public class BluetoothService extends IBluetooth.Stub { filter.addAction(Intent.ACTION_DOCK_EVENT); mContext.registerReceiver(mReceiver, filter); + mInputDevices = new HashMap<BluetoothDevice, Integer>(); } public static synchronized String readDockBluetoothAddress() { @@ -1220,6 +1228,127 @@ public class BluetoothService extends IBluetooth.Stub { return sp.contains(SHARED_PREFERENCE_DOCK_ADDRESS + address); } + public synchronized boolean connectInputDevice(BluetoothDevice device) { + mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, + "Need BLUETOOTH_ADMIN permission"); + + String objectPath = getObjectPathFromAddress(device.getAddress()); + if (objectPath == null || getConnectedInputDevices().length != 0 || + getInputDevicePriority(device) == BluetoothInputDevice.PRIORITY_OFF) { + return false; + } + if(connectInputDeviceNative(objectPath)) { + handleInputDeviceStateChange(device, BluetoothInputDevice.STATE_CONNECTING); + return true; + } + return false; + } + + public synchronized boolean disconnectInputDevice(BluetoothDevice device) { + mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, + "Need BLUETOOTH_ADMIN permission"); + + String objectPath = getObjectPathFromAddress(device.getAddress()); + if (objectPath == null || getConnectedInputDevices().length == 0) { + return false; + } + if(disconnectInputDeviceNative(objectPath)) { + handleInputDeviceStateChange(device, BluetoothInputDevice.STATE_DISCONNECTING); + return true; + } + return false; + } + + public synchronized int getInputDeviceState(BluetoothDevice device) { + mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); + + if (mInputDevices.get(device) == null) { + return BluetoothInputDevice.STATE_DISCONNECTED; + } + return mInputDevices.get(device.getAddress()); + } + + public synchronized BluetoothDevice[] getConnectedInputDevices() { + mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); + Set<BluetoothDevice> devices = lookupInputDevicesMatchingStates( + new int[] {BluetoothInputDevice.STATE_CONNECTED}); + return devices.toArray(new BluetoothDevice[devices.size()]); + } + + public synchronized int getInputDevicePriority(BluetoothDevice device) { + mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); + return Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.getBluetoothInputDevicePriorityKey(device.getAddress()), + BluetoothInputDevice.PRIORITY_UNDEFINED); + } + + public synchronized boolean setInputDevicePriority(BluetoothDevice device, int priority) { + mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, + "Need BLUETOOTH_ADMIN permission"); + if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { + return false; + } + return Settings.Secure.putInt(mContext.getContentResolver(), + Settings.Secure.getBluetoothInputDevicePriorityKey(device.getAddress()), + priority); + } + + /*package*/synchronized Set<BluetoothDevice> lookupInputDevicesMatchingStates(int[] states) { + Set<BluetoothDevice> inputDevices = new HashSet<BluetoothDevice>(); + if (mInputDevices.isEmpty()) { + return inputDevices; + } + for (BluetoothDevice device: mInputDevices.keySet()) { + int inputDeviceState = getInputDeviceState(device); + for (int state : states) { + if (state == inputDeviceState) { + inputDevices.add(device); + break; + } + } + } + return inputDevices; + } + + private synchronized void handleInputDeviceStateChange(BluetoothDevice device, int state) { + int prevState; + if (mInputDevices.get(device) == null) { + prevState = BluetoothInputDevice.STATE_DISCONNECTED; + } else { + prevState = mInputDevices.get(device); + } + if (prevState == state) return; + + mInputDevices.put(device, state); + + if (getInputDevicePriority(device) > + BluetoothInputDevice.PRIORITY_OFF && + state == BluetoothInputDevice.STATE_CONNECTING || + state == BluetoothInputDevice.STATE_CONNECTED) { + // We have connected or attempting to connect. + // Bump priority + setInputDevicePriority(device, BluetoothInputDevice.PRIORITY_AUTO_CONNECT); + } + + Intent intent = new Intent(BluetoothInputDevice.ACTION_INPUT_DEVICE_STATE_CHANGED); + intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); + intent.putExtra(BluetoothInputDevice.EXTRA_PREVIOUS_INPUT_DEVICE_STATE, prevState); + intent.putExtra(BluetoothInputDevice.EXTRA_INPUT_DEVICE_STATE, state); + mContext.sendBroadcast(intent, BLUETOOTH_PERM); + + if (DBG) log("InputDevice state : device: " + device + " State:" + prevState + "->" + state); + + } + + /*package*/ void handleInputDevicePropertyChange(String path, boolean connected) { + String address = getAddressFromObjectPath(path); + if (address == null) return; + int state = connected ? BluetoothInputDevice.STATE_CONNECTED : + BluetoothInputDevice.STATE_DISCONNECTED; + BluetoothDevice device = mAdapter.getRemoteDevice(address); + handleInputDeviceStateChange(device, state); + } + /*package*/ boolean isRemoteDeviceInCache(String address) { return (mDeviceProperties.get(address) != null); } @@ -2103,4 +2232,6 @@ public class BluetoothService extends IBluetooth.Stub { short channel); private native boolean removeServiceRecordNative(int handle); private native boolean setLinkTimeoutNative(String path, int num_slots); + private native boolean connectInputDeviceNative(String path); + private native boolean disconnectInputDeviceNative(String path); } |