Loading core/java/android/bluetooth/BluetoothHealth.java +43 −32 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package android.bluetooth; import android.annotation.SdkConstant; import android.content.Context; import android.os.IBinder; import android.os.ParcelFileDescriptor; Loading Loading @@ -67,9 +66,6 @@ public final class BluetoothHealth implements BluetoothProfile { */ public static final int CHANNEL_TYPE_ANY = 12; private final ArrayList<BluetoothHealthAppConfiguration> mAppConfigs = new ArrayList<BluetoothHealthAppConfiguration>(); /** * Register an application configuration that acts as a Health SINK. * This is the configuration that will be used to communicate with health devices Loading @@ -86,7 +82,7 @@ public final class BluetoothHealth implements BluetoothProfile { * @return If true, callback will be called. */ public boolean registerSinkAppConfiguration(String name, int dataType, IBluetoothHealthCallback callback) { BluetoothHealthCallback callback) { if (!isEnabled() || name == null) return false; if (DBG) log("registerSinkApplication(" + name + ":" + dataType + ")"); Loading @@ -111,18 +107,18 @@ public final class BluetoothHealth implements BluetoothProfile { * @hide */ public boolean registerAppConfiguration(String name, int dataType, int role, int channelType, IBluetoothHealthCallback callback) { int channelType, BluetoothHealthCallback callback) { boolean result = false; if (!isEnabled() || !checkAppParam(name, role, channelType, callback)) return result; if (DBG) log("registerApplication(" + name + ":" + dataType + ")"); BluetoothHealthCallbackWrapper wrapper = new BluetoothHealthCallbackWrapper(callback); BluetoothHealthAppConfiguration config = new BluetoothHealthAppConfiguration(name, dataType, role, channelType, callback); new BluetoothHealthAppConfiguration(name, dataType, role, channelType); if (mService != null) { try { result = mService.registerAppConfiguration(config); result = mService.registerAppConfiguration(config, wrapper); } catch (RemoteException e) { Log.e(TAG, e.toString()); } Loading @@ -130,8 +126,6 @@ public final class BluetoothHealth implements BluetoothProfile { Log.w(TAG, "Proxy not attached to service"); if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); } if (result) mAppConfigs.add(config); return result; } Loading @@ -147,7 +141,7 @@ public final class BluetoothHealth implements BluetoothProfile { */ public boolean unregisterAppConfiguration(BluetoothHealthAppConfiguration config) { boolean result = false; if (mService != null && isEnabled() && isValidAppConfig(config)) { if (mService != null && isEnabled() && config != null) { try { result = mService.unregisterAppConfiguration(config); } catch (RemoteException e) { Loading @@ -157,26 +151,26 @@ public final class BluetoothHealth implements BluetoothProfile { Log.w(TAG, "Proxy not attached to service"); if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); } if (result) mAppConfigs.remove(config); return result; } /** * Connect to a health device which has the {@link #SOURCE_ROLE}. * This is an asynchrnous call. If this function returns true, the callback * This is an asynchronous call. If this function returns true, the callback * associated with the application configuration will be called. * * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * * @param device The remote Bluetooth device. * @param config The application configuration which has been registed using * {@link #registerSinkAppConfiguration(String, int, IBluetoothHealthCallback) } * @param config The application configuration which has been registered using * {@link #registerSinkAppConfiguration(String, int, BluetoothHealthCallback) } * @return If true, the callback associated with the application config will be called. */ public boolean connectChannelToSource(BluetoothDevice device, BluetoothHealthAppConfiguration config) { if (mService != null && isEnabled() && isValidDevice(device) && isValidAppConfig(config)) { config != null) { try { return mService.connectChannelToSource(device, config); } catch (RemoteException e) { Loading @@ -197,15 +191,15 @@ public final class BluetoothHealth implements BluetoothProfile { *<p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * * @param device The remote Bluetooth device. * @param config The application configuration which has been registed using * {@link #registerSinkAppConfiguration(String, int, IBluetoothHealthCallback) } * @param config The application configuration which has been registered using * {@link #registerSinkAppConfiguration(String, int, BluetoothHealthCallback) } * @return If true, the callback associated with the application config will be called. * @hide */ public boolean connectChannelToSink(BluetoothDevice device, BluetoothHealthAppConfiguration config, int channelType) { if (mService != null && isEnabled() && isValidDevice(device) && isValidAppConfig(config)) { config != null) { try { return mService.connectChannelToSink(device, config, channelType); } catch (RemoteException e) { Loading @@ -226,8 +220,8 @@ public final class BluetoothHealth implements BluetoothProfile { *<p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * * @param device The remote Bluetooth device. * @param config The application configuration which has been registed using * {@link #registerSinkAppConfiguration(String, int, IBluetoothHealthCallback) } * @param config The application configuration which has been registered using * {@link #registerSinkAppConfiguration(String, int, BluetoothHealthCallback) } * @param fd The file descriptor that was associated with the channel. * @return If true, the callback associated with the application config will be called. * @hide Loading @@ -235,7 +229,7 @@ public final class BluetoothHealth implements BluetoothProfile { public boolean disconnectChannel(BluetoothDevice device, BluetoothHealthAppConfiguration config, ParcelFileDescriptor fd) { if (mService != null && isEnabled() && isValidDevice(device) && isValidAppConfig(config)) { config != null) { try { return mService.disconnectChannel(device, config, fd); } catch (RemoteException e) { Loading @@ -262,7 +256,7 @@ public final class BluetoothHealth implements BluetoothProfile { public ParcelFileDescriptor getMainChannelFd(BluetoothDevice device, BluetoothHealthAppConfiguration config) { if (mService != null && isEnabled() && isValidDevice(device) && isValidAppConfig(config)) { config != null) { try { return mService.getMainChannelFd(device, config); } catch (RemoteException e) { Loading Loading @@ -290,6 +284,7 @@ public final class BluetoothHealth implements BluetoothProfile { * {@link #STATE_CONNECTED}, {@link #STATE_CONNECTING}, * {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING} */ @Override public int getConnectionState(BluetoothDevice device) { if (mService != null && isEnabled() && isValidDevice(device)) { try { Loading Loading @@ -317,6 +312,7 @@ public final class BluetoothHealth implements BluetoothProfile { * local adapter. * @return List of devices. The list will be empty on error. */ @Override public List<BluetoothDevice> getConnectedDevices() { if (mService != null && isEnabled()) { try { Loading Loading @@ -348,6 +344,7 @@ public final class BluetoothHealth implements BluetoothProfile { * {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING}, * @return List of devices. The list will be empty on error. */ @Override public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { if (mService != null && isEnabled()) { try { Loading @@ -361,6 +358,27 @@ public final class BluetoothHealth implements BluetoothProfile { return new ArrayList<BluetoothDevice>(); } private static class BluetoothHealthCallbackWrapper extends IBluetoothHealthCallback.Stub { private BluetoothHealthCallback mCallback; public BluetoothHealthCallbackWrapper(BluetoothHealthCallback callback) { mCallback = callback; } @Override public void onHealthAppConfigurationStatusChange(BluetoothHealthAppConfiguration config, int status) { mCallback.onHealthAppConfigurationStatusChange(config, status); } @Override public void onHealthChannelStateChange(BluetoothHealthAppConfiguration config, BluetoothDevice device, int prevState, int newState, ParcelFileDescriptor fd) { mCallback.onHealthChannelStateChange(config, device, prevState, newState, fd); } } /** Health Channel Connection State - Disconnected */ public static final int STATE_CHANNEL_DISCONNECTED = 0; /** Health Channel Connection State - Connecting */ Loading @@ -379,7 +397,6 @@ public final class BluetoothHealth implements BluetoothProfile { /** Health App Configuration un-registration failure */ public static final int APPLICATION_UNREGISTRATION_FAILURE = 3; private Context mContext; private ServiceListener mServiceListener; private IBluetooth mService; BluetoothAdapter mAdapter; Loading Loading @@ -420,14 +437,8 @@ public final class BluetoothHealth implements BluetoothProfile { return false; } private boolean isValidAppConfig(BluetoothHealthAppConfiguration config) { if (!mAppConfigs.isEmpty() && mAppConfigs.contains(config)) return true; log("Not a valid config: " + config); return false; } private boolean checkAppParam(String name, int role, int channelType, IBluetoothHealthCallback callback) { BluetoothHealthCallback callback) { if (name == null || (role != SOURCE_ROLE && role != SINK_ROLE) || (channelType != CHANNEL_TYPE_RELIABLE && channelType != CHANNEL_TYPE_STREAMING && Loading core/java/android/bluetooth/BluetoothHealthAppConfiguration.java +16 −29 Original line number Diff line number Diff line Loading @@ -17,7 +17,6 @@ package android.bluetooth; import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; Loading @@ -34,21 +33,18 @@ public final class BluetoothHealthAppConfiguration implements Parcelable { private final int mDataType; private final int mRole; private final int mChannelType; private final IBluetoothHealthCallback mCallback; /** * 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 * @param callback Callback associated with the application configuration. */ BluetoothHealthAppConfiguration(String name, int dataType, IBluetoothHealthCallback callback) { BluetoothHealthAppConfiguration(String name, int dataType) { mName = name; mDataType = dataType; mRole = BluetoothHealth.SINK_ROLE; mChannelType = BluetoothHealth.CHANNEL_TYPE_ANY; mCallback = callback; } /** Loading @@ -56,17 +52,15 @@ public final class BluetoothHealthAppConfiguration implements Parcelable { * * @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} * @param callback Callback associated with the application configuration. * @param role {@link BluetoothHealth#SOURCE_ROLE} or * {@link BluetoothHealth#SINK_ROLE} */ BluetoothHealthAppConfiguration(String name, int dataType, int role, int channelType, IBluetoothHealthCallback callback) { BluetoothHealthAppConfiguration(String name, int dataType, int role, int channelType) { mName = name; mDataType = dataType; mRole = role; mChannelType = channelType; mCallback = callback; } @Override Loading @@ -77,8 +71,7 @@ public final class BluetoothHealthAppConfiguration implements Parcelable { return mName.equals(config.getName()) && mDataType == config.getDataType() && mRole == config.getRole() && mChannelType == config.getChannelType() && mCallback.equals(config.getCallback()); mChannelType == config.getChannelType(); } return false; } Loading @@ -90,7 +83,6 @@ public final class BluetoothHealthAppConfiguration implements Parcelable { result = 31 * result + mDataType; result = 31 * result + mRole; result = 31 * result + mChannelType; result = 31 * result + (mCallback != null ? mCallback.hashCode() : 0); return result; } Loading @@ -98,9 +90,10 @@ public final class BluetoothHealthAppConfiguration implements Parcelable { public String toString() { return "BluetoothHealthAppConfiguration [mName = " + mName + ",mDataType = " + mDataType + ", mRole = " + mRole + ",mChannelType = " + mChannelType + ",callback=" + mCallback +"]"; mChannelType + "]"; } @Override public int describeContents() { return 0; } Loading Loading @@ -144,37 +137,31 @@ public final class BluetoothHealthAppConfiguration implements Parcelable { return mChannelType; } /** * Return the callback associated with this application configuration. * * @return IBluetoothHealthCallback */ public IBluetoothHealthCallback getCallback() { return mCallback; } 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(); IBluetoothHealthCallback callback = IBluetoothHealthCallback.Stub.asInterface(in.readStrongBinder()); return new BluetoothHealthAppConfiguration(name, type, role, channelType, callback); return new BluetoothHealthAppConfiguration(name, type, role, channelType); } @Override public BluetoothHealthAppConfiguration[] newArray(int size) { return new BluetoothHealthAppConfiguration[size]; } }; @Override public void writeToParcel(Parcel out, int flags) { out.writeString(mName); out.writeInt(mDataType); out.writeInt(mRole); out.writeInt(mChannelType); out.writeStrongInterface(mCallback); } } core/java/android/bluetooth/BluetoothHealthCallback.java 0 → 100644 +42 −0 Original line number Diff line number Diff line /* * 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 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.bluetooth; import android.os.ParcelFileDescriptor; import android.util.Log; /** * This class is used for all the {@link BluetoothHealth} callbacks. * @hide */ public abstract class BluetoothHealthCallback { private static final String TAG = "BluetoothHealthCallback"; public void onHealthAppConfigurationStatusChange(BluetoothHealthAppConfiguration config, int status) { Log.d(TAG, "onHealthAppConfigurationStatusChange: " + config + " Status:" + status); } public void onHealthChannelStateChange(BluetoothHealthAppConfiguration config, BluetoothDevice device, int prevState, int newState, ParcelFileDescriptor fd) { Log.d(TAG, "onHealthChannelStateChange: " + config + " Device:" + device + "PrevState:" + prevState + "NewState:" + newState + "FileDescriptor:" + fd); } } core/java/android/bluetooth/IBluetooth.aidl +3 −1 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.bluetooth; import android.bluetooth.IBluetoothCallback; import android.bluetooth.IBluetoothHealthCallback; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHealthAppConfiguration; import android.os.ParcelUuid; Loading Loading @@ -102,7 +103,8 @@ interface IBluetooth boolean disconnectPanDevice(in BluetoothDevice device); // HDP profile APIs boolean registerAppConfiguration(in BluetoothHealthAppConfiguration config); boolean registerAppConfiguration(in BluetoothHealthAppConfiguration config, in IBluetoothHealthCallback callback); boolean unregisterAppConfiguration(in BluetoothHealthAppConfiguration config); boolean connectChannelToSource(in BluetoothDevice device, in BluetoothHealthAppConfiguration config); boolean connectChannelToSink(in BluetoothDevice device, in BluetoothHealthAppConfiguration config, Loading core/java/android/server/BluetoothHealthProfileHandler.java +25 −24 Original line number Diff line number Diff line Loading @@ -20,15 +20,12 @@ import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHealth; import android.bluetooth.BluetoothHealthAppConfiguration; import android.bluetooth.BluetoothHealth; import android.bluetooth.BluetoothInputDevice; import android.bluetooth.IBluetoothHealthCallback; import android.content.Context; import android.content.Intent; import android.os.Handler; import android.os.Message; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.provider.Settings; import android.util.Log; import java.util.ArrayList; Loading @@ -36,10 +33,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map.Entry; import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.IOException; /** * This handles all the operations on the Bluetooth Health profile. * All functions are called by BluetoothService, as Bluetooth Service Loading @@ -58,6 +51,7 @@ final class BluetoothHealthProfileHandler { private ArrayList<HealthChannel> mHealthChannels; private HashMap <BluetoothHealthAppConfiguration, String> mHealthAppConfigs; private HashMap <BluetoothDevice, Integer> mHealthDevices; private HashMap <BluetoothHealthAppConfiguration, IBluetoothHealthCallback> mCallbacks; private static final int MESSAGE_REGISTER_APPLICATION = 0; private static final int MESSAGE_UNREGISTER_APPLICATION = 1; Loading Loading @@ -103,6 +97,7 @@ final class BluetoothHealthProfileHandler { } if (path == null) { mCallbacks.remove(registerApp); callHealthApplicationStatusCallback(registerApp, BluetoothHealth.APPLICATION_REGISTRATION_FAILURE); } else { Loading @@ -118,6 +113,7 @@ final class BluetoothHealthProfileHandler { boolean result = mBluetoothService.unregisterHealthApplicationNative( mHealthAppConfigs.get(unregisterApp)); if (result) { mCallbacks.remove(unregisterApp); callHealthApplicationStatusCallback(unregisterApp, BluetoothHealth.APPLICATION_UNREGISTRATION_SUCCESS); } else { Loading Loading @@ -149,6 +145,7 @@ final class BluetoothHealthProfileHandler { mHealthAppConfigs = new HashMap<BluetoothHealthAppConfiguration, String>(); mHealthChannels = new ArrayList<HealthChannel>(); mHealthDevices = new HashMap<BluetoothDevice, Integer>(); mCallbacks = new HashMap<BluetoothHealthAppConfiguration, IBluetoothHealthCallback>(); } static synchronized BluetoothHealthProfileHandler getInstance(Context context, Loading @@ -157,10 +154,12 @@ final class BluetoothHealthProfileHandler { return sInstance; } boolean registerAppConfiguration(BluetoothHealthAppConfiguration config) { boolean registerAppConfiguration(BluetoothHealthAppConfiguration config, IBluetoothHealthCallback callback) { Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_APPLICATION); msg.obj = config; mHandler.sendMessage(msg); mCallbacks.put(config, callback); return true; } Loading Loading @@ -442,11 +441,11 @@ final class BluetoothHealthProfileHandler { debugLog("Health Device Callback: " + device + " State Change: " + prevState + "->" + state); IBluetoothHealthCallback callback = mCallbacks.get(config); if (callback != null) { try { config.getCallback().onHealthChannelStateChange(config, device, prevState, state, fd); } catch (RemoteException e) { errorLog("Error while making health channel state change callback: " + e); callback.onHealthChannelStateChange(config, device, prevState, state, fd); } catch (RemoteException e) {} } } Loading @@ -454,10 +453,11 @@ final class BluetoothHealthProfileHandler { BluetoothHealthAppConfiguration config, int status) { debugLog("Health Device Application: " + config + " State Change: status:" + status); IBluetoothHealthCallback callback = mCallbacks.get(config); if (callback != null) { try { config.getCallback().onHealthAppConfigurationStatusChange(config, status); } catch (RemoteException e) { errorLog("Error while making health app registration state change callback: " + e); callback.onHealthAppConfigurationStatusChange(config, status); } catch (RemoteException e) {} } } Loading Loading @@ -526,19 +526,19 @@ final class BluetoothHealthProfileHandler { List<HealthChannel> chan; switch (currDeviceState) { case BluetoothHealth.STATE_DISCONNECTED: updateAndsendIntent(device, currDeviceState, newDeviceState); updateAndSendIntent(device, currDeviceState, newDeviceState); break; case BluetoothHealth.STATE_CONNECTING: // Channel got connected. if (newDeviceState == BluetoothHealth.STATE_CONNECTED) { updateAndsendIntent(device, currDeviceState, newDeviceState); updateAndSendIntent(device, currDeviceState, newDeviceState); } else { // Channel got disconnected chan = findChannelByStates(device, new int [] { BluetoothHealth.STATE_CHANNEL_CONNECTING, BluetoothHealth.STATE_CHANNEL_DISCONNECTING}); if (chan.isEmpty()) { updateAndsendIntent(device, currDeviceState, newDeviceState); updateAndSendIntent(device, currDeviceState, newDeviceState); } } break; Loading @@ -548,22 +548,23 @@ final class BluetoothHealthProfileHandler { BluetoothHealth.STATE_CHANNEL_CONNECTING, BluetoothHealth.STATE_CHANNEL_CONNECTED}); if (chan.isEmpty()) { updateAndsendIntent(device, currDeviceState, newDeviceState); updateAndSendIntent(device, currDeviceState, newDeviceState); } break; case BluetoothHealth.STATE_DISCONNECTING: // Channel got disconnected. chan = findChannelByStates(device, new int [] { BluetoothHealth.STATE_CHANNEL_CONNECTING, BluetoothHealth.STATE_CHANNEL_DISCONNECTING}); if (chan.isEmpty()) { updateAndsendIntent(device, currDeviceState, newDeviceState); updateAndSendIntent(device, currDeviceState, newDeviceState); } break; } } } private void updateAndsendIntent(BluetoothDevice device, int prevDeviceState, private void updateAndSendIntent(BluetoothDevice device, int prevDeviceState, int newDeviceState) { mHealthDevices.put(device, newDeviceState); mBluetoothService.sendConnectionStateChange(device, prevDeviceState, newDeviceState); Loading Loading
core/java/android/bluetooth/BluetoothHealth.java +43 −32 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package android.bluetooth; import android.annotation.SdkConstant; import android.content.Context; import android.os.IBinder; import android.os.ParcelFileDescriptor; Loading Loading @@ -67,9 +66,6 @@ public final class BluetoothHealth implements BluetoothProfile { */ public static final int CHANNEL_TYPE_ANY = 12; private final ArrayList<BluetoothHealthAppConfiguration> mAppConfigs = new ArrayList<BluetoothHealthAppConfiguration>(); /** * Register an application configuration that acts as a Health SINK. * This is the configuration that will be used to communicate with health devices Loading @@ -86,7 +82,7 @@ public final class BluetoothHealth implements BluetoothProfile { * @return If true, callback will be called. */ public boolean registerSinkAppConfiguration(String name, int dataType, IBluetoothHealthCallback callback) { BluetoothHealthCallback callback) { if (!isEnabled() || name == null) return false; if (DBG) log("registerSinkApplication(" + name + ":" + dataType + ")"); Loading @@ -111,18 +107,18 @@ public final class BluetoothHealth implements BluetoothProfile { * @hide */ public boolean registerAppConfiguration(String name, int dataType, int role, int channelType, IBluetoothHealthCallback callback) { int channelType, BluetoothHealthCallback callback) { boolean result = false; if (!isEnabled() || !checkAppParam(name, role, channelType, callback)) return result; if (DBG) log("registerApplication(" + name + ":" + dataType + ")"); BluetoothHealthCallbackWrapper wrapper = new BluetoothHealthCallbackWrapper(callback); BluetoothHealthAppConfiguration config = new BluetoothHealthAppConfiguration(name, dataType, role, channelType, callback); new BluetoothHealthAppConfiguration(name, dataType, role, channelType); if (mService != null) { try { result = mService.registerAppConfiguration(config); result = mService.registerAppConfiguration(config, wrapper); } catch (RemoteException e) { Log.e(TAG, e.toString()); } Loading @@ -130,8 +126,6 @@ public final class BluetoothHealth implements BluetoothProfile { Log.w(TAG, "Proxy not attached to service"); if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); } if (result) mAppConfigs.add(config); return result; } Loading @@ -147,7 +141,7 @@ public final class BluetoothHealth implements BluetoothProfile { */ public boolean unregisterAppConfiguration(BluetoothHealthAppConfiguration config) { boolean result = false; if (mService != null && isEnabled() && isValidAppConfig(config)) { if (mService != null && isEnabled() && config != null) { try { result = mService.unregisterAppConfiguration(config); } catch (RemoteException e) { Loading @@ -157,26 +151,26 @@ public final class BluetoothHealth implements BluetoothProfile { Log.w(TAG, "Proxy not attached to service"); if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); } if (result) mAppConfigs.remove(config); return result; } /** * Connect to a health device which has the {@link #SOURCE_ROLE}. * This is an asynchrnous call. If this function returns true, the callback * This is an asynchronous call. If this function returns true, the callback * associated with the application configuration will be called. * * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * * @param device The remote Bluetooth device. * @param config The application configuration which has been registed using * {@link #registerSinkAppConfiguration(String, int, IBluetoothHealthCallback) } * @param config The application configuration which has been registered using * {@link #registerSinkAppConfiguration(String, int, BluetoothHealthCallback) } * @return If true, the callback associated with the application config will be called. */ public boolean connectChannelToSource(BluetoothDevice device, BluetoothHealthAppConfiguration config) { if (mService != null && isEnabled() && isValidDevice(device) && isValidAppConfig(config)) { config != null) { try { return mService.connectChannelToSource(device, config); } catch (RemoteException e) { Loading @@ -197,15 +191,15 @@ public final class BluetoothHealth implements BluetoothProfile { *<p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * * @param device The remote Bluetooth device. * @param config The application configuration which has been registed using * {@link #registerSinkAppConfiguration(String, int, IBluetoothHealthCallback) } * @param config The application configuration which has been registered using * {@link #registerSinkAppConfiguration(String, int, BluetoothHealthCallback) } * @return If true, the callback associated with the application config will be called. * @hide */ public boolean connectChannelToSink(BluetoothDevice device, BluetoothHealthAppConfiguration config, int channelType) { if (mService != null && isEnabled() && isValidDevice(device) && isValidAppConfig(config)) { config != null) { try { return mService.connectChannelToSink(device, config, channelType); } catch (RemoteException e) { Loading @@ -226,8 +220,8 @@ public final class BluetoothHealth implements BluetoothProfile { *<p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * * @param device The remote Bluetooth device. * @param config The application configuration which has been registed using * {@link #registerSinkAppConfiguration(String, int, IBluetoothHealthCallback) } * @param config The application configuration which has been registered using * {@link #registerSinkAppConfiguration(String, int, BluetoothHealthCallback) } * @param fd The file descriptor that was associated with the channel. * @return If true, the callback associated with the application config will be called. * @hide Loading @@ -235,7 +229,7 @@ public final class BluetoothHealth implements BluetoothProfile { public boolean disconnectChannel(BluetoothDevice device, BluetoothHealthAppConfiguration config, ParcelFileDescriptor fd) { if (mService != null && isEnabled() && isValidDevice(device) && isValidAppConfig(config)) { config != null) { try { return mService.disconnectChannel(device, config, fd); } catch (RemoteException e) { Loading @@ -262,7 +256,7 @@ public final class BluetoothHealth implements BluetoothProfile { public ParcelFileDescriptor getMainChannelFd(BluetoothDevice device, BluetoothHealthAppConfiguration config) { if (mService != null && isEnabled() && isValidDevice(device) && isValidAppConfig(config)) { config != null) { try { return mService.getMainChannelFd(device, config); } catch (RemoteException e) { Loading Loading @@ -290,6 +284,7 @@ public final class BluetoothHealth implements BluetoothProfile { * {@link #STATE_CONNECTED}, {@link #STATE_CONNECTING}, * {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING} */ @Override public int getConnectionState(BluetoothDevice device) { if (mService != null && isEnabled() && isValidDevice(device)) { try { Loading Loading @@ -317,6 +312,7 @@ public final class BluetoothHealth implements BluetoothProfile { * local adapter. * @return List of devices. The list will be empty on error. */ @Override public List<BluetoothDevice> getConnectedDevices() { if (mService != null && isEnabled()) { try { Loading Loading @@ -348,6 +344,7 @@ public final class BluetoothHealth implements BluetoothProfile { * {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING}, * @return List of devices. The list will be empty on error. */ @Override public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { if (mService != null && isEnabled()) { try { Loading @@ -361,6 +358,27 @@ public final class BluetoothHealth implements BluetoothProfile { return new ArrayList<BluetoothDevice>(); } private static class BluetoothHealthCallbackWrapper extends IBluetoothHealthCallback.Stub { private BluetoothHealthCallback mCallback; public BluetoothHealthCallbackWrapper(BluetoothHealthCallback callback) { mCallback = callback; } @Override public void onHealthAppConfigurationStatusChange(BluetoothHealthAppConfiguration config, int status) { mCallback.onHealthAppConfigurationStatusChange(config, status); } @Override public void onHealthChannelStateChange(BluetoothHealthAppConfiguration config, BluetoothDevice device, int prevState, int newState, ParcelFileDescriptor fd) { mCallback.onHealthChannelStateChange(config, device, prevState, newState, fd); } } /** Health Channel Connection State - Disconnected */ public static final int STATE_CHANNEL_DISCONNECTED = 0; /** Health Channel Connection State - Connecting */ Loading @@ -379,7 +397,6 @@ public final class BluetoothHealth implements BluetoothProfile { /** Health App Configuration un-registration failure */ public static final int APPLICATION_UNREGISTRATION_FAILURE = 3; private Context mContext; private ServiceListener mServiceListener; private IBluetooth mService; BluetoothAdapter mAdapter; Loading Loading @@ -420,14 +437,8 @@ public final class BluetoothHealth implements BluetoothProfile { return false; } private boolean isValidAppConfig(BluetoothHealthAppConfiguration config) { if (!mAppConfigs.isEmpty() && mAppConfigs.contains(config)) return true; log("Not a valid config: " + config); return false; } private boolean checkAppParam(String name, int role, int channelType, IBluetoothHealthCallback callback) { BluetoothHealthCallback callback) { if (name == null || (role != SOURCE_ROLE && role != SINK_ROLE) || (channelType != CHANNEL_TYPE_RELIABLE && channelType != CHANNEL_TYPE_STREAMING && Loading
core/java/android/bluetooth/BluetoothHealthAppConfiguration.java +16 −29 Original line number Diff line number Diff line Loading @@ -17,7 +17,6 @@ package android.bluetooth; import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; Loading @@ -34,21 +33,18 @@ public final class BluetoothHealthAppConfiguration implements Parcelable { private final int mDataType; private final int mRole; private final int mChannelType; private final IBluetoothHealthCallback mCallback; /** * 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 * @param callback Callback associated with the application configuration. */ BluetoothHealthAppConfiguration(String name, int dataType, IBluetoothHealthCallback callback) { BluetoothHealthAppConfiguration(String name, int dataType) { mName = name; mDataType = dataType; mRole = BluetoothHealth.SINK_ROLE; mChannelType = BluetoothHealth.CHANNEL_TYPE_ANY; mCallback = callback; } /** Loading @@ -56,17 +52,15 @@ public final class BluetoothHealthAppConfiguration implements Parcelable { * * @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} * @param callback Callback associated with the application configuration. * @param role {@link BluetoothHealth#SOURCE_ROLE} or * {@link BluetoothHealth#SINK_ROLE} */ BluetoothHealthAppConfiguration(String name, int dataType, int role, int channelType, IBluetoothHealthCallback callback) { BluetoothHealthAppConfiguration(String name, int dataType, int role, int channelType) { mName = name; mDataType = dataType; mRole = role; mChannelType = channelType; mCallback = callback; } @Override Loading @@ -77,8 +71,7 @@ public final class BluetoothHealthAppConfiguration implements Parcelable { return mName.equals(config.getName()) && mDataType == config.getDataType() && mRole == config.getRole() && mChannelType == config.getChannelType() && mCallback.equals(config.getCallback()); mChannelType == config.getChannelType(); } return false; } Loading @@ -90,7 +83,6 @@ public final class BluetoothHealthAppConfiguration implements Parcelable { result = 31 * result + mDataType; result = 31 * result + mRole; result = 31 * result + mChannelType; result = 31 * result + (mCallback != null ? mCallback.hashCode() : 0); return result; } Loading @@ -98,9 +90,10 @@ public final class BluetoothHealthAppConfiguration implements Parcelable { public String toString() { return "BluetoothHealthAppConfiguration [mName = " + mName + ",mDataType = " + mDataType + ", mRole = " + mRole + ",mChannelType = " + mChannelType + ",callback=" + mCallback +"]"; mChannelType + "]"; } @Override public int describeContents() { return 0; } Loading Loading @@ -144,37 +137,31 @@ public final class BluetoothHealthAppConfiguration implements Parcelable { return mChannelType; } /** * Return the callback associated with this application configuration. * * @return IBluetoothHealthCallback */ public IBluetoothHealthCallback getCallback() { return mCallback; } 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(); IBluetoothHealthCallback callback = IBluetoothHealthCallback.Stub.asInterface(in.readStrongBinder()); return new BluetoothHealthAppConfiguration(name, type, role, channelType, callback); return new BluetoothHealthAppConfiguration(name, type, role, channelType); } @Override public BluetoothHealthAppConfiguration[] newArray(int size) { return new BluetoothHealthAppConfiguration[size]; } }; @Override public void writeToParcel(Parcel out, int flags) { out.writeString(mName); out.writeInt(mDataType); out.writeInt(mRole); out.writeInt(mChannelType); out.writeStrongInterface(mCallback); } }
core/java/android/bluetooth/BluetoothHealthCallback.java 0 → 100644 +42 −0 Original line number Diff line number Diff line /* * 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 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.bluetooth; import android.os.ParcelFileDescriptor; import android.util.Log; /** * This class is used for all the {@link BluetoothHealth} callbacks. * @hide */ public abstract class BluetoothHealthCallback { private static final String TAG = "BluetoothHealthCallback"; public void onHealthAppConfigurationStatusChange(BluetoothHealthAppConfiguration config, int status) { Log.d(TAG, "onHealthAppConfigurationStatusChange: " + config + " Status:" + status); } public void onHealthChannelStateChange(BluetoothHealthAppConfiguration config, BluetoothDevice device, int prevState, int newState, ParcelFileDescriptor fd) { Log.d(TAG, "onHealthChannelStateChange: " + config + " Device:" + device + "PrevState:" + prevState + "NewState:" + newState + "FileDescriptor:" + fd); } }
core/java/android/bluetooth/IBluetooth.aidl +3 −1 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.bluetooth; import android.bluetooth.IBluetoothCallback; import android.bluetooth.IBluetoothHealthCallback; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHealthAppConfiguration; import android.os.ParcelUuid; Loading Loading @@ -102,7 +103,8 @@ interface IBluetooth boolean disconnectPanDevice(in BluetoothDevice device); // HDP profile APIs boolean registerAppConfiguration(in BluetoothHealthAppConfiguration config); boolean registerAppConfiguration(in BluetoothHealthAppConfiguration config, in IBluetoothHealthCallback callback); boolean unregisterAppConfiguration(in BluetoothHealthAppConfiguration config); boolean connectChannelToSource(in BluetoothDevice device, in BluetoothHealthAppConfiguration config); boolean connectChannelToSink(in BluetoothDevice device, in BluetoothHealthAppConfiguration config, Loading
core/java/android/server/BluetoothHealthProfileHandler.java +25 −24 Original line number Diff line number Diff line Loading @@ -20,15 +20,12 @@ import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHealth; import android.bluetooth.BluetoothHealthAppConfiguration; import android.bluetooth.BluetoothHealth; import android.bluetooth.BluetoothInputDevice; import android.bluetooth.IBluetoothHealthCallback; import android.content.Context; import android.content.Intent; import android.os.Handler; import android.os.Message; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.provider.Settings; import android.util.Log; import java.util.ArrayList; Loading @@ -36,10 +33,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map.Entry; import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.IOException; /** * This handles all the operations on the Bluetooth Health profile. * All functions are called by BluetoothService, as Bluetooth Service Loading @@ -58,6 +51,7 @@ final class BluetoothHealthProfileHandler { private ArrayList<HealthChannel> mHealthChannels; private HashMap <BluetoothHealthAppConfiguration, String> mHealthAppConfigs; private HashMap <BluetoothDevice, Integer> mHealthDevices; private HashMap <BluetoothHealthAppConfiguration, IBluetoothHealthCallback> mCallbacks; private static final int MESSAGE_REGISTER_APPLICATION = 0; private static final int MESSAGE_UNREGISTER_APPLICATION = 1; Loading Loading @@ -103,6 +97,7 @@ final class BluetoothHealthProfileHandler { } if (path == null) { mCallbacks.remove(registerApp); callHealthApplicationStatusCallback(registerApp, BluetoothHealth.APPLICATION_REGISTRATION_FAILURE); } else { Loading @@ -118,6 +113,7 @@ final class BluetoothHealthProfileHandler { boolean result = mBluetoothService.unregisterHealthApplicationNative( mHealthAppConfigs.get(unregisterApp)); if (result) { mCallbacks.remove(unregisterApp); callHealthApplicationStatusCallback(unregisterApp, BluetoothHealth.APPLICATION_UNREGISTRATION_SUCCESS); } else { Loading Loading @@ -149,6 +145,7 @@ final class BluetoothHealthProfileHandler { mHealthAppConfigs = new HashMap<BluetoothHealthAppConfiguration, String>(); mHealthChannels = new ArrayList<HealthChannel>(); mHealthDevices = new HashMap<BluetoothDevice, Integer>(); mCallbacks = new HashMap<BluetoothHealthAppConfiguration, IBluetoothHealthCallback>(); } static synchronized BluetoothHealthProfileHandler getInstance(Context context, Loading @@ -157,10 +154,12 @@ final class BluetoothHealthProfileHandler { return sInstance; } boolean registerAppConfiguration(BluetoothHealthAppConfiguration config) { boolean registerAppConfiguration(BluetoothHealthAppConfiguration config, IBluetoothHealthCallback callback) { Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_APPLICATION); msg.obj = config; mHandler.sendMessage(msg); mCallbacks.put(config, callback); return true; } Loading Loading @@ -442,11 +441,11 @@ final class BluetoothHealthProfileHandler { debugLog("Health Device Callback: " + device + " State Change: " + prevState + "->" + state); IBluetoothHealthCallback callback = mCallbacks.get(config); if (callback != null) { try { config.getCallback().onHealthChannelStateChange(config, device, prevState, state, fd); } catch (RemoteException e) { errorLog("Error while making health channel state change callback: " + e); callback.onHealthChannelStateChange(config, device, prevState, state, fd); } catch (RemoteException e) {} } } Loading @@ -454,10 +453,11 @@ final class BluetoothHealthProfileHandler { BluetoothHealthAppConfiguration config, int status) { debugLog("Health Device Application: " + config + " State Change: status:" + status); IBluetoothHealthCallback callback = mCallbacks.get(config); if (callback != null) { try { config.getCallback().onHealthAppConfigurationStatusChange(config, status); } catch (RemoteException e) { errorLog("Error while making health app registration state change callback: " + e); callback.onHealthAppConfigurationStatusChange(config, status); } catch (RemoteException e) {} } } Loading Loading @@ -526,19 +526,19 @@ final class BluetoothHealthProfileHandler { List<HealthChannel> chan; switch (currDeviceState) { case BluetoothHealth.STATE_DISCONNECTED: updateAndsendIntent(device, currDeviceState, newDeviceState); updateAndSendIntent(device, currDeviceState, newDeviceState); break; case BluetoothHealth.STATE_CONNECTING: // Channel got connected. if (newDeviceState == BluetoothHealth.STATE_CONNECTED) { updateAndsendIntent(device, currDeviceState, newDeviceState); updateAndSendIntent(device, currDeviceState, newDeviceState); } else { // Channel got disconnected chan = findChannelByStates(device, new int [] { BluetoothHealth.STATE_CHANNEL_CONNECTING, BluetoothHealth.STATE_CHANNEL_DISCONNECTING}); if (chan.isEmpty()) { updateAndsendIntent(device, currDeviceState, newDeviceState); updateAndSendIntent(device, currDeviceState, newDeviceState); } } break; Loading @@ -548,22 +548,23 @@ final class BluetoothHealthProfileHandler { BluetoothHealth.STATE_CHANNEL_CONNECTING, BluetoothHealth.STATE_CHANNEL_CONNECTED}); if (chan.isEmpty()) { updateAndsendIntent(device, currDeviceState, newDeviceState); updateAndSendIntent(device, currDeviceState, newDeviceState); } break; case BluetoothHealth.STATE_DISCONNECTING: // Channel got disconnected. chan = findChannelByStates(device, new int [] { BluetoothHealth.STATE_CHANNEL_CONNECTING, BluetoothHealth.STATE_CHANNEL_DISCONNECTING}); if (chan.isEmpty()) { updateAndsendIntent(device, currDeviceState, newDeviceState); updateAndSendIntent(device, currDeviceState, newDeviceState); } break; } } } private void updateAndsendIntent(BluetoothDevice device, int prevDeviceState, private void updateAndSendIntent(BluetoothDevice device, int prevDeviceState, int newDeviceState) { mHealthDevices.put(device, newDeviceState); mBluetoothService.sendConnectionStateChange(device, prevDeviceState, newDeviceState); Loading