diff options
13 files changed, 568 insertions, 920 deletions
@@ -116,6 +116,8 @@ LOCAL_SRC_FILES += \ core/java/android/bluetooth/IBluetoothSap.aidl \ core/java/android/bluetooth/IBluetoothStateChangeCallback.aidl \ core/java/android/bluetooth/IBluetoothHeadsetClient.aidl \ + core/java/android/bluetooth/IBluetoothHidDevice.aidl \ + core/java/android/bluetooth/IBluetoothHidDeviceCallback.aidl \ core/java/android/bluetooth/IBluetoothGatt.aidl \ core/java/android/bluetooth/IBluetoothGattCallback.aidl \ core/java/android/bluetooth/IBluetoothGattServerCallback.aidl \ diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index 1f3ff51..b9e5a75 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -1837,6 +1837,9 @@ public final class BluetoothAdapter { } else if (profile == BluetoothProfile.SAP) { BluetoothSap sap = new BluetoothSap(context, listener); return true; + } else if (profile == BluetoothProfile.HID_DEVICE) { + BluetoothHidDevice hidd = new BluetoothHidDevice(context, listener); + return true; } else { return false; } @@ -1905,6 +1908,10 @@ public final class BluetoothAdapter { BluetoothSap sap = (BluetoothSap)proxy; sap.close(); break; + case BluetoothProfile.HID_DEVICE: + BluetoothHidDevice hidd = (BluetoothHidDevice) proxy; + hidd.close(); + break; } } diff --git a/core/java/android/bluetooth/BluetoothHidDevice.java b/core/java/android/bluetooth/BluetoothHidDevice.java index b8b8f5f..3d6209a 100644 --- a/core/java/android/bluetooth/BluetoothHidDevice.java +++ b/core/java/android/bluetooth/BluetoothHidDevice.java @@ -1,4 +1,6 @@ /* + * Copyright (C) 2013 The Linux Foundation. All rights reserved + * Not a Contribution. * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,8 +18,6 @@ package android.bluetooth; -import android.annotation.SdkConstant; -import android.annotation.SdkConstant.SdkConstantType; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -26,209 +26,175 @@ import android.os.IBinder; import android.os.RemoteException; import android.util.Log; -import java.util.ArrayList; +import java.util.Arrays; import java.util.List; - /** - * This class provides the public APIs to control the Bluetooth Input - * Device Profile. - * - *<p>BluetoothInputDevice is a proxy object for controlling the Bluetooth - * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get - * the BluetoothInputDevice proxy object. - * - *<p>Each method is protected with its appropriate permission. - *@hide + * @hide */ -public final class BluetoothInputDevice implements BluetoothProfile { - private static final String TAG = "BluetoothInputDevice"; - private static final boolean DBG = true; - private static final boolean VDBG = false; +public final class BluetoothHidDevice implements BluetoothProfile { - /** - * Intent used to broadcast the change in connection state of the Input - * Device profile. - * - * <p>This intent will have 3 extras: - * <ul> - * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> - * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li> - * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> - * </ul> - * - * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of - * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING}, - * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}. - * - * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to - * receive. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_CONNECTION_STATE_CHANGED = - "android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED"; - - /** - * @hide - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_PROTOCOL_MODE_CHANGED = - "android.bluetooth.input.profile.action.PROTOCOL_MODE_CHANGED"; + private static final String TAG = BluetoothHidDevice.class.getSimpleName(); - /** - * @hide - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_REPORT = - "android.bluetooth.input.profile.action.REPORT"; + public static final String ACTION_CONNECTION_STATE_CHANGED = + "codeaurora.bluetooth.hid.profile.action.CONNECTION_STATE_CHANGED"; /** - * @hide + * Constants representing device subclass. + * + * @see #registerApp(String, String, String, byte, byte[], + * BluetoothHidDeviceCallback) */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_VIRTUAL_UNPLUG_STATUS = - "android.bluetooth.input.profile.action.VIRTUAL_UNPLUG_STATUS"; + public static final byte SUBCLASS1_NONE = (byte) 0x00; + public static final byte SUBCLASS1_KEYBOARD = (byte) 0x40; + public static final byte SUBCLASS1_MOUSE = (byte) 0x80; + public static final byte SUBCLASS1_COMBO = (byte) 0xC0; + public static final byte SUBCLASS2_UNCATEGORIZED = (byte) 0x00; + public static final byte SUBCLASS2_JOYSTICK = (byte) 0x01; + public static final byte SUBCLASS2_GAMEPAD = (byte) 0x02; + public static final byte SUBCLASS2_REMOTE_CONTROL = (byte) 0x03; + public static final byte SUBCLASS2_SENSING_DEVICE = (byte) 0x04; + public static final byte SUBCLASS2_DIGITIZER_TABLED = (byte) 0x05; + public static final byte SUBCLASS2_CARD_READER = (byte) 0x06; /** - * Return codes for the connect and disconnect Bluez / Dbus calls. - * @hide - */ - public static final int INPUT_DISCONNECT_FAILED_NOT_CONNECTED = 5000; - - /** - * @hide + * Constants representing report types. + * + * @see BluetoothHidDeviceCallback#onGetReport(byte, byte, int) + * @see BluetoothHidDeviceCallback#onSetReport(byte, byte, byte[]) + * @see BluetoothHidDeviceCallback#onIntrData(byte, byte[]) */ - public static final int INPUT_CONNECT_FAILED_ALREADY_CONNECTED = 5001; + public static final byte REPORT_TYPE_INPUT = (byte) 1; + public static final byte REPORT_TYPE_OUTPUT = (byte) 2; + public static final byte REPORT_TYPE_FEATURE = (byte) 3; /** - * @hide + * Constants representing error response for Set Report. + * + * @see BluetoothHidDeviceCallback#onSetReport(byte, byte, byte[]) */ - public static final int INPUT_CONNECT_FAILED_ATTEMPT_FAILED = 5002; + public static final byte ERROR_RSP_SUCCESS = (byte) 0; + public static final byte ERROR_RSP_NOT_READY = (byte) 1; + public static final byte ERROR_RSP_INVALID_RPT_ID = (byte) 2; + public static final byte ERROR_RSP_UNSUPPORTED_REQ = (byte) 3; + public static final byte ERROR_RSP_INVALID_PARAM = (byte) 4; + public static final byte ERROR_RSP_UNKNOWN = (byte) 14; /** - * @hide + * Constants representing protocol mode used set by host. Default is always + * {@link #PROTOCOL_REPORT_MODE} unless notified otherwise. + * + * @see BluetoothHidDeviceCallback#onSetProtocol(byte) */ - public static final int INPUT_OPERATION_GENERIC_FAILURE = 5003; + public static final byte PROTOCOL_BOOT_MODE = (byte) 0; + public static final byte PROTOCOL_REPORT_MODE = (byte) 1; - /** - * @hide - */ - public static final int INPUT_OPERATION_SUCCESS = 5004; + private Context mContext; - /** - * @hide - */ - public static final int PROTOCOL_REPORT_MODE = 0; + private ServiceListener mServiceListener; - /** - * @hide - */ - public static final int PROTOCOL_BOOT_MODE = 1; + private IBluetoothHidDevice mService; - /** - * @hide - */ - public static final int PROTOCOL_UNSUPPORTED_MODE = 255; + private BluetoothAdapter mAdapter; - /* int reportType, int reportType, int bufferSize */ - /** - * @hide - */ - public static final byte REPORT_TYPE_INPUT = 1; + private static class BluetoothHidDeviceCallbackWrapper extends IBluetoothHidDeviceCallback.Stub { - /** - * @hide - */ - public static final byte REPORT_TYPE_OUTPUT = 2; + private BluetoothHidDeviceCallback mCallback; - /** - * @hide - */ - public static final byte REPORT_TYPE_FEATURE = 3; + public BluetoothHidDeviceCallbackWrapper(BluetoothHidDeviceCallback callback) { + mCallback = callback; + } - /** - * @hide - */ - public static final int VIRTUAL_UNPLUG_STATUS_SUCCESS = 0; + @Override + public void onAppStatusChanged(BluetoothDevice pluggedDevice, + BluetoothHidDeviceAppConfiguration config, boolean registered) { + mCallback.onAppStatusChanged(pluggedDevice, config, registered); + } - /** - * @hide - */ - public static final int VIRTUAL_UNPLUG_STATUS_FAIL = 1; + @Override + public void onConnectionStateChanged(BluetoothDevice device, int state) { + mCallback.onConnectionStateChanged(device, state); + } - /** - * @hide - */ - public static final String EXTRA_PROTOCOL_MODE = "android.bluetooth.BluetoothInputDevice.extra.PROTOCOL_MODE"; + @Override + public void onGetReport(byte type, byte id, int bufferSize) { + mCallback.onGetReport(type, id, bufferSize); + } - /** - * @hide - */ - public static final String EXTRA_REPORT_TYPE = "android.bluetooth.BluetoothInputDevice.extra.REPORT_TYPE"; + @Override + public void onSetReport(byte type, byte id, byte[] data) { + mCallback.onSetReport(type, id, data); + } - /** - * @hide - */ - public static final String EXTRA_REPORT_ID = "android.bluetooth.BluetoothInputDevice.extra.REPORT_ID"; + @Override + public void onSetProtocol(byte protocol) { + mCallback.onSetProtocol(protocol); + } - /** - * @hide - */ - public static final String EXTRA_REPORT_BUFFER_SIZE = "android.bluetooth.BluetoothInputDevice.extra.REPORT_BUFFER_SIZE"; + @Override + public void onIntrData(byte reportId, byte[] data) { + mCallback.onIntrData(reportId, data); + } - /** - * @hide - */ - public static final String EXTRA_REPORT = "android.bluetooth.BluetoothInputDevice.extra.REPORT"; + @Override + public void onVirtualCableUnplug() { + mCallback.onVirtualCableUnplug(); + } + } - /** - * @hide - */ - public static final String EXTRA_VIRTUAL_UNPLUG_STATUS = "android.bluetooth.BluetoothInputDevice.extra.VIRTUAL_UNPLUG_STATUS"; + final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback = + new IBluetoothStateChangeCallback.Stub() { - private Context mContext; - private ServiceListener mServiceListener; - private BluetoothAdapter mAdapter; - private IBluetoothInputDevice mService; + public void onBluetoothStateChange(boolean up) { + Log.d(TAG, "onBluetoothStateChange: up=" + up); - final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback = - new IBluetoothStateChangeCallback.Stub() { - public void onBluetoothStateChange(boolean up) { - if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); - if (!up) { - if (VDBG) Log.d(TAG,"Unbinding service..."); - synchronized (mConnection) { - try { - mService = null; - mContext.unbindService(mConnection); - } catch (Exception re) { - Log.e(TAG,"",re); - } - } - } else { - synchronized (mConnection) { - try { - if (mService == null) { - if (VDBG) Log.d(TAG,"Binding service..."); - doBind(); - } - } catch (Exception re) { - Log.e(TAG,"",re); - } + synchronized (mConnection) { + if (!up) { + mService = null; + mContext.unbindService(mConnection); + } else { + if (mService == null) { + Log.v(TAG, "Binding service"); + if (!mContext.bindService(new Intent(IBluetoothHidDevice.class.getName()), + mConnection, 0)) { + Log.e(TAG, "Could not bind service"); } } } - }; + } + } + }; + + private ServiceConnection mConnection = new ServiceConnection() { + + public void onServiceConnected(ComponentName className, IBinder service) { + Log.d(TAG, "onServiceConnected()"); + + mService = IBluetoothHidDevice.Stub.asInterface(service); + + if (mServiceListener != null) { + mServiceListener.onServiceConnected(BluetoothProfile.HID_DEVICE, + BluetoothHidDevice.this); + } + } + + public void onServiceDisconnected(ComponentName className) { + Log.d(TAG, "onServiceDisconnected()"); + + mService = null; + + if (mServiceListener != null) { + mServiceListener.onServiceDisconnected(BluetoothProfile.HID_DEVICE); + } + } + }; + + BluetoothHidDevice(Context context, ServiceListener listener) { + Log.v(TAG, "BluetoothInputDevice()"); - /** - * Create a BluetoothInputDevice proxy object for interacting with the local - * Bluetooth Service which handles the InputDevice profile - * - */ - /*package*/ BluetoothInputDevice(Context context, ServiceListener l) { mContext = context; - mServiceListener = l; + mServiceListener = listener; mAdapter = BluetoothAdapter.getDefaultAdapter(); IBluetoothManager mgr = mAdapter.getBluetoothManager(); @@ -236,416 +202,278 @@ public final class BluetoothInputDevice implements BluetoothProfile { try { mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); } catch (RemoteException e) { - Log.e(TAG,"",e); + e.printStackTrace(); } } - doBind(); - } - - boolean doBind() { - Intent intent = new Intent(IBluetoothInputDevice.class.getName()); - ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); - intent.setComponent(comp); - if (comp == null || !mContext.bindService(intent, mConnection, 0)) { - Log.e(TAG, "Could not bind to Bluetooth HID Service with " + intent); - return false; + if (!context.bindService(new Intent(IBluetoothHidDevice.class.getName()), + mConnection, 0)) { + Log.e(TAG, "Could not bind service"); } - return true; } - /*package*/ void close() { - if (VDBG) log("close()"); + void close() { + Log.v(TAG, "close()"); + IBluetoothManager mgr = mAdapter.getBluetoothManager(); if (mgr != null) { try { mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); - } catch (Exception e) { - Log.e(TAG,"",e); + } catch (RemoteException e) { + e.printStackTrace(); } } synchronized (mConnection) { if (mService != null) { - try { - mService = null; - mContext.unbindService(mConnection); - } catch (Exception re) { - Log.e(TAG,"",re); - } + mService = null; + mContext.unbindService(mConnection); } } + mServiceListener = null; } - /** - * Initiate connection to a profile of the remote bluetooth device. - * - * <p> The system supports connection to multiple input devices. - * - * <p> This API returns false in scenarios like the profile on the - * device is already connected or Bluetooth is not turned on. - * When this API returns true, it is guaranteed that - * connection state intent for the profile will be broadcasted with - * the state. Users can get the connection state of the profile - * from this intent. - * - * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} - * permission. - * - * @param device Remote Bluetooth Device - * @return false on immediate error, - * true otherwise - * @hide - */ - public boolean connect(BluetoothDevice device) { - if (DBG) log("connect(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { - try { - return mService.connect(device); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; - } - } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); - return false; + @Override + public List<BluetoothDevice> getConnectedDevices() { + Log.v(TAG, "getConnectedDevices()"); + return null; } - /** - * Initiate disconnection from a profile - * - * <p> This API will return false in scenarios like the profile on the - * Bluetooth device is not in connected state etc. When this API returns, - * true, it is guaranteed that the connection state change - * intent will be broadcasted with the state. Users can get the - * disconnection state of the profile from this intent. - * - * <p> If the disconnection is initiated by a remote device, the state - * will transition from {@link #STATE_CONNECTED} to - * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the - * host (local) device the state will transition from - * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to - * state {@link #STATE_DISCONNECTED}. The transition to - * {@link #STATE_DISCONNECTING} can be used to distinguish between the - * two scenarios. - * - * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} - * permission. - * - * @param device Remote Bluetooth Device - * @return false on immediate error, - * true otherwise - * @hide - */ - public boolean disconnect(BluetoothDevice device) { - if (DBG) log("disconnect(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { - try { - return mService.disconnect(device); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; - } - } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); - return false; + @Override + public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { + Log.v(TAG, "getDevicesMatchingConnectionStates(): states=" + Arrays.toString(states)); + return null; } - /** - * {@inheritDoc} - */ - public List<BluetoothDevice> getConnectedDevices() { - if (VDBG) log("getConnectedDevices()"); - if (mService != null && isEnabled()) { - try { - return mService.getConnectedDevices(); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return new ArrayList<BluetoothDevice>(); - } - } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList<BluetoothDevice>(); + @Override + public int getConnectionState(BluetoothDevice device) { + Log.v(TAG, "getConnectionState(): device=" + device.getAddress()); + + return STATE_DISCONNECTED; } /** - * {@inheritDoc} - */ - public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { - if (VDBG) log("getDevicesMatchingStates()"); - if (mService != null && isEnabled()) { - try { - return mService.getDevicesMatchingConnectionStates(states); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return new ArrayList<BluetoothDevice>(); - } + * Registers application to be used for HID device. Connections to HID + * Device are only possible when application is registered. Only one + * application can be registered at time. When no longer used, application + * should be unregistered using + * {@link #unregisterApp(BluetoothHidDeviceAppConfiguration)}. + * + * @param sdp {@link BluetoothHidDeviceAppSdpSettings} object of + * HID Device SDP record. + * @param inQos {@link BluetoothHidDeviceAppQosSettings} object of + * Incoming QoS Settings. + * @param outQos {@link BluetoothHidDeviceAppQosSettings} object of + * Outgoing QoS Settings. + * @param callback {@link BluetoothHidDeviceCallback} object to which + * callback messages will be sent. + * @return + */ + public boolean registerApp(BluetoothHidDeviceAppSdpSettings sdp, + BluetoothHidDeviceAppQosSettings inQos, BluetoothHidDeviceAppQosSettings outQos, + BluetoothHidDeviceCallback callback) { + Log.v(TAG, "registerApp(): sdp=" + sdp + " inQos=" + inQos + " outQos=" + outQos + + " callback=" + callback); + + boolean result = false; + + if (sdp == null || callback == null) { + return false; } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList<BluetoothDevice>(); - } - /** - * {@inheritDoc} - */ - public int getConnectionState(BluetoothDevice device) { - if (VDBG) log("getState(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + if (mService != null) { try { - return mService.getConnectionState(device); + BluetoothHidDeviceAppConfiguration config = + new BluetoothHidDeviceAppConfiguration(); + BluetoothHidDeviceCallbackWrapper cbw = + new BluetoothHidDeviceCallbackWrapper(callback); + result = mService.registerApp(config, sdp, inQos, outQos, cbw); } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return BluetoothProfile.STATE_DISCONNECTED; + Log.e(TAG, e.toString()); } + } else { + Log.w(TAG, "Proxy not attached to service"); } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); - return BluetoothProfile.STATE_DISCONNECTED; + + return result; } /** - * Set priority of the profile + * Unregisters application. Active connection will be disconnected and no + * new connections will be allowed until registered again using + * {@link #registerApp(String, String, String, byte, byte[], BluetoothHidDeviceCallback)} * - * <p> The device should already be paired. - * Priority can be one of {@link #PRIORITY_ON} or - * {@link #PRIORITY_OFF}, + * @param config {@link BluetoothHidDeviceAppConfiguration} object as + * obtained from + * {@link BluetoothHidDeviceCallback#onAppStatusChanged(BluetoothDevice, + * BluetoothHidDeviceAppConfiguration, boolean)} * - * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} - * permission. - * - * @param device Paired bluetooth device - * @param priority - * @return true if priority is set, false on error - * @hide + * @return */ - public boolean setPriority(BluetoothDevice device, int priority) { - if (DBG) log("setPriority(" + device + ", " + priority + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { - if (priority != BluetoothProfile.PRIORITY_OFF && - priority != BluetoothProfile.PRIORITY_ON) { - return false; - } + public boolean unregisterApp(BluetoothHidDeviceAppConfiguration config) { + Log.v(TAG, "unregisterApp()"); + + boolean result = false; + + if (mService != null) { try { - return mService.setPriority(device, priority); + result = mService.unregisterApp(config); } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; + Log.e(TAG, e.toString()); } + } else { + Log.w(TAG, "Proxy not attached to service"); } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); - return false; + + return result; } /** - * Get the priority of the profile. - * - * <p> The priority can be any of: - * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF}, - * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED} - * - * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. + * Sends report to remote host using interrupt channel. * - * @param device Bluetooth device - * @return priority of the device - * @hide + * @param id Report Id, as defined in descriptor. Can be 0 in case Report Id + * are not defined in descriptor. + * @param data Report data, not including Report Id. + * @return */ - public int getPriority(BluetoothDevice device) { - if (VDBG) log("getPriority(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { - try { - return mService.getPriority(device); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return BluetoothProfile.PRIORITY_OFF; - } - } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); - return BluetoothProfile.PRIORITY_OFF; - } + public boolean sendReport(int id, byte[] data) { + Log.v(TAG, "sendReport(): id=" + id); - private final ServiceConnection mConnection = new ServiceConnection() { - public void onServiceConnected(ComponentName className, IBinder service) { - if (DBG) Log.d(TAG, "Proxy object connected"); - mService = IBluetoothInputDevice.Stub.asInterface(service); + boolean result = false; - if (mServiceListener != null) { - mServiceListener.onServiceConnected(BluetoothProfile.INPUT_DEVICE, BluetoothInputDevice.this); - } - } - public void onServiceDisconnected(ComponentName className) { - if (DBG) Log.d(TAG, "Proxy object disconnected"); - mService = null; - if (mServiceListener != null) { - mServiceListener.onServiceDisconnected(BluetoothProfile.INPUT_DEVICE); + if (mService != null) { + try { + result = mService.sendReport(id, data); + } catch (RemoteException e) { + Log.e(TAG, e.toString()); } + } else { + Log.w(TAG, "Proxy not attached to service"); } - }; - private boolean isEnabled() { - if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; - return false; + return result; } - private boolean isValidDevice(BluetoothDevice device) { - if (device == null) return false; - - if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; - return false; - } - - /** - * Initiate virtual unplug for a HID input device. - * - * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. + * Sends report to remote host as reply for GET_REPORT request from + * {@link BluetoothHidDeviceCallback#onGetReport(byte, byte, int)}. * - * @param device Remote Bluetooth Device - * @return false on immediate error, - * true otherwise - * @hide + * @param type Report Type, as in request. + * @param id Report Id, as in request. + * @param data Report data, not including Report Id. + * @return */ - public boolean virtualUnplug(BluetoothDevice device) { - if (DBG) log("virtualUnplug(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { - try { - return mService.virtualUnplug(device); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; - } - } + public boolean replyReport(byte type, byte id, byte[] data) { + Log.v(TAG, "replyReport(): type=" + type + " id=" + id); - if (mService == null) Log.w(TAG, "Proxy not attached to service"); - return false; + boolean result = false; - } - - /** - * Send Get_Protocol_Mode command to the connected HID input device. - * - * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. - * - * @param device Remote Bluetooth Device - * @return false on immediate error, - *true otherwise - * @hide - */ - public boolean getProtocolMode(BluetoothDevice device) { - if (VDBG) log("getProtocolMode(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + if (mService != null) { try { - return mService.getProtocolMode(device); + result = mService.replyReport(type, id, data); } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; + Log.e(TAG, e.toString()); } + } else { + Log.w(TAG, "Proxy not attached to service"); } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); - return false; + + return result; } /** - * Send Set_Protocol_Mode command to the connected HID input device. - * - * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. + * Sends error handshake message as reply for invalid SET_REPORT request + * from {@link BluetoothHidDeviceCallback#onSetReport(byte, byte, byte[])}. * - * @param device Remote Bluetooth Device - * @return false on immediate error, - * true otherwise - * @hide + * @param error Error to be sent for SET_REPORT via HANDSHAKE. + * @return */ - public boolean setProtocolMode(BluetoothDevice device, int protocolMode) { - if (DBG) log("setProtocolMode(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + public boolean reportError(byte error) { + Log.v(TAG, "reportError(): error = " + error); + + boolean result = false; + + if (mService != null) { try { - return mService.setProtocolMode(device, protocolMode); + result = mService.reportError(error); } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; + Log.e(TAG, e.toString()); } + } else { + Log.w(TAG, "Proxy not attached to service"); } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); - return false; + + return result; } /** - * Send Get_Report command to the connected HID input device. - * - * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. + * Sends Virtual Cable Unplug to currently connected host. * - * @param device Remote Bluetooth Device - * @param reportType Report type - * @param reportId Report ID - * @param bufferSize Report receiving buffer size - * @return false on immediate error, - * true otherwise - * @hide + * @return */ - public boolean getReport(BluetoothDevice device, byte reportType, byte reportId, int bufferSize) { - if (VDBG) log("getReport(" + device + "), reportType=" + reportType + " reportId=" + reportId + "bufferSize=" + bufferSize); - if (mService != null && isEnabled() && isValidDevice(device)) { + public boolean unplug() { + Log.v(TAG, "unplug()"); + + boolean result = false; + + if (mService != null) { try { - return mService.getReport(device, reportType, reportId, bufferSize); + result = mService.unplug(); } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; + Log.e(TAG, e.toString()); } + } else { + Log.w(TAG, "Proxy not attached to service"); } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); - return false; + + return result; } /** - * Send Set_Report command to the connected HID input device. + * Initiates connection to host which currently has Virtual Cable + * established with device. * - * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. - * - * @param device Remote Bluetooth Device - * @param reportType Report type - * @param report Report receiving buffer size - * @return false on immediate error, - * true otherwise - * @hide + * @return */ - public boolean setReport(BluetoothDevice device, byte reportType, String report) { - if (DBG) log("setReport(" + device + "), reportType=" + reportType + " report=" + report); - if (mService != null && isEnabled() && isValidDevice(device)) { + public boolean connect() { + Log.v(TAG, "connect()"); + + boolean result = false; + + if (mService != null) { try { - return mService.setReport(device, reportType, report); + result = mService.connect(); } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; + Log.e(TAG, e.toString()); } + } else { + Log.w(TAG, "Proxy not attached to service"); } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); - return false; + + return result; } /** - * Send Send_Data command to the connected HID input device. - * - * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. + * Disconnects from currently connected host. * - * @param device Remote Bluetooth Device - * @param data Data to send - * @return false on immediate error, - * true otherwise - * @hide + * @return */ - public boolean sendData(BluetoothDevice device, String report) { - if (DBG) log("sendData(" + device + "), report=" + report); - if (mService != null && isEnabled() && isValidDevice(device)) { + public boolean disconnect() { + Log.v(TAG, "disconnect()"); + + boolean result = false; + + if (mService != null) { try { - return mService.sendData(device, report); + result = mService.disconnect(); } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; + Log.e(TAG, e.toString()); } + } else { + Log.w(TAG, "Proxy not attached to service"); } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); - return false; - } - private static void log(String msg) { - Log.d(TAG, msg); + + return result; } } diff --git a/core/java/android/bluetooth/BluetoothHidDeviceAppConfiguration.aidl b/core/java/android/bluetooth/BluetoothHidDeviceAppConfiguration.aidl index bc9e54f..1af309c 100644 --- a/core/java/android/bluetooth/BluetoothHidDeviceAppConfiguration.aidl +++ b/core/java/android/bluetooth/BluetoothHidDeviceAppConfiguration.aidl @@ -1,4 +1,6 @@ /* +** Copyright (C) 2013 The Linux Foundation. All rights reserved +** Not a Contribution. ** Copyright 2011, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,4 +18,4 @@ package android.bluetooth; -parcelable BluetoothHealthAppConfiguration; +parcelable BluetoothHidDeviceAppConfiguration; diff --git a/core/java/android/bluetooth/BluetoothHidDeviceAppConfiguration.java b/core/java/android/bluetooth/BluetoothHidDeviceAppConfiguration.java index 15a9101..9f3cd3c 100644 --- a/core/java/android/bluetooth/BluetoothHidDeviceAppConfiguration.java +++ b/core/java/android/bluetooth/BluetoothHidDeviceAppConfiguration.java @@ -1,4 +1,6 @@ /* + * Copyright (C) 2013 The Linux Foundation. All rights reserved + * Not a Contribution. * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,152 +16,57 @@ * limitations under the License. */ - package android.bluetooth; import android.os.Parcel; import android.os.Parcelable; -/** - * The Bluetooth Health Application Configuration that is used in conjunction with - * the {@link BluetoothHealth} class. This class represents an application configuration - * that the Bluetooth Health third party application will register to communicate with the - * remote Bluetooth health device. - * - */ -public final class BluetoothHealthAppConfiguration implements Parcelable { - private final String mName; - private final int mDataType; - private final int mRole; - private final int mChannelType; +import java.util.Random; - /** - * Constructor to register the SINK role - * - * @param name Friendly name associated with the application configuration - * @param dataType Data Type of the remote Bluetooth Health device - * @hide - */ - BluetoothHealthAppConfiguration(String name, int dataType) { - mName = name; - mDataType = dataType; - mRole = BluetoothHealth.SINK_ROLE; - mChannelType = BluetoothHealth.CHANNEL_TYPE_ANY; +/** @hide */ +public final class BluetoothHidDeviceAppConfiguration implements Parcelable { + private final long mHash; + + BluetoothHidDeviceAppConfiguration() { + Random rnd = new Random(); + mHash = rnd.nextLong(); } - /** - * Constructor to register the application configuration. - * - * @param name Friendly name associated with the application configuration - * @param dataType Data Type of the remote Bluetooth Health device - * @param role {@link BluetoothHealth#SOURCE_ROLE} or - * {@link BluetoothHealth#SINK_ROLE} - * @hide - */ - BluetoothHealthAppConfiguration(String name, int dataType, int role, int - channelType) { - mName = name; - mDataType = dataType; - mRole = role; - mChannelType = channelType; + BluetoothHidDeviceAppConfiguration(long hash) { + mHash = hash; } @Override public boolean equals(Object o) { - if (o instanceof BluetoothHealthAppConfiguration) { - BluetoothHealthAppConfiguration config = (BluetoothHealthAppConfiguration) o; - // config.getName() can never be NULL - return mName.equals(config.getName()) && - mDataType == config.getDataType() && - mRole == config.getRole() && - mChannelType == config.getChannelType(); + if (o instanceof BluetoothHidDeviceAppConfiguration) { + BluetoothHidDeviceAppConfiguration config = (BluetoothHidDeviceAppConfiguration) o; + return mHash == config.mHash; } return false; } @Override - public int hashCode() { - int result = 17; - result = 31 * result + (mName != null ? mName.hashCode() : 0); - result = 31 * result + mDataType; - result = 31 * result + mRole; - result = 31 * result + mChannelType; - return result; - } - - @Override - public String toString() { - return "BluetoothHealthAppConfiguration [mName = " + mName + - ",mDataType = " + mDataType + ", mRole = " + mRole + ",mChannelType = " + - mChannelType + "]"; - } - public int describeContents() { return 0; } - /** - * Return the data type associated with this application configuration. - * - * @return dataType - */ - public int getDataType() { - return mDataType; - } - - /** - * Return the name of the application configuration. - * - * @return String name - */ - public String getName() { - return mName; - } - - /** - * Return the role associated with this application configuration. - * - * @return One of {@link BluetoothHealth#SOURCE_ROLE} or - * {@link BluetoothHealth#SINK_ROLE} - */ - public int getRole() { - return mRole; - } - - /** - * Return the channel type associated with this application configuration. - * - * @return One of {@link BluetoothHealth#CHANNEL_TYPE_RELIABLE} or - * {@link BluetoothHealth#CHANNEL_TYPE_STREAMING} or - * {@link BluetoothHealth#CHANNEL_TYPE_ANY}. - * @hide - */ - public int getChannelType() { - return mChannelType; - } + public static final Parcelable.Creator<BluetoothHidDeviceAppConfiguration> CREATOR = + new Parcelable.Creator<BluetoothHidDeviceAppConfiguration>() { - public static final Parcelable.Creator<BluetoothHealthAppConfiguration> CREATOR = - new Parcelable.Creator<BluetoothHealthAppConfiguration>() { @Override - public BluetoothHealthAppConfiguration createFromParcel(Parcel in) { - String name = in.readString(); - int type = in.readInt(); - int role = in.readInt(); - int channelType = in.readInt(); - return new BluetoothHealthAppConfiguration(name, type, role, - channelType); + public BluetoothHidDeviceAppConfiguration createFromParcel(Parcel in) { + long hash = in.readLong(); + return new BluetoothHidDeviceAppConfiguration(hash); } @Override - public BluetoothHealthAppConfiguration[] newArray(int size) { - return new BluetoothHealthAppConfiguration[size]; + public BluetoothHidDeviceAppConfiguration[] newArray(int size) { + return new BluetoothHidDeviceAppConfiguration[size]; } }; + @Override public void writeToParcel(Parcel out, int flags) { - out.writeString(mName); - out.writeInt(mDataType); - out.writeInt(mRole); - out.writeInt(mChannelType); + out.writeLong(mHash); } } diff --git a/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.aidl b/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.aidl index bc9e54f..ae93235 100644 --- a/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.aidl +++ b/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.aidl @@ -1,4 +1,6 @@ /* +** Copyright (C) 2013 The Linux Foundation. All rights reserved +** Not a Contribution. ** Copyright 2011, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,4 +18,4 @@ package android.bluetooth; -parcelable BluetoothHealthAppConfiguration; +parcelable BluetoothHidDeviceAppQosSettings; diff --git a/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.java b/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.java index 15a9101..a4044d9 100644 --- a/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.java +++ b/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.java @@ -1,4 +1,6 @@ /* + * Copyright (C) 2013 The Linux Foundation. All rights reserved + * Not a Contribution. * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,152 +16,84 @@ * limitations under the License. */ - package android.bluetooth; import android.os.Parcel; import android.os.Parcelable; -/** - * The Bluetooth Health Application Configuration that is used in conjunction with - * the {@link BluetoothHealth} class. This class represents an application configuration - * that the Bluetooth Health third party application will register to communicate with the - * remote Bluetooth health device. - * - */ -public final class BluetoothHealthAppConfiguration implements Parcelable { - private final String mName; - private final int mDataType; - private final int mRole; - private final int mChannelType; - - /** - * Constructor to register the SINK role - * - * @param name Friendly name associated with the application configuration - * @param dataType Data Type of the remote Bluetooth Health device - * @hide - */ - BluetoothHealthAppConfiguration(String name, int dataType) { - mName = name; - mDataType = dataType; - mRole = BluetoothHealth.SINK_ROLE; - mChannelType = BluetoothHealth.CHANNEL_TYPE_ANY; - } - - /** - * Constructor to register the application configuration. - * - * @param name Friendly name associated with the application configuration - * @param dataType Data Type of the remote Bluetooth Health device - * @param role {@link BluetoothHealth#SOURCE_ROLE} or - * {@link BluetoothHealth#SINK_ROLE} - * @hide - */ - BluetoothHealthAppConfiguration(String name, int dataType, int role, int - channelType) { - mName = name; - mDataType = dataType; - mRole = role; - mChannelType = channelType; +import java.util.Random; + +/** @hide */ +public final class BluetoothHidDeviceAppQosSettings implements Parcelable { + + final public int serviceType; + final public int tokenRate; + final public int tokenBucketSize; + final public int peakBandwidth; + final public int latency; + final public int delayVariation; + + final static public int SERVICE_NO_TRAFFIC = 0x00; + final static public int SERVICE_BEST_EFFORT = 0x01; + final static public int SERVICE_GUARANTEED = 0x02; + + final static public int MAX = (int) 0xffffffff; + + public BluetoothHidDeviceAppQosSettings(int serviceType, int tokenRate, int tokenBucketSize, + int peakBandwidth, + int latency, int delayVariation) { + this.serviceType = serviceType; + this.tokenRate = tokenRate; + this.tokenBucketSize = tokenBucketSize; + this.peakBandwidth = peakBandwidth; + this.latency = latency; + this.delayVariation = delayVariation; } @Override public boolean equals(Object o) { - if (o instanceof BluetoothHealthAppConfiguration) { - BluetoothHealthAppConfiguration config = (BluetoothHealthAppConfiguration) o; - // config.getName() can never be NULL - return mName.equals(config.getName()) && - mDataType == config.getDataType() && - mRole == config.getRole() && - mChannelType == config.getChannelType(); + if (o instanceof BluetoothHidDeviceAppQosSettings) { + BluetoothHidDeviceAppQosSettings qos = (BluetoothHidDeviceAppQosSettings) o; + return false; } return false; } @Override - public int hashCode() { - int result = 17; - result = 31 * result + (mName != null ? mName.hashCode() : 0); - result = 31 * result + mDataType; - result = 31 * result + mRole; - result = 31 * result + mChannelType; - return result; - } - - @Override - public String toString() { - return "BluetoothHealthAppConfiguration [mName = " + mName + - ",mDataType = " + mDataType + ", mRole = " + mRole + ",mChannelType = " + - mChannelType + "]"; - } - public int describeContents() { return 0; } - /** - * Return the data type associated with this application configuration. - * - * @return dataType - */ - public int getDataType() { - return mDataType; - } + public static final Parcelable.Creator<BluetoothHidDeviceAppQosSettings> CREATOR = + new Parcelable.Creator<BluetoothHidDeviceAppQosSettings>() { - /** - * Return the name of the application configuration. - * - * @return String name - */ - public String getName() { - return mName; - } - - /** - * Return the role associated with this application configuration. - * - * @return One of {@link BluetoothHealth#SOURCE_ROLE} or - * {@link BluetoothHealth#SINK_ROLE} - */ - public int getRole() { - return mRole; - } - - /** - * Return the channel type associated with this application configuration. - * - * @return One of {@link BluetoothHealth#CHANNEL_TYPE_RELIABLE} or - * {@link BluetoothHealth#CHANNEL_TYPE_STREAMING} or - * {@link BluetoothHealth#CHANNEL_TYPE_ANY}. - * @hide - */ - public int getChannelType() { - return mChannelType; - } - - public static final Parcelable.Creator<BluetoothHealthAppConfiguration> CREATOR = - new Parcelable.Creator<BluetoothHealthAppConfiguration>() { @Override - public BluetoothHealthAppConfiguration createFromParcel(Parcel in) { - String name = in.readString(); - int type = in.readInt(); - int role = in.readInt(); - int channelType = in.readInt(); - return new BluetoothHealthAppConfiguration(name, type, role, - channelType); + public BluetoothHidDeviceAppQosSettings createFromParcel(Parcel in) { + + return new BluetoothHidDeviceAppQosSettings(in.readInt(), in.readInt(), in.readInt(), + in.readInt(), + in.readInt(), in.readInt()); } @Override - public BluetoothHealthAppConfiguration[] newArray(int size) { - return new BluetoothHealthAppConfiguration[size]; + public BluetoothHidDeviceAppQosSettings[] newArray(int size) { + return new BluetoothHidDeviceAppQosSettings[size]; } }; + @Override public void writeToParcel(Parcel out, int flags) { - out.writeString(mName); - out.writeInt(mDataType); - out.writeInt(mRole); - out.writeInt(mChannelType); + out.writeInt(serviceType); + out.writeInt(tokenRate); + out.writeInt(tokenBucketSize); + out.writeInt(peakBandwidth); + out.writeInt(latency); + out.writeInt(delayVariation); + } + + public int[] toArray() { + return new int[] { + serviceType, tokenRate, tokenBucketSize, peakBandwidth, latency, delayVariation + }; } } diff --git a/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.aidl b/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.aidl index bc9e54f..38ac1ec 100644 --- a/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.aidl +++ b/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.aidl @@ -1,4 +1,6 @@ /* +** Copyright (C) 2013 The Linux Foundation. All rights reserved +** Not a Contribution. ** Copyright 2011, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,4 +18,4 @@ package android.bluetooth; -parcelable BluetoothHealthAppConfiguration; +parcelable BluetoothHidDeviceAppSdpSettings; diff --git a/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java b/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java index 15a9101..db88f0d 100644 --- a/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java +++ b/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java @@ -1,4 +1,6 @@ /* + * Copyright (C) 2013 The Linux Foundation. All rights reserved + * Not a Contribution. * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,152 +16,67 @@ * limitations under the License. */ - package android.bluetooth; import android.os.Parcel; import android.os.Parcelable; -/** - * The Bluetooth Health Application Configuration that is used in conjunction with - * the {@link BluetoothHealth} class. This class represents an application configuration - * that the Bluetooth Health third party application will register to communicate with the - * remote Bluetooth health device. - * - */ -public final class BluetoothHealthAppConfiguration implements Parcelable { - private final String mName; - private final int mDataType; - private final int mRole; - private final int mChannelType; +import java.util.Random; - /** - * Constructor to register the SINK role - * - * @param name Friendly name associated with the application configuration - * @param dataType Data Type of the remote Bluetooth Health device - * @hide - */ - BluetoothHealthAppConfiguration(String name, int dataType) { - mName = name; - mDataType = dataType; - mRole = BluetoothHealth.SINK_ROLE; - mChannelType = BluetoothHealth.CHANNEL_TYPE_ANY; - } +/** @hide */ +public final class BluetoothHidDeviceAppSdpSettings implements Parcelable { + + final public String name; + final public String description; + final public String provider; + final public byte subclass; + final public byte[] descriptors; - /** - * Constructor to register the application configuration. - * - * @param name Friendly name associated with the application configuration - * @param dataType Data Type of the remote Bluetooth Health device - * @param role {@link BluetoothHealth#SOURCE_ROLE} or - * {@link BluetoothHealth#SINK_ROLE} - * @hide - */ - BluetoothHealthAppConfiguration(String name, int dataType, int role, int - channelType) { - mName = name; - mDataType = dataType; - mRole = role; - mChannelType = channelType; + public BluetoothHidDeviceAppSdpSettings(String name, String description, String provider, + byte subclass, byte[] descriptors) { + this.name = name; + this.description = description; + this.provider = provider; + this.subclass = subclass; + this.descriptors = descriptors.clone(); } @Override public boolean equals(Object o) { - if (o instanceof BluetoothHealthAppConfiguration) { - BluetoothHealthAppConfiguration config = (BluetoothHealthAppConfiguration) o; - // config.getName() can never be NULL - return mName.equals(config.getName()) && - mDataType == config.getDataType() && - mRole == config.getRole() && - mChannelType == config.getChannelType(); + if (o instanceof BluetoothHidDeviceAppSdpSettings) { + BluetoothHidDeviceAppSdpSettings sdp = (BluetoothHidDeviceAppSdpSettings) o; + return false; } return false; } @Override - public int hashCode() { - int result = 17; - result = 31 * result + (mName != null ? mName.hashCode() : 0); - result = 31 * result + mDataType; - result = 31 * result + mRole; - result = 31 * result + mChannelType; - return result; - } - - @Override - public String toString() { - return "BluetoothHealthAppConfiguration [mName = " + mName + - ",mDataType = " + mDataType + ", mRole = " + mRole + ",mChannelType = " + - mChannelType + "]"; - } - public int describeContents() { return 0; } - /** - * Return the data type associated with this application configuration. - * - * @return dataType - */ - public int getDataType() { - return mDataType; - } - - /** - * Return the name of the application configuration. - * - * @return String name - */ - public String getName() { - return mName; - } - - /** - * Return the role associated with this application configuration. - * - * @return One of {@link BluetoothHealth#SOURCE_ROLE} or - * {@link BluetoothHealth#SINK_ROLE} - */ - public int getRole() { - return mRole; - } + public static final Parcelable.Creator<BluetoothHidDeviceAppSdpSettings> CREATOR = + new Parcelable.Creator<BluetoothHidDeviceAppSdpSettings>() { - /** - * Return the channel type associated with this application configuration. - * - * @return One of {@link BluetoothHealth#CHANNEL_TYPE_RELIABLE} or - * {@link BluetoothHealth#CHANNEL_TYPE_STREAMING} or - * {@link BluetoothHealth#CHANNEL_TYPE_ANY}. - * @hide - */ - public int getChannelType() { - return mChannelType; - } - - public static final Parcelable.Creator<BluetoothHealthAppConfiguration> CREATOR = - new Parcelable.Creator<BluetoothHealthAppConfiguration>() { @Override - public BluetoothHealthAppConfiguration createFromParcel(Parcel in) { - String name = in.readString(); - int type = in.readInt(); - int role = in.readInt(); - int channelType = in.readInt(); - return new BluetoothHealthAppConfiguration(name, type, role, - channelType); + public BluetoothHidDeviceAppSdpSettings createFromParcel(Parcel in) { + + return new BluetoothHidDeviceAppSdpSettings(in.readString(), in.readString(), + in.readString(), in.readByte(), in.createByteArray()); } @Override - public BluetoothHealthAppConfiguration[] newArray(int size) { - return new BluetoothHealthAppConfiguration[size]; + public BluetoothHidDeviceAppSdpSettings[] newArray(int size) { + return new BluetoothHidDeviceAppSdpSettings[size]; } }; + @Override public void writeToParcel(Parcel out, int flags) { - out.writeString(mName); - out.writeInt(mDataType); - out.writeInt(mRole); - out.writeInt(mChannelType); + out.writeString(name); + out.writeString(description); + out.writeString(provider); + out.writeByte(subclass); + out.writeByteArray(descriptors); } } diff --git a/core/java/android/bluetooth/BluetoothHidDeviceCallback.java b/core/java/android/bluetooth/BluetoothHidDeviceCallback.java index baf2ade..cc60833 100644 --- a/core/java/android/bluetooth/BluetoothHidDeviceCallback.java +++ b/core/java/android/bluetooth/BluetoothHidDeviceCallback.java @@ -1,4 +1,6 @@ /* + * Copyright (C) 2013 The Linux Foundation. All rights reserved + * Not a Contribution. * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,55 +16,113 @@ * limitations under the License. */ - package android.bluetooth; -import android.os.ParcelFileDescriptor; import android.util.Log; -/** - * This abstract class is used to implement {@link BluetoothHealth} callbacks. - */ -public abstract class BluetoothHealthCallback { - private static final String TAG = "BluetoothHealthCallback"; +/** @hide */ +public abstract class BluetoothHidDeviceCallback { + + private static final String TAG = BluetoothHidDeviceCallback.class.getSimpleName(); + + /** + * Callback called when application registration state changes. Usually it's + * called due to either + * {@link BluetoothHidDevice#registerApp(String, String, String, byte, byte[], + * BluetoothHidDeviceCallback)} + * or + * {@link BluetoothHidDevice#unregisterApp(BluetoothHidDeviceAppConfiguration)} + * , but can be also unsolicited in case e.g. Bluetooth was turned off in + * which case application is unregistered automatically. + * + * @param pluggedDevice {@link BluetoothDevice} object which represents host + * that currently has Virtual Cable established with device. Only + * valid when application is registered, can be <code>null</code> + * . + * @param config {@link BluetoothHidDeviceAppConfiguration} object which + * represents token required to unregister application using + * {@link BluetoothHidDevice#unregisterApp(BluetoothHidDeviceAppConfiguration)} + * . + * @param registered <code>true</code> if application is registered, + * <code>false</code> otherwise. + */ + public void onAppStatusChanged(BluetoothDevice pluggedDevice, + BluetoothHidDeviceAppConfiguration config, boolean registered) { + Log.d(TAG, "onAppStatusChanged: pluggedDevice=" + (pluggedDevice == null ? + null : pluggedDevice.toString()) + " registered=" + registered); + } /** - * Callback to inform change in registration state of the health - * application. - * <p> This callback is called on the binder thread (not on the UI thread) + * Callback called when connection state with remote host was changed. + * Application can assume than Virtual Cable is established when called with + * {@link BluetoothProfile#STATE_CONNECTED} <code>state</code>. * - * @param config Bluetooth Health app configuration - * @param status Success or failure of the registration or unregistration - * calls. Can be one of - * {@link BluetoothHealth#APP_CONFIG_REGISTRATION_SUCCESS} or - * {@link BluetoothHealth#APP_CONFIG_REGISTRATION_FAILURE} or - * {@link BluetoothHealth#APP_CONFIG_UNREGISTRATION_SUCCESS} or - * {@link BluetoothHealth#APP_CONFIG_UNREGISTRATION_FAILURE} + * @param device {@link BluetoothDevice} object representing host device + * which connection state was changed. + * @param state Connection state as defined in {@link BluetoothProfile}. */ - public void onHealthAppConfigurationStatusChange(BluetoothHealthAppConfiguration config, - int status) { - Log.d(TAG, "onHealthAppConfigurationStatusChange: " + config + "Status: " + status); + public void onConnectionStateChanged(BluetoothDevice device, int state) { + Log.d(TAG, "onConnectionStateChanged: device=" + device.toString() + " state=" + state); } /** - * Callback to inform change in channel state. - * <p> Its the responsibility of the implementor of this callback to close the - * parcel file descriptor when done. This callback is called on the Binder - * thread (not the UI thread) + * Callback called when GET_REPORT is received from remote host. Should be + * replied by application using + * {@link BluetoothHidDevice#replyReport(byte, byte, byte[])}. * - * @param config The Health app configutation - * @param device The Bluetooth Device - * @param prevState The previous state of the channel - * @param newState The new state of the channel. - * @param fd The Parcel File Descriptor when the channel state is connected. - * @param channelId The id associated with the channel. This id will be used - * in future calls like when disconnecting the channel. + * @param type Requested Report Type. + * @param id Requested Report Id, can be 0 if no Report Id are defined in + * descriptor. + * @param bufferSize Requested buffer size, application shall respond with + * at least given number of bytes. + */ + public void onGetReport(byte type, byte id, int bufferSize) { + Log.d(TAG, "onGetReport: type=" + type + " id=" + id + " bufferSize=" + bufferSize); + } + + /** + * Callback called when SET_REPORT is received from remote host. In case + * received data are invalid, application shall respond with + * {@link BluetoothHidDevice#reportError()}. + * + * @param type Report Type. + * @param id Report Id. + * @param data Report data. + */ + public void onSetReport(byte type, byte id, byte[] data) { + Log.d(TAG, "onSetReport: type=" + type + " id=" + id); + } + + /** + * Callback called when SET_PROTOCOL is received from remote host. + * Application shall use this information to send only reports valid for + * given protocol mode. By default, + * {@link BluetoothHidDevice#PROTOCOL_REPORT_MODE} shall be assumed. + * + * @param protocol Protocol Mode. + */ + public void onSetProtocol(byte protocol) { + Log.d(TAG, "onSetProtocol: protocol=" + protocol); + } + + /** + * Callback called when report data is received over interrupt channel. + * Report Type is assumed to be + * {@link BluetoothHidDevice#REPORT_TYPE_OUTPUT}. + * + * @param reportId Report Id. + * @param data Report data. + */ + public void onIntrData(byte reportId, byte[] data) { + Log.d(TAG, "onIntrData: reportId=" + reportId); + } + + /** + * Callback called when Virtual Cable is removed. This can be either due to + * {@link BluetoothHidDevice#unplug()} or request from remote side. After + * this callback is received connection will be disconnected automatically. */ - public void onHealthChannelStateChange(BluetoothHealthAppConfiguration config, - BluetoothDevice device, int prevState, int newState, ParcelFileDescriptor fd, - int channelId) { - Log.d(TAG, "onHealthChannelStateChange: " + config + "Device: " + device + - "prevState:" + prevState + "newState:" + newState + "ParcelFd:" + fd + - "ChannelId:" + channelId); + public void onVirtualCableUnplug() { + Log.d(TAG, "onVirtualCableUnplug"); } } diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java index cbce22c..674b4fb 100644 --- a/core/java/android/bluetooth/BluetoothProfile.java +++ b/core/java/android/bluetooth/BluetoothProfile.java @@ -131,6 +131,12 @@ public interface BluetoothProfile { public static final int HEADSET_CLIENT = 16; /** + * HID device + * @hide + */ + public static final int HID_DEVICE = 17; + + /** * Default priority for devices that we try to auto-connect to and * and allow incoming connections for the profile * @hide diff --git a/core/java/android/bluetooth/IBluetoothHidDevice.aidl b/core/java/android/bluetooth/IBluetoothHidDevice.aidl index 1ebb9ca..60358c5 100644 --- a/core/java/android/bluetooth/IBluetoothHidDevice.aidl +++ b/core/java/android/bluetooth/IBluetoothHidDevice.aidl @@ -1,4 +1,6 @@ /* + * Copyright (C) 2013 The Linux Foundation. All rights reserved + * Not a Contribution. * Copyright (C) 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,43 +19,21 @@ package android.bluetooth; import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothHidDeviceAppConfiguration; +import android.bluetooth.IBluetoothHidDeviceCallback; +import android.bluetooth.BluetoothHidDeviceAppSdpSettings; +import android.bluetooth.BluetoothHidDeviceAppQosSettings; -/** - * API for Bluetooth HID service - * - * {@hide} - */ -interface IBluetoothInputDevice { - // Public API - boolean connect(in BluetoothDevice device); - boolean disconnect(in BluetoothDevice device); - List<BluetoothDevice> getConnectedDevices(); - List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states); - int getConnectionState(in BluetoothDevice device); - boolean setPriority(in BluetoothDevice device, int priority); - int getPriority(in BluetoothDevice device); - /** - * @hide - */ - boolean getProtocolMode(in BluetoothDevice device); - /** - * @hide - */ - boolean virtualUnplug(in BluetoothDevice device); - /** - * @hide - */ - boolean setProtocolMode(in BluetoothDevice device, int protocolMode); - /** - * @hide - */ - boolean getReport(in BluetoothDevice device, byte reportType, byte reportId, int bufferSize); - /** - * @hide - */ - boolean setReport(in BluetoothDevice device, byte reportType, String report); - /** - * @hide - */ - boolean sendData(in BluetoothDevice device, String report); +/** @hide */ +interface IBluetoothHidDevice { + boolean registerApp(in BluetoothHidDeviceAppConfiguration config, + in BluetoothHidDeviceAppSdpSettings sdp, in BluetoothHidDeviceAppQosSettings inQos, + in BluetoothHidDeviceAppQosSettings outQos, in IBluetoothHidDeviceCallback callback); + boolean unregisterApp(in BluetoothHidDeviceAppConfiguration config); + boolean sendReport(in int id, in byte[] data); + boolean replyReport(in byte type, in byte id, in byte[] data); + boolean reportError(byte error); + boolean unplug(); + boolean connect(); + boolean disconnect(); } diff --git a/core/java/android/bluetooth/IBluetoothHidDeviceCallback.aidl b/core/java/android/bluetooth/IBluetoothHidDeviceCallback.aidl index 0ace9fe..7c71a17 100644 --- a/core/java/android/bluetooth/IBluetoothHidDeviceCallback.aidl +++ b/core/java/android/bluetooth/IBluetoothHidDeviceCallback.aidl @@ -1,11 +1,13 @@ /* + * Copyright (C) 2013 The Linux Foundation. All rights reserved + * Not a Contribution. * Copyright (C) 2011, The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -17,16 +19,15 @@ package android.bluetooth; import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothHealthAppConfiguration; -import android.os.ParcelFileDescriptor; +import android.bluetooth.BluetoothHidDeviceAppConfiguration; -/** - *@hide - */ -interface IBluetoothHealthCallback -{ - void onHealthAppConfigurationStatusChange(in BluetoothHealthAppConfiguration config, int status); - void onHealthChannelStateChange(in BluetoothHealthAppConfiguration config, - in BluetoothDevice device, int prevState, int newState, in - ParcelFileDescriptor fd, int id); +/** @hide */ +interface IBluetoothHidDeviceCallback { + void onAppStatusChanged(in BluetoothDevice device, in BluetoothHidDeviceAppConfiguration config, boolean registered); + void onConnectionStateChanged(in BluetoothDevice device, in int state); + void onGetReport(in byte type, in byte id, in int bufferSize); + void onSetReport(in byte type, in byte id, in byte[] data); + void onSetProtocol(in byte protocol); + void onIntrData(in byte reportId, in byte[] data); + void onVirtualCableUnplug(); } |