summaryrefslogtreecommitdiffstats
path: root/core/java/android/server
diff options
context:
space:
mode:
authorJaikumar Ganesh <jaikumar@google.com>2010-06-04 10:23:03 -0700
committerJaikumar Ganesh <jaikumar@google.com>2010-06-17 13:49:25 -0700
commit545e6708adda6859932b55fd824794b1401f5318 (patch)
treece35056656b208a19aca1edc98864f35935d4edf /core/java/android/server
parent4e74ae3d5b27d917ea26d0929015f9fdc64af412 (diff)
downloadframeworks_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.java52
-rw-r--r--core/java/android/server/BluetoothService.java131
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);
}