Merge "Make Bluetooth Health APIs public."
This commit is contained in:
committed by
Android (Google) Code Review
commit
cedd460820
@ -4528,6 +4528,44 @@ package android.bluetooth {
|
|||||||
field public static final java.lang.String VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY = "android.bluetooth.headset.intent.category.companyid";
|
field public static final java.lang.String VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY = "android.bluetooth.headset.intent.category.companyid";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class BluetoothHealth implements android.bluetooth.BluetoothProfile {
|
||||||
|
method public boolean connectChannelToSource(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothHealthAppConfiguration);
|
||||||
|
method public boolean disconnectChannel(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothHealthAppConfiguration, int);
|
||||||
|
method public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
|
||||||
|
method public int getConnectionState(android.bluetooth.BluetoothDevice);
|
||||||
|
method public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
|
||||||
|
method public android.os.ParcelFileDescriptor getMainChannelFd(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothHealthAppConfiguration);
|
||||||
|
method public boolean registerSinkAppConfiguration(java.lang.String, int, android.bluetooth.BluetoothHealthCallback);
|
||||||
|
method public boolean unregisterAppConfiguration(android.bluetooth.BluetoothHealthAppConfiguration);
|
||||||
|
field public static final int APP_CONFIG_REGISTRATION_FAILURE = 1; // 0x1
|
||||||
|
field public static final int APP_CONFIG_REGISTRATION_SUCCESS = 0; // 0x0
|
||||||
|
field public static final int APP_CONFIG_UNREGISTRATION_FAILURE = 3; // 0x3
|
||||||
|
field public static final int APP_CONFIG_UNREGISTRATION_SUCCESS = 2; // 0x2
|
||||||
|
field public static final int CHANNEL_TYPE_RELIABLE = 10; // 0xa
|
||||||
|
field public static final int CHANNEL_TYPE_STREAMING = 11; // 0xb
|
||||||
|
field public static final int SINK_ROLE = 2; // 0x2
|
||||||
|
field public static final int SOURCE_ROLE = 1; // 0x1
|
||||||
|
field public static final int STATE_CHANNEL_CONNECTED = 2; // 0x2
|
||||||
|
field public static final int STATE_CHANNEL_CONNECTING = 1; // 0x1
|
||||||
|
field public static final int STATE_CHANNEL_DISCONNECTED = 0; // 0x0
|
||||||
|
field public static final int STATE_CHANNEL_DISCONNECTING = 3; // 0x3
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class BluetoothHealthAppConfiguration implements android.os.Parcelable {
|
||||||
|
method public int describeContents();
|
||||||
|
method public int getDataType();
|
||||||
|
method public java.lang.String getName();
|
||||||
|
method public int getRole();
|
||||||
|
method public void writeToParcel(android.os.Parcel, int);
|
||||||
|
field public static final android.os.Parcelable.Creator CREATOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class BluetoothHealthCallback {
|
||||||
|
ctor public BluetoothHealthCallback();
|
||||||
|
method public void onHealthAppConfigurationStatusChange(android.bluetooth.BluetoothHealthAppConfiguration, int);
|
||||||
|
method public void onHealthChannelStateChange(android.bluetooth.BluetoothHealthAppConfiguration, android.bluetooth.BluetoothDevice, int, int, android.os.ParcelFileDescriptor, int);
|
||||||
|
}
|
||||||
|
|
||||||
public abstract interface BluetoothProfile {
|
public abstract interface BluetoothProfile {
|
||||||
method public abstract java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
|
method public abstract java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
|
||||||
method public abstract int getConnectionState(android.bluetooth.BluetoothDevice);
|
method public abstract int getConnectionState(android.bluetooth.BluetoothDevice);
|
||||||
|
@ -32,10 +32,25 @@ import java.util.List;
|
|||||||
* <p>BluetoothHealth is a proxy object for controlling the Bluetooth
|
* <p>BluetoothHealth is a proxy object for controlling the Bluetooth
|
||||||
* Service via IPC.
|
* Service via IPC.
|
||||||
*
|
*
|
||||||
* <p> Use {@link BluetoothAdapter#getProfileProxy} to get
|
* <p> How to connect to a health device which is acting in the source role.
|
||||||
* the BluetoothHealth proxy object. Use
|
* <li> Use {@link BluetoothAdapter#getProfileProxy} to get
|
||||||
* {@link BluetoothAdapter#closeProfileProxy} to close the service connection.
|
* the BluetoothHealth proxy object. </li>
|
||||||
* @hide
|
* <li> Create an {@link BluetoothHealth} callback and call
|
||||||
|
* {@link #registerSinkAppConfiguration} to register an application
|
||||||
|
* configuration </li>
|
||||||
|
* <li> Pair with the remote device. This currently needs to be done manually
|
||||||
|
* from Bluetooth Settings </li>
|
||||||
|
* <li> Connect to a health device using {@link #connectChannelToSource}. Some
|
||||||
|
* devices will connect the channel automatically. The {@link BluetoothHealth}
|
||||||
|
* callback will inform the application of channel state change. </li>
|
||||||
|
* <li> Use the file descriptor provided with a connected channel to read and
|
||||||
|
* write data to the health channel. </li>
|
||||||
|
* <li> The received data needs to be interpreted using a health manager which
|
||||||
|
* implements the IEEE 11073-xxxxx specifications.
|
||||||
|
* <li> When done, close the health channel by calling {@link #disconnectChannel}
|
||||||
|
* and unregister the application configuration calling
|
||||||
|
* {@link #unregisterAppConfiguration}
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public final class BluetoothHealth implements BluetoothProfile {
|
public final class BluetoothHealth implements BluetoothProfile {
|
||||||
private static final String TAG = "BluetoothHealth";
|
private static final String TAG = "BluetoothHealth";
|
||||||
@ -137,7 +152,6 @@ public final class BluetoothHealth implements BluetoothProfile {
|
|||||||
*
|
*
|
||||||
* @param config The health app configuration
|
* @param config The health app configuration
|
||||||
* @return Success or failure.
|
* @return Success or failure.
|
||||||
* @hide
|
|
||||||
*/
|
*/
|
||||||
public boolean unregisterAppConfiguration(BluetoothHealthAppConfiguration config) {
|
public boolean unregisterAppConfiguration(BluetoothHealthAppConfiguration config) {
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
@ -222,16 +236,15 @@ public final class BluetoothHealth implements BluetoothProfile {
|
|||||||
* @param device The remote Bluetooth device.
|
* @param device The remote Bluetooth device.
|
||||||
* @param config The application configuration which has been registered using
|
* @param config The application configuration which has been registered using
|
||||||
* {@link #registerSinkAppConfiguration(String, int, BluetoothHealthCallback) }
|
* {@link #registerSinkAppConfiguration(String, int, BluetoothHealthCallback) }
|
||||||
* @param fd The file descriptor that was associated with the channel.
|
* @param channelId The channel id associated with the channel
|
||||||
* @return If true, the callback associated with the application config will be called.
|
* @return If true, the callback associated with the application config will be called.
|
||||||
* @hide
|
|
||||||
*/
|
*/
|
||||||
public boolean disconnectChannel(BluetoothDevice device,
|
public boolean disconnectChannel(BluetoothDevice device,
|
||||||
BluetoothHealthAppConfiguration config, ParcelFileDescriptor fd) {
|
BluetoothHealthAppConfiguration config, int channelId) {
|
||||||
if (mService != null && isEnabled() && isValidDevice(device) &&
|
if (mService != null && isEnabled() && isValidDevice(device) &&
|
||||||
config != null) {
|
config != null) {
|
||||||
try {
|
try {
|
||||||
return mService.disconnectChannel(device, config, fd);
|
return mService.disconnectChannel(device, config, channelId);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.e(TAG, e.toString());
|
Log.e(TAG, e.toString());
|
||||||
}
|
}
|
||||||
@ -248,11 +261,13 @@ public final class BluetoothHealth implements BluetoothProfile {
|
|||||||
*
|
*
|
||||||
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
|
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
|
||||||
*
|
*
|
||||||
|
* <p> Its the responsibility of the caller to close the ParcelFileDescriptor
|
||||||
|
* when done.
|
||||||
|
*
|
||||||
* @param device The remote Bluetooth health device
|
* @param device The remote Bluetooth health device
|
||||||
* @param config The application configuration
|
* @param config The application configuration
|
||||||
* @return null on failure, ParcelFileDescriptor on success.
|
* @return null on failure, ParcelFileDescriptor on success.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public ParcelFileDescriptor getMainChannelFd(BluetoothDevice device,
|
public ParcelFileDescriptor getMainChannelFd(BluetoothDevice device,
|
||||||
BluetoothHealthAppConfiguration config) {
|
BluetoothHealthAppConfiguration config) {
|
||||||
if (mService != null && isEnabled() && isValidDevice(device) &&
|
if (mService != null && isEnabled() && isValidDevice(device) &&
|
||||||
@ -300,7 +315,7 @@ public final class BluetoothHealth implements BluetoothProfile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get connected devices for this specific profile.
|
* Get connected devices for the health profile.
|
||||||
*
|
*
|
||||||
* <p> Return the set of devices which are in state {@link #STATE_CONNECTED}
|
* <p> Return the set of devices which are in state {@link #STATE_CONNECTED}
|
||||||
*
|
*
|
||||||
@ -374,8 +389,9 @@ public final class BluetoothHealth implements BluetoothProfile {
|
|||||||
@Override
|
@Override
|
||||||
public void onHealthChannelStateChange(BluetoothHealthAppConfiguration config,
|
public void onHealthChannelStateChange(BluetoothHealthAppConfiguration config,
|
||||||
BluetoothDevice device, int prevState, int newState,
|
BluetoothDevice device, int prevState, int newState,
|
||||||
ParcelFileDescriptor fd) {
|
ParcelFileDescriptor fd, int channelId) {
|
||||||
mCallback.onHealthChannelStateChange(config, device, prevState, newState, fd);
|
mCallback.onHealthChannelStateChange(config, device, prevState, newState, fd,
|
||||||
|
channelId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -389,13 +405,13 @@ public final class BluetoothHealth implements BluetoothProfile {
|
|||||||
public static final int STATE_CHANNEL_DISCONNECTING = 3;
|
public static final int STATE_CHANNEL_DISCONNECTING = 3;
|
||||||
|
|
||||||
/** Health App Configuration registration success */
|
/** Health App Configuration registration success */
|
||||||
public static final int APPLICATION_REGISTRATION_SUCCESS = 0;
|
public static final int APP_CONFIG_REGISTRATION_SUCCESS = 0;
|
||||||
/** Health App Configuration registration failure */
|
/** Health App Configuration registration failure */
|
||||||
public static final int APPLICATION_REGISTRATION_FAILURE = 1;
|
public static final int APP_CONFIG_REGISTRATION_FAILURE = 1;
|
||||||
/** Health App Configuration un-registration success */
|
/** Health App Configuration un-registration success */
|
||||||
public static final int APPLICATION_UNREGISTRATION_SUCCESS = 2;
|
public static final int APP_CONFIG_UNREGISTRATION_SUCCESS = 2;
|
||||||
/** Health App Configuration un-registration failure */
|
/** Health App Configuration un-registration failure */
|
||||||
public static final int APPLICATION_UNREGISTRATION_FAILURE = 3;
|
public static final int APP_CONFIG_UNREGISTRATION_FAILURE = 3;
|
||||||
|
|
||||||
private ServiceListener mServiceListener;
|
private ServiceListener mServiceListener;
|
||||||
private IBluetooth mService;
|
private IBluetooth mService;
|
||||||
|
@ -26,7 +26,6 @@ import android.os.Parcelable;
|
|||||||
* that the Bluetooth Health third party application will register to communicate with the
|
* that the Bluetooth Health third party application will register to communicate with the
|
||||||
* remote Bluetooth health device.
|
* remote Bluetooth health device.
|
||||||
*
|
*
|
||||||
* @hide
|
|
||||||
*/
|
*/
|
||||||
public final class BluetoothHealthAppConfiguration implements Parcelable {
|
public final class BluetoothHealthAppConfiguration implements Parcelable {
|
||||||
private final String mName;
|
private final String mName;
|
||||||
@ -39,6 +38,7 @@ public final class BluetoothHealthAppConfiguration implements Parcelable {
|
|||||||
*
|
*
|
||||||
* @param name Friendly name associated with the application configuration
|
* @param name Friendly name associated with the application configuration
|
||||||
* @param dataType Data Type of the remote Bluetooth Health device
|
* @param dataType Data Type of the remote Bluetooth Health device
|
||||||
|
* @hide
|
||||||
*/
|
*/
|
||||||
BluetoothHealthAppConfiguration(String name, int dataType) {
|
BluetoothHealthAppConfiguration(String name, int dataType) {
|
||||||
mName = name;
|
mName = name;
|
||||||
@ -54,6 +54,7 @@ public final class BluetoothHealthAppConfiguration implements Parcelable {
|
|||||||
* @param dataType Data Type of the remote Bluetooth Health device
|
* @param dataType Data Type of the remote Bluetooth Health device
|
||||||
* @param role {@link BluetoothHealth#SOURCE_ROLE} or
|
* @param role {@link BluetoothHealth#SOURCE_ROLE} or
|
||||||
* {@link BluetoothHealth#SINK_ROLE}
|
* {@link BluetoothHealth#SINK_ROLE}
|
||||||
|
* @hide
|
||||||
*/
|
*/
|
||||||
BluetoothHealthAppConfiguration(String name, int dataType, int role, int
|
BluetoothHealthAppConfiguration(String name, int dataType, int role, int
|
||||||
channelType) {
|
channelType) {
|
||||||
@ -93,7 +94,6 @@ public final class BluetoothHealthAppConfiguration implements Parcelable {
|
|||||||
mChannelType + "]";
|
mChannelType + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int describeContents() {
|
public int describeContents() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -132,6 +132,7 @@ public final class BluetoothHealthAppConfiguration implements Parcelable {
|
|||||||
* @return One of {@link BluetoothHealth#CHANNEL_TYPE_RELIABLE} or
|
* @return One of {@link BluetoothHealth#CHANNEL_TYPE_RELIABLE} or
|
||||||
* {@link BluetoothHealth#CHANNEL_TYPE_STREAMING} or
|
* {@link BluetoothHealth#CHANNEL_TYPE_STREAMING} or
|
||||||
* {@link BluetoothHealth#CHANNEL_TYPE_ANY}.
|
* {@link BluetoothHealth#CHANNEL_TYPE_ANY}.
|
||||||
|
* @hide
|
||||||
*/
|
*/
|
||||||
public int getChannelType() {
|
public int getChannelType() {
|
||||||
return mChannelType;
|
return mChannelType;
|
||||||
@ -155,13 +156,10 @@ public final class BluetoothHealthAppConfiguration implements Parcelable {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeToParcel(Parcel out, int flags) {
|
public void writeToParcel(Parcel out, int flags) {
|
||||||
out.writeString(mName);
|
out.writeString(mName);
|
||||||
out.writeInt(mDataType);
|
out.writeInt(mDataType);
|
||||||
out.writeInt(mRole);
|
out.writeInt(mRole);
|
||||||
out.writeInt(mChannelType);
|
out.writeInt(mChannelType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,22 +21,48 @@ import android.os.ParcelFileDescriptor;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is used for all the {@link BluetoothHealth} callbacks.
|
* This abstract class is used to implement {@link BluetoothHealth} callbacks.
|
||||||
* @hide
|
|
||||||
*/
|
*/
|
||||||
public abstract class BluetoothHealthCallback {
|
public abstract class BluetoothHealthCallback {
|
||||||
|
|
||||||
private static final String TAG = "BluetoothHealthCallback";
|
private static final String TAG = "BluetoothHealthCallback";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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)
|
||||||
|
*
|
||||||
|
* @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}
|
||||||
|
*/
|
||||||
public void onHealthAppConfigurationStatusChange(BluetoothHealthAppConfiguration config,
|
public void onHealthAppConfigurationStatusChange(BluetoothHealthAppConfiguration config,
|
||||||
int status) {
|
int status) {
|
||||||
Log.d(TAG, "onHealthAppConfigurationStatusChange: " + config + "Status: " + status);
|
Log.d(TAG, "onHealthAppConfigurationStatusChange: " + config + "Status: " + status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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)
|
||||||
|
*
|
||||||
|
* @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.
|
||||||
|
*/
|
||||||
public void onHealthChannelStateChange(BluetoothHealthAppConfiguration config,
|
public void onHealthChannelStateChange(BluetoothHealthAppConfiguration config,
|
||||||
BluetoothDevice device, int prevState, int newState,
|
BluetoothDevice device, int prevState, int newState, ParcelFileDescriptor fd,
|
||||||
ParcelFileDescriptor fd) {
|
int channelId) {
|
||||||
Log.d(TAG, "onHealthChannelStateChange: " + config + "Device: " + device +
|
Log.d(TAG, "onHealthChannelStateChange: " + config + "Device: " + device +
|
||||||
"PrevState:" + prevState + "NewState:" + newState + "FileDescriptor:" + fd);
|
"prevState:" + prevState + "newState:" + newState + "ParcelFd:" + fd +
|
||||||
|
"ChannelId:" + channelId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ interface IBluetooth
|
|||||||
boolean connectChannelToSource(in BluetoothDevice device, in BluetoothHealthAppConfiguration config);
|
boolean connectChannelToSource(in BluetoothDevice device, in BluetoothHealthAppConfiguration config);
|
||||||
boolean connectChannelToSink(in BluetoothDevice device, in BluetoothHealthAppConfiguration config,
|
boolean connectChannelToSink(in BluetoothDevice device, in BluetoothHealthAppConfiguration config,
|
||||||
int channelType);
|
int channelType);
|
||||||
boolean disconnectChannel(in BluetoothDevice device, in BluetoothHealthAppConfiguration config, in ParcelFileDescriptor fd);
|
boolean disconnectChannel(in BluetoothDevice device, in BluetoothHealthAppConfiguration config, int id);
|
||||||
ParcelFileDescriptor getMainChannelFd(in BluetoothDevice device, in BluetoothHealthAppConfiguration config);
|
ParcelFileDescriptor getMainChannelFd(in BluetoothDevice device, in BluetoothHealthAppConfiguration config);
|
||||||
List<BluetoothDevice> getConnectedHealthDevices();
|
List<BluetoothDevice> getConnectedHealthDevices();
|
||||||
List<BluetoothDevice> getHealthDevicesMatchingConnectionStates(in int[] states);
|
List<BluetoothDevice> getHealthDevicesMatchingConnectionStates(in int[] states);
|
||||||
|
@ -27,5 +27,6 @@ interface IBluetoothHealthCallback
|
|||||||
{
|
{
|
||||||
void onHealthAppConfigurationStatusChange(in BluetoothHealthAppConfiguration config, int status);
|
void onHealthAppConfigurationStatusChange(in BluetoothHealthAppConfiguration config, int status);
|
||||||
void onHealthChannelStateChange(in BluetoothHealthAppConfiguration config,
|
void onHealthChannelStateChange(in BluetoothHealthAppConfiguration config,
|
||||||
in BluetoothDevice device, int prevState, int newState, in ParcelFileDescriptor fd);
|
in BluetoothDevice device, int prevState, int newState, in
|
||||||
|
ParcelFileDescriptor fd, int id);
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,8 @@ import android.os.ParcelFileDescriptor;
|
|||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.io.FileDescriptor;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -47,7 +49,6 @@ final class BluetoothHealthProfileHandler {
|
|||||||
private static final boolean DBG = true;
|
private static final boolean DBG = true;
|
||||||
|
|
||||||
private static BluetoothHealthProfileHandler sInstance;
|
private static BluetoothHealthProfileHandler sInstance;
|
||||||
private Context mContext;
|
|
||||||
private BluetoothService mBluetoothService;
|
private BluetoothService mBluetoothService;
|
||||||
private ArrayList<HealthChannel> mHealthChannels;
|
private ArrayList<HealthChannel> mHealthChannels;
|
||||||
private HashMap <BluetoothHealthAppConfiguration, String> mHealthAppConfigs;
|
private HashMap <BluetoothHealthAppConfiguration, String> mHealthAppConfigs;
|
||||||
@ -76,6 +77,17 @@ final class BluetoothHealthProfileHandler {
|
|||||||
mConfig = config;
|
mConfig = config;
|
||||||
mState = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
|
mState = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = 17;
|
||||||
|
result = 31 * result + (mChannelPath == null ? 0 : mChannelPath.hashCode());
|
||||||
|
result = 31 * result + mDevice.hashCode();
|
||||||
|
result = 31 * result + mConfig.hashCode();
|
||||||
|
result = 31 * result + mState;
|
||||||
|
result = 31 * result + mChannelType;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Handler mHandler = new Handler() {
|
private final Handler mHandler = new Handler() {
|
||||||
@ -98,28 +110,38 @@ final class BluetoothHealthProfileHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (path == null) {
|
if (path == null) {
|
||||||
mCallbacks.remove(registerApp);
|
|
||||||
callHealthApplicationStatusCallback(registerApp,
|
callHealthApplicationStatusCallback(registerApp,
|
||||||
BluetoothHealth.APPLICATION_REGISTRATION_FAILURE);
|
BluetoothHealth.APP_CONFIG_REGISTRATION_FAILURE);
|
||||||
|
mCallbacks.remove(registerApp);
|
||||||
} else {
|
} else {
|
||||||
mHealthAppConfigs.put(registerApp, path);
|
mHealthAppConfigs.put(registerApp, path);
|
||||||
callHealthApplicationStatusCallback(registerApp,
|
callHealthApplicationStatusCallback(registerApp,
|
||||||
BluetoothHealth.APPLICATION_REGISTRATION_SUCCESS);
|
BluetoothHealth.APP_CONFIG_REGISTRATION_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case MESSAGE_UNREGISTER_APPLICATION:
|
case MESSAGE_UNREGISTER_APPLICATION:
|
||||||
BluetoothHealthAppConfiguration unregisterApp =
|
BluetoothHealthAppConfiguration unregisterApp =
|
||||||
(BluetoothHealthAppConfiguration) msg.obj;
|
(BluetoothHealthAppConfiguration) msg.obj;
|
||||||
|
|
||||||
|
// Disconnect all the channels
|
||||||
|
for (HealthChannel chan : mHealthChannels) {
|
||||||
|
if (chan.mConfig.equals(unregisterApp) &&
|
||||||
|
chan.mState != BluetoothHealth.STATE_CHANNEL_DISCONNECTED) {
|
||||||
|
disconnectChannel(chan.mDevice, unregisterApp, chan.hashCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
boolean result = mBluetoothService.unregisterHealthApplicationNative(
|
boolean result = mBluetoothService.unregisterHealthApplicationNative(
|
||||||
mHealthAppConfigs.get(unregisterApp));
|
mHealthAppConfigs.get(unregisterApp));
|
||||||
if (result) {
|
if (result) {
|
||||||
mCallbacks.remove(unregisterApp);
|
|
||||||
callHealthApplicationStatusCallback(unregisterApp,
|
callHealthApplicationStatusCallback(unregisterApp,
|
||||||
BluetoothHealth.APPLICATION_UNREGISTRATION_SUCCESS);
|
BluetoothHealth.APP_CONFIG_UNREGISTRATION_SUCCESS);
|
||||||
|
mCallbacks.remove(unregisterApp);
|
||||||
|
mHealthAppConfigs.remove(unregisterApp);
|
||||||
} else {
|
} else {
|
||||||
callHealthApplicationStatusCallback(unregisterApp,
|
callHealthApplicationStatusCallback(unregisterApp,
|
||||||
BluetoothHealth.APPLICATION_UNREGISTRATION_FAILURE);
|
BluetoothHealth.APP_CONFIG_UNREGISTRATION_FAILURE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MESSAGE_CONNECT_CHANNEL:
|
case MESSAGE_CONNECT_CHANNEL:
|
||||||
@ -133,7 +155,8 @@ final class BluetoothHealthProfileHandler {
|
|||||||
channelType)) {
|
channelType)) {
|
||||||
int prevState = chan.mState;
|
int prevState = chan.mState;
|
||||||
int state = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
|
int state = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
|
||||||
callHealthChannelCallback(chan.mConfig, chan.mDevice, prevState, state, null);
|
callHealthChannelCallback(chan.mConfig, chan.mDevice, prevState, state, null,
|
||||||
|
chan.hashCode());
|
||||||
mHealthChannels.remove(chan);
|
mHealthChannels.remove(chan);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -141,7 +164,6 @@ final class BluetoothHealthProfileHandler {
|
|||||||
};
|
};
|
||||||
|
|
||||||
private BluetoothHealthProfileHandler(Context context, BluetoothService service) {
|
private BluetoothHealthProfileHandler(Context context, BluetoothService service) {
|
||||||
mContext = context;
|
|
||||||
mBluetoothService = service;
|
mBluetoothService = service;
|
||||||
mHealthAppConfigs = new HashMap<BluetoothHealthAppConfiguration, String>();
|
mHealthAppConfigs = new HashMap<BluetoothHealthAppConfiguration, String>();
|
||||||
mHealthChannels = new ArrayList<HealthChannel>();
|
mHealthChannels = new ArrayList<HealthChannel>();
|
||||||
@ -205,7 +227,7 @@ final class BluetoothHealthProfileHandler {
|
|||||||
|
|
||||||
int prevState = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
|
int prevState = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
|
||||||
int state = BluetoothHealth.STATE_CHANNEL_CONNECTING;
|
int state = BluetoothHealth.STATE_CHANNEL_CONNECTING;
|
||||||
callHealthChannelCallback(config, device, prevState, state, null);
|
callHealthChannelCallback(config, device, prevState, state, null, chan.hashCode());
|
||||||
|
|
||||||
Message msg = mHandler.obtainMessage(MESSAGE_CONNECT_CHANNEL);
|
Message msg = mHandler.obtainMessage(MESSAGE_CONNECT_CHANNEL);
|
||||||
msg.obj = chan;
|
msg.obj = chan;
|
||||||
@ -235,37 +257,44 @@ final class BluetoothHealthProfileHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
boolean disconnectChannel(BluetoothDevice device,
|
boolean disconnectChannel(BluetoothDevice device,
|
||||||
BluetoothHealthAppConfiguration config, ParcelFileDescriptor fd) {
|
BluetoothHealthAppConfiguration config, int id) {
|
||||||
HealthChannel chan = findChannelByFd(device, config, fd);
|
HealthChannel chan = findChannelById(device, config, id);
|
||||||
if (chan == null) return false;
|
if (chan == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
String deviceObjectPath =
|
String deviceObjectPath =
|
||||||
mBluetoothService.getObjectPathFromAddress(device.getAddress());
|
mBluetoothService.getObjectPathFromAddress(device.getAddress());
|
||||||
if (mBluetoothService.destroyChannelNative(deviceObjectPath, chan.mChannelPath)) {
|
|
||||||
|
mBluetoothService.releaseChannelFdNative(chan.mChannelPath);
|
||||||
|
|
||||||
int prevState = chan.mState;
|
int prevState = chan.mState;
|
||||||
chan.mState = BluetoothHealth.STATE_CHANNEL_DISCONNECTING;
|
chan.mState = BluetoothHealth.STATE_CHANNEL_DISCONNECTING;
|
||||||
callHealthChannelCallback(config, device, prevState, chan.mState,
|
callHealthChannelCallback(config, device, prevState, chan.mState,
|
||||||
chan.mChannelFd);
|
null, chan.hashCode());
|
||||||
return true;
|
|
||||||
} else {
|
if (!mBluetoothService.destroyChannelNative(deviceObjectPath, chan.mChannelPath)) {
|
||||||
|
prevState = chan.mState;
|
||||||
|
chan.mState = BluetoothHealth.STATE_CHANNEL_CONNECTED;
|
||||||
|
callHealthChannelCallback(config, device, prevState, chan.mState,
|
||||||
|
chan.mChannelFd, chan.hashCode());
|
||||||
return false;
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private HealthChannel findChannelByFd(BluetoothDevice device,
|
private HealthChannel findChannelById(BluetoothDevice device,
|
||||||
BluetoothHealthAppConfiguration config, ParcelFileDescriptor fd) {
|
BluetoothHealthAppConfiguration config, int id) {
|
||||||
for (HealthChannel chan : mHealthChannels) {
|
for (HealthChannel chan : mHealthChannels) {
|
||||||
if (chan.mChannelFd.equals(fd) && chan.mDevice.equals(device) &&
|
if (chan.hashCode() == id) return chan;
|
||||||
chan.mConfig.equals(config)) return chan;
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private HealthChannel findChannelByPath(BluetoothDevice device,
|
private HealthChannel findChannelByPath(BluetoothDevice device, String path) {
|
||||||
BluetoothHealthAppConfiguration config, String path) {
|
|
||||||
for (HealthChannel chan : mHealthChannels) {
|
for (HealthChannel chan : mHealthChannels) {
|
||||||
if (chan.mChannelPath.equals(path) && chan.mDevice.equals(device) &&
|
if (chan.mChannelPath.equals(path) && chan.mDevice.equals(device)) return chan;
|
||||||
chan.mConfig.equals(config)) return chan;
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -296,7 +325,15 @@ final class BluetoothHealthProfileHandler {
|
|||||||
ParcelFileDescriptor getMainChannelFd(BluetoothDevice device,
|
ParcelFileDescriptor getMainChannelFd(BluetoothDevice device,
|
||||||
BluetoothHealthAppConfiguration config) {
|
BluetoothHealthAppConfiguration config) {
|
||||||
HealthChannel chan = getMainChannel(device, config);
|
HealthChannel chan = getMainChannel(device, config);
|
||||||
if (chan != null) return chan.mChannelFd;
|
if (chan != null) {
|
||||||
|
ParcelFileDescriptor pfd = null;
|
||||||
|
try {
|
||||||
|
pfd = chan.mChannelFd.dup();
|
||||||
|
return pfd;
|
||||||
|
} catch (IOException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String objectPath =
|
String objectPath =
|
||||||
mBluetoothService.getObjectPathFromAddress(device.getAddress());
|
mBluetoothService.getObjectPathFromAddress(device.getAddress());
|
||||||
@ -308,14 +345,18 @@ final class BluetoothHealthProfileHandler {
|
|||||||
// We had no record of the main channel but querying Bluez we got a
|
// We had no record of the main channel but querying Bluez we got a
|
||||||
// main channel. We might not have received the PropertyChanged yet for
|
// main channel. We might not have received the PropertyChanged yet for
|
||||||
// the main channel creation so update our data structure here.
|
// the main channel creation so update our data structure here.
|
||||||
chan = findChannelByPath(device, config, mainChannelPath);
|
chan = findChannelByPath(device, mainChannelPath);
|
||||||
if (chan == null) {
|
if (chan == null) {
|
||||||
errorLog("Main Channel present but we don't have any account of it:" +
|
errorLog("Main Channel present but we don't have any account of it:" +
|
||||||
device +":" + config);
|
device +":" + config);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
chan.mMainChannel = true;
|
chan.mMainChannel = true;
|
||||||
return chan.mChannelFd;
|
try {
|
||||||
|
return chan.mChannelFd.dup();
|
||||||
|
} catch (IOException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ void onHealthDevicePropertyChanged(String devicePath,
|
/*package*/ void onHealthDevicePropertyChanged(String devicePath,
|
||||||
@ -334,7 +375,7 @@ final class BluetoothHealthProfileHandler {
|
|||||||
BluetoothHealthAppConfiguration config = findHealthApplication(device,
|
BluetoothHealthAppConfiguration config = findHealthApplication(device,
|
||||||
channelPath);
|
channelPath);
|
||||||
if (config != null) {
|
if (config != null) {
|
||||||
HealthChannel chan = findChannelByPath(device, config, channelPath);
|
HealthChannel chan = findChannelByPath(device, channelPath);
|
||||||
if (chan == null) {
|
if (chan == null) {
|
||||||
errorLog("Health Channel is not present:" + channelPath);
|
errorLog("Health Channel is not present:" + channelPath);
|
||||||
} else {
|
} else {
|
||||||
@ -346,11 +387,14 @@ final class BluetoothHealthProfileHandler {
|
|||||||
private BluetoothHealthAppConfiguration findHealthApplication(
|
private BluetoothHealthAppConfiguration findHealthApplication(
|
||||||
BluetoothDevice device, String channelPath) {
|
BluetoothDevice device, String channelPath) {
|
||||||
BluetoothHealthAppConfiguration config = null;
|
BluetoothHealthAppConfiguration config = null;
|
||||||
String configPath = mBluetoothService.getChannelApplicationNative(channelPath);
|
HealthChannel chan = findChannelByPath(device, channelPath);
|
||||||
|
|
||||||
|
if (chan != null) {
|
||||||
|
config = chan.mConfig;
|
||||||
|
} else {
|
||||||
|
String configPath = mBluetoothService.getChannelApplicationNative(channelPath);
|
||||||
if (configPath == null) {
|
if (configPath == null) {
|
||||||
errorLog("No associated application for Health Channel:" + channelPath);
|
errorLog("Config path is null for application");
|
||||||
return null;
|
|
||||||
} else {
|
} else {
|
||||||
for (Entry<BluetoothHealthAppConfiguration, String> e :
|
for (Entry<BluetoothHealthAppConfiguration, String> e :
|
||||||
mHealthAppConfigs.entrySet()) {
|
mHealthAppConfigs.entrySet()) {
|
||||||
@ -358,9 +402,7 @@ final class BluetoothHealthProfileHandler {
|
|||||||
config = e.getKey();
|
config = e.getKey();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (config == null) {
|
if (config == null) errorLog("No associated application for path:" + configPath);
|
||||||
errorLog("No associated application for application path:" + configPath);
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return config;
|
return config;
|
||||||
@ -375,22 +417,18 @@ final class BluetoothHealthProfileHandler {
|
|||||||
if (address == null) return;
|
if (address == null) return;
|
||||||
|
|
||||||
BluetoothDevice device = adapter.getRemoteDevice(address);
|
BluetoothDevice device = adapter.getRemoteDevice(address);
|
||||||
|
BluetoothHealthAppConfiguration config;
|
||||||
BluetoothHealthAppConfiguration config = findHealthApplication(device,
|
|
||||||
channelPath);
|
|
||||||
int state, prevState = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
|
int state, prevState = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
|
||||||
ParcelFileDescriptor fd;
|
ParcelFileDescriptor fd;
|
||||||
HealthChannel channel;
|
HealthChannel channel;
|
||||||
|
config = findHealthApplication(device, channelPath);
|
||||||
|
|
||||||
if (config != null) {
|
|
||||||
if (exists) {
|
if (exists) {
|
||||||
fd = mBluetoothService.getChannelFdNative(channelPath);
|
fd = mBluetoothService.getChannelFdNative(channelPath);
|
||||||
|
|
||||||
if (fd == null) {
|
if (fd == null) {
|
||||||
errorLog("Error obtaining fd for channel:" + channelPath);
|
errorLog("Error obtaining fd for channel:" + channelPath);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean mainChannel =
|
boolean mainChannel =
|
||||||
getMainChannel(device, config) == null ? false : true;
|
getMainChannel(device, config) == null ? false : true;
|
||||||
if (!mainChannel) {
|
if (!mainChannel) {
|
||||||
@ -402,7 +440,6 @@ final class BluetoothHealthProfileHandler {
|
|||||||
}
|
}
|
||||||
if (mainChannelPath.equals(channelPath)) mainChannel = true;
|
if (mainChannelPath.equals(channelPath)) mainChannel = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
channel = findConnectingChannel(device, config);
|
channel = findConnectingChannel(device, config);
|
||||||
if (channel != null) {
|
if (channel != null) {
|
||||||
channel.mChannelFd = fd;
|
channel.mChannelFd = fd;
|
||||||
@ -417,36 +454,46 @@ final class BluetoothHealthProfileHandler {
|
|||||||
}
|
}
|
||||||
state = BluetoothHealth.STATE_CHANNEL_CONNECTED;
|
state = BluetoothHealth.STATE_CHANNEL_CONNECTED;
|
||||||
} else {
|
} else {
|
||||||
channel = findChannelByPath(device, config, channelPath);
|
channel = findChannelByPath(device, channelPath);
|
||||||
if (channel == null) {
|
if (channel == null) {
|
||||||
errorLog("Channel not found:" + config + ":" + channelPath);
|
errorLog("Channel not found:" + config + ":" + channelPath);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = channel.mChannelFd;
|
|
||||||
// CLOSE FD
|
|
||||||
mBluetoothService.releaseChannelFdNative(channel.mChannelPath);
|
|
||||||
mHealthChannels.remove(channel);
|
mHealthChannels.remove(channel);
|
||||||
|
|
||||||
|
channel.mChannelFd = null;
|
||||||
prevState = channel.mState;
|
prevState = channel.mState;
|
||||||
state = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
|
state = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
|
||||||
}
|
}
|
||||||
channel.mState = state;
|
channel.mState = state;
|
||||||
callHealthChannelCallback(config, device, prevState, state, fd);
|
callHealthChannelCallback(config, device, prevState, state, channel.mChannelFd,
|
||||||
}
|
channel.hashCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void callHealthChannelCallback(BluetoothHealthAppConfiguration config,
|
private void callHealthChannelCallback(BluetoothHealthAppConfiguration config,
|
||||||
BluetoothDevice device, int prevState, int state, ParcelFileDescriptor fd) {
|
BluetoothDevice device, int prevState, int state, ParcelFileDescriptor fd, int id) {
|
||||||
broadcastHealthDeviceStateChange(device, prevState, state);
|
broadcastHealthDeviceStateChange(device, prevState, state);
|
||||||
|
|
||||||
debugLog("Health Device Callback: " + device + " State Change: "
|
debugLog("Health Device Callback: " + device + " State Change: "
|
||||||
+ prevState + "->" + state);
|
+ prevState + "->" + state);
|
||||||
|
|
||||||
|
ParcelFileDescriptor dupedFd = null;
|
||||||
|
if (fd != null) {
|
||||||
|
try {
|
||||||
|
dupedFd = fd.dup();
|
||||||
|
} catch (IOException e) {
|
||||||
|
dupedFd = null;
|
||||||
|
errorLog("Exception while duping: " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
IBluetoothHealthCallback callback = mCallbacks.get(config);
|
IBluetoothHealthCallback callback = mCallbacks.get(config);
|
||||||
if (callback != null) {
|
if (callback != null) {
|
||||||
try {
|
try {
|
||||||
callback.onHealthChannelStateChange(config, device, prevState, state, fd);
|
callback.onHealthChannelStateChange(config, device, prevState, state, dupedFd, id);
|
||||||
} catch (RemoteException e) {}
|
} catch (RemoteException e) {
|
||||||
|
errorLog("Remote Exception:" + e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -458,7 +505,9 @@ final class BluetoothHealthProfileHandler {
|
|||||||
if (callback != null) {
|
if (callback != null) {
|
||||||
try {
|
try {
|
||||||
callback.onHealthAppConfigurationStatusChange(config, status);
|
callback.onHealthAppConfigurationStatusChange(config, status);
|
||||||
} catch (RemoteException e) {}
|
} catch (RemoteException e) {
|
||||||
|
errorLog("Remote Exception:" + e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2243,11 +2243,11 @@ public class BluetoothService extends IBluetooth.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean disconnectChannel(BluetoothDevice device,
|
public boolean disconnectChannel(BluetoothDevice device,
|
||||||
BluetoothHealthAppConfiguration config, ParcelFileDescriptor fd) {
|
BluetoothHealthAppConfiguration config, int id) {
|
||||||
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
|
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
|
||||||
"Need BLUETOOTH permission");
|
"Need BLUETOOTH permission");
|
||||||
synchronized (mBluetoothHealthProfileHandler) {
|
synchronized (mBluetoothHealthProfileHandler) {
|
||||||
return mBluetoothHealthProfileHandler.disconnectChannel(device, config, fd);
|
return mBluetoothHealthProfileHandler.disconnectChannel(device, config, id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1659,6 +1659,7 @@ static jobject getChannelFdNative(JNIEnv *env, jobject object, jstring channelPa
|
|||||||
if (fileDesc == NULL) {
|
if (fileDesc == NULL) {
|
||||||
// FileDescriptor constructor has thrown an exception
|
// FileDescriptor constructor has thrown an exception
|
||||||
releaseChannelFdNative(env, object, channelPath);
|
releaseChannelFdNative(env, object, channelPath);
|
||||||
|
close(fd);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1667,7 +1668,7 @@ static jobject getChannelFdNative(JNIEnv *env, jobject object, jstring channelPa
|
|||||||
if (parcelFileDesc == NULL) {
|
if (parcelFileDesc == NULL) {
|
||||||
// ParcelFileDescriptor constructor has thrown an exception
|
// ParcelFileDescriptor constructor has thrown an exception
|
||||||
releaseChannelFdNative(env, object, channelPath);
|
releaseChannelFdNative(env, object, channelPath);
|
||||||
LOGE("---Parcel File Desc is null");
|
close(fd);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user