BluetoothHealth.java revision 13450df2b9264ef2220418f308037c19cec739a9
12ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh/* 22ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * Copyright (C) 2011 The Android Open Source Project 32ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * 42ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * Licensed under the Apache License, Version 2.0 (the "License"); 52ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * you may not use this file except in compliance with the License. 62ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * You may obtain a copy of the License at 72ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * 82ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * http://www.apache.org/licenses/LICENSE-2.0 92ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * 102ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * Unless required by applicable law or agreed to in writing, software 112ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * distributed under the License is distributed on an "AS IS" BASIS, 122ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * See the License for the specific language governing permissions and 142ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * limitations under the License. 152ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh */ 162ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 172ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganeshpackage android.bluetooth; 182ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 1913450df2b9264ef2220418f308037c19cec739a9Matthew Xieimport android.content.ComponentName; 202ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganeshimport android.content.Context; 2113450df2b9264ef2220418f308037c19cec739a9Matthew Xieimport android.content.Intent; 2213450df2b9264ef2220418f308037c19cec739a9Matthew Xieimport android.content.ServiceConnection; 232ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganeshimport android.os.IBinder; 242ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganeshimport android.os.ParcelFileDescriptor; 252ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganeshimport android.os.RemoteException; 262ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganeshimport android.os.ServiceManager; 272ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganeshimport android.util.Log; 282ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 292ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganeshimport java.util.ArrayList; 302ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganeshimport java.util.List; 312ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 322ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh/** 332ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * Public API for Bluetooth Health Profile. 342ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * 352ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * <p>BluetoothHealth is a proxy object for controlling the Bluetooth 362ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * Service via IPC. 372ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * 38eb9d34630f74d0260690287f2df57c0cd3d7ba1dJaikumar Ganesh * <p> How to connect to a health device which is acting in the source role. 39eb9d34630f74d0260690287f2df57c0cd3d7ba1dJaikumar Ganesh * <li> Use {@link BluetoothAdapter#getProfileProxy} to get 40eb9d34630f74d0260690287f2df57c0cd3d7ba1dJaikumar Ganesh * the BluetoothHealth proxy object. </li> 41eb9d34630f74d0260690287f2df57c0cd3d7ba1dJaikumar Ganesh * <li> Create an {@link BluetoothHealth} callback and call 42eb9d34630f74d0260690287f2df57c0cd3d7ba1dJaikumar Ganesh * {@link #registerSinkAppConfiguration} to register an application 43eb9d34630f74d0260690287f2df57c0cd3d7ba1dJaikumar Ganesh * configuration </li> 44eb9d34630f74d0260690287f2df57c0cd3d7ba1dJaikumar Ganesh * <li> Pair with the remote device. This currently needs to be done manually 45eb9d34630f74d0260690287f2df57c0cd3d7ba1dJaikumar Ganesh * from Bluetooth Settings </li> 46eb9d34630f74d0260690287f2df57c0cd3d7ba1dJaikumar Ganesh * <li> Connect to a health device using {@link #connectChannelToSource}. Some 47eb9d34630f74d0260690287f2df57c0cd3d7ba1dJaikumar Ganesh * devices will connect the channel automatically. The {@link BluetoothHealth} 48eb9d34630f74d0260690287f2df57c0cd3d7ba1dJaikumar Ganesh * callback will inform the application of channel state change. </li> 49eb9d34630f74d0260690287f2df57c0cd3d7ba1dJaikumar Ganesh * <li> Use the file descriptor provided with a connected channel to read and 50eb9d34630f74d0260690287f2df57c0cd3d7ba1dJaikumar Ganesh * write data to the health channel. </li> 51eb9d34630f74d0260690287f2df57c0cd3d7ba1dJaikumar Ganesh * <li> The received data needs to be interpreted using a health manager which 52eb9d34630f74d0260690287f2df57c0cd3d7ba1dJaikumar Ganesh * implements the IEEE 11073-xxxxx specifications. 53eb9d34630f74d0260690287f2df57c0cd3d7ba1dJaikumar Ganesh * <li> When done, close the health channel by calling {@link #disconnectChannel} 54eb9d34630f74d0260690287f2df57c0cd3d7ba1dJaikumar Ganesh * and unregister the application configuration calling 55eb9d34630f74d0260690287f2df57c0cd3d7ba1dJaikumar Ganesh * {@link #unregisterAppConfiguration} 56eb9d34630f74d0260690287f2df57c0cd3d7ba1dJaikumar Ganesh * 572ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh */ 582ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganeshpublic final class BluetoothHealth implements BluetoothProfile { 592ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh private static final String TAG = "BluetoothHealth"; 602ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh private static final boolean DBG = false; 612ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 622ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh /** 632ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * Health Profile Source Role - the health device. 642ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh */ 652ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public static final int SOURCE_ROLE = 1 << 0; 662ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 672ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh /** 682ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * Health Profile Sink Role the device talking to the health device. 692ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh */ 702ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public static final int SINK_ROLE = 1 << 1; 712ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 722ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh /** 732ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * Health Profile - Channel Type used - Reliable 742ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh */ 752ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public static final int CHANNEL_TYPE_RELIABLE = 10; 762ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 772ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh /** 782ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * Health Profile - Channel Type used - Streaming 792ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh */ 802ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public static final int CHANNEL_TYPE_STREAMING = 11; 812ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 822ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh /** 832ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * @hide 842ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh */ 852ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public static final int CHANNEL_TYPE_ANY = 12; 862ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 87b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh /** @hide */ 88b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh public static final int HEALTH_OPERATION_SUCCESS = 6000; 89b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh /** @hide */ 90b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh public static final int HEALTH_OPERATION_ERROR = 6001; 91b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh /** @hide */ 92b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh public static final int HEALTH_OPERATION_INVALID_ARGS = 6002; 93b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh /** @hide */ 94b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh public static final int HEALTH_OPERATION_GENERIC_FAILURE = 6003; 95b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh /** @hide */ 96b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh public static final int HEALTH_OPERATION_NOT_FOUND = 6004; 97b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh /** @hide */ 98b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh public static final int HEALTH_OPERATION_NOT_ALLOWED = 6005; 99b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh 100b5d2d4526cd2c0117b7a33b1297ac683c37ac5c7Jaikumar Ganesh 1012ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh /** 1022ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * Register an application configuration that acts as a Health SINK. 1032ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * This is the configuration that will be used to communicate with health devices 1042ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * which will act as the {@link #SOURCE_ROLE}. This is an asynchronous call and so 1052ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * the callback is used to notify success or failure if the function returns true. 1062ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * 1072ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 1082ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * 1092ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * @param name The friendly name associated with the application or configuration. 1102ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * @param dataType The dataType of the Source role of Health Profile to which 1112ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * the sink wants to connect to. 1122ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * @param callback A callback to indicate success or failure of the registration and 1132ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * all operations done on this application configuration. 1142ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * @return If true, callback will be called. 1152ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh */ 1162ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public boolean registerSinkAppConfiguration(String name, int dataType, 117fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh BluetoothHealthCallback callback) { 1182ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh if (!isEnabled() || name == null) return false; 1192ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 1202ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh if (DBG) log("registerSinkApplication(" + name + ":" + dataType + ")"); 1212ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return registerAppConfiguration(name, dataType, SINK_ROLE, 1222ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh CHANNEL_TYPE_ANY, callback); 1232ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 1242ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 1252ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh /** 1262ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * Register an application configuration that acts as a Health SINK or in a Health 1272ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * SOURCE role.This is an asynchronous call and so 1282ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * the callback is used to notify success or failure if the function returns true. 1292ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * 1302ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 1312ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * 1322ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * @param name The friendly name associated with the application or configuration. 1332ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * @param dataType The dataType of the Source role of Health Profile. 1342ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * @param channelType The channel type. Will be one of 1352ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * {@link #CHANNEL_TYPE_RELIABLE} or 1362ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * {@link #CHANNEL_TYPE_STREAMING} 1372ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * @param callback - A callback to indicate success or failure. 1382ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * @return If true, callback will be called. 1392ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * @hide 1402ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh */ 1412ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public boolean registerAppConfiguration(String name, int dataType, int role, 142fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh int channelType, BluetoothHealthCallback callback) { 1432ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh boolean result = false; 1442ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh if (!isEnabled() || !checkAppParam(name, role, channelType, callback)) return result; 1452ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 1462ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh if (DBG) log("registerApplication(" + name + ":" + dataType + ")"); 147fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh BluetoothHealthCallbackWrapper wrapper = new BluetoothHealthCallbackWrapper(callback); 1482ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh BluetoothHealthAppConfiguration config = 149fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh new BluetoothHealthAppConfiguration(name, dataType, role, channelType); 1502ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 1512ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh if (mService != null) { 1522ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh try { 153fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh result = mService.registerAppConfiguration(config, wrapper); 1542ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } catch (RemoteException e) { 1552ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh Log.e(TAG, e.toString()); 15613450df2b9264ef2220418f308037c19cec739a9Matthew Xie } 1572ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } else { 1582ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh Log.w(TAG, "Proxy not attached to service"); 1592ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); 1602ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 1612ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return result; 1622ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 1632ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 1642ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh /** 1652ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * Unregister an application configuration that has been registered using 1662ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * {@link #registerSinkAppConfiguration} 1672ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * 1682ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 1692ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * 1702ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * @param config The health app configuration 1712ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * @return Success or failure. 1722ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh */ 1732ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public boolean unregisterAppConfiguration(BluetoothHealthAppConfiguration config) { 1742ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh boolean result = false; 175fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh if (mService != null && isEnabled() && config != null) { 1762ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh try { 1772ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh result = mService.unregisterAppConfiguration(config); 1782ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } catch (RemoteException e) { 1792ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh Log.e(TAG, e.toString()); 18013450df2b9264ef2220418f308037c19cec739a9Matthew Xie } 1812ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } else { 1822ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh Log.w(TAG, "Proxy not attached to service"); 1832ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); 1842ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 185fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh 1862ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return result; 1872ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 1882ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 1892ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh /** 1902ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * Connect to a health device which has the {@link #SOURCE_ROLE}. 191fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh * This is an asynchronous call. If this function returns true, the callback 1922ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * associated with the application configuration will be called. 1932ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * 1942ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 1952ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * 1962ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * @param device The remote Bluetooth device. 197fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh * @param config The application configuration which has been registered using 198fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh * {@link #registerSinkAppConfiguration(String, int, BluetoothHealthCallback) } 1992ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * @return If true, the callback associated with the application config will be called. 2002ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh */ 2012ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public boolean connectChannelToSource(BluetoothDevice device, 2022ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh BluetoothHealthAppConfiguration config) { 2032ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh if (mService != null && isEnabled() && isValidDevice(device) && 204fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh config != null) { 2052ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh try { 2062ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return mService.connectChannelToSource(device, config); 2072ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } catch (RemoteException e) { 2082ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh Log.e(TAG, e.toString()); 20913450df2b9264ef2220418f308037c19cec739a9Matthew Xie } 2102ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } else { 2112ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh Log.w(TAG, "Proxy not attached to service"); 2122ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); 2132ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 2142ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return false; 2152ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 2162ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 2172ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh /** 2182ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * Connect to a health device which has the {@link #SINK_ROLE}. 2192ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * This is an asynchronous call. If this function returns true, the callback 2202ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * associated with the application configuration will be called. 2212ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * 2222ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh *<p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 2232ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * 2242ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * @param device The remote Bluetooth device. 225fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh * @param config The application configuration which has been registered using 226fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh * {@link #registerSinkAppConfiguration(String, int, BluetoothHealthCallback) } 2272ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * @return If true, the callback associated with the application config will be called. 2282ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * @hide 2292ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh */ 2302ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public boolean connectChannelToSink(BluetoothDevice device, 2312ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh BluetoothHealthAppConfiguration config, int channelType) { 2322ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh if (mService != null && isEnabled() && isValidDevice(device) && 233fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh config != null) { 2342ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh try { 2352ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return mService.connectChannelToSink(device, config, channelType); 2362ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } catch (RemoteException e) { 2372ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh Log.e(TAG, e.toString()); 23813450df2b9264ef2220418f308037c19cec739a9Matthew Xie } 2392ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } else { 2402ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh Log.w(TAG, "Proxy not attached to service"); 2412ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); 2422ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 2432ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return false; 2442ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 2452ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 2462ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh /** 2472ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * Disconnect a connected health channel. 2482ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * This is an asynchronous call. If this function returns true, the callback 2492ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * associated with the application configuration will be called. 2502ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * 2512ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh *<p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 2522ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * 2532ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * @param device The remote Bluetooth device. 254fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh * @param config The application configuration which has been registered using 255fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh * {@link #registerSinkAppConfiguration(String, int, BluetoothHealthCallback) } 256eb9d34630f74d0260690287f2df57c0cd3d7ba1dJaikumar Ganesh * @param channelId The channel id associated with the channel 2572ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * @return If true, the callback associated with the application config will be called. 2582ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh */ 2592ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public boolean disconnectChannel(BluetoothDevice device, 260eb9d34630f74d0260690287f2df57c0cd3d7ba1dJaikumar Ganesh BluetoothHealthAppConfiguration config, int channelId) { 2612ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh if (mService != null && isEnabled() && isValidDevice(device) && 262fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh config != null) { 2632ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh try { 264eb9d34630f74d0260690287f2df57c0cd3d7ba1dJaikumar Ganesh return mService.disconnectChannel(device, config, channelId); 2652ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } catch (RemoteException e) { 2662ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh Log.e(TAG, e.toString()); 26713450df2b9264ef2220418f308037c19cec739a9Matthew Xie } 2682ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } else { 2692ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh Log.w(TAG, "Proxy not attached to service"); 2702ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); 2712ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 2722ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return false; 2732ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 2742ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 2752ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh /** 2762ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * Get the file descriptor of the main channel associated with the remote device 2772ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * and application configuration. 2782ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * 2792ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 2802ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * 281eb9d34630f74d0260690287f2df57c0cd3d7ba1dJaikumar Ganesh * <p> Its the responsibility of the caller to close the ParcelFileDescriptor 282eb9d34630f74d0260690287f2df57c0cd3d7ba1dJaikumar Ganesh * when done. 283eb9d34630f74d0260690287f2df57c0cd3d7ba1dJaikumar Ganesh * 2842ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * @param device The remote Bluetooth health device 2852ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * @param config The application configuration 2862ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * @return null on failure, ParcelFileDescriptor on success. 2872ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh */ 2882ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public ParcelFileDescriptor getMainChannelFd(BluetoothDevice device, 2892ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh BluetoothHealthAppConfiguration config) { 2902ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh if (mService != null && isEnabled() && isValidDevice(device) && 291fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh config != null) { 2922ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh try { 2932ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return mService.getMainChannelFd(device, config); 2942ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } catch (RemoteException e) { 2952ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh Log.e(TAG, e.toString()); 29613450df2b9264ef2220418f308037c19cec739a9Matthew Xie } 2972ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } else { 2982ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh Log.w(TAG, "Proxy not attached to service"); 2992ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); 3002ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 3012ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return null; 3022ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 3032ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 3042ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh /** 3052ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * Get the current connection state of the profile. 3062ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * 3072ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 3082ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * 3092ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * This is not specific to any application configuration but represents the connection 3102ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * state of the local Bluetooth adapter with the remote device. This can be used 3112ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * by applications like status bar which would just like to know the state of the 3122ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * local adapter. 3132ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * 3142ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * @param device Remote bluetooth device. 3152ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * @return State of the profile connection. One of 3162ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * {@link #STATE_CONNECTED}, {@link #STATE_CONNECTING}, 3172ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING} 3182ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh */ 319fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh @Override 3202ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public int getConnectionState(BluetoothDevice device) { 3212ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh if (mService != null && isEnabled() && isValidDevice(device)) { 3222ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh try { 3232ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return mService.getHealthDeviceConnectionState(device); 3242ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } catch (RemoteException e) { 3252ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh Log.e(TAG, e.toString()); 32613450df2b9264ef2220418f308037c19cec739a9Matthew Xie } 3272ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } else { 3282ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh Log.w(TAG, "Proxy not attached to service"); 3292ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); 3302ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 3312ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return STATE_DISCONNECTED; 3322ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 3332ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 3342ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh /** 335eb9d34630f74d0260690287f2df57c0cd3d7ba1dJaikumar Ganesh * Get connected devices for the health profile. 3362ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * 3372ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * <p> Return the set of devices which are in state {@link #STATE_CONNECTED} 3382ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * 3392ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 3402ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * 3412ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * This is not specific to any application configuration but represents the connection 3422ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * state of the local Bluetooth adapter for this profile. This can be used 3432ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * by applications like status bar which would just like to know the state of the 3442ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * local adapter. 3452ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * @return List of devices. The list will be empty on error. 3462ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh */ 347fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh @Override 3482ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public List<BluetoothDevice> getConnectedDevices() { 3492ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh if (mService != null && isEnabled()) { 3502ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh try { 3512ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return mService.getConnectedHealthDevices(); 3522ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } catch (RemoteException e) { 3532ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); 3542ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return new ArrayList<BluetoothDevice>(); 35513450df2b9264ef2220418f308037c19cec739a9Matthew Xie } 3562ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 3572ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh if (mService == null) Log.w(TAG, "Proxy not attached to service"); 3582ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return new ArrayList<BluetoothDevice>(); 3592ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 3602ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 3612ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh /** 3622ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * Get a list of devices that match any of the given connection 3632ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * states. 3642ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * 3652ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * <p> If none of the devices match any of the given states, 3662ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * an empty list will be returned. 3672ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * 3682ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 3692ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * This is not specific to any application configuration but represents the connection 3702ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * state of the local Bluetooth adapter for this profile. This can be used 3712ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * by applications like status bar which would just like to know the state of the 3722ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * local adapter. 3732ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * 3742ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * @param states Array of states. States can be one of 3752ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * {@link #STATE_CONNECTED}, {@link #STATE_CONNECTING}, 3762ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING}, 3772ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * @return List of devices. The list will be empty on error. 3782ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh */ 379fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh @Override 3802ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 3812ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh if (mService != null && isEnabled()) { 3822ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh try { 3832ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return mService.getHealthDevicesMatchingConnectionStates(states); 3842ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } catch (RemoteException e) { 3852ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); 3862ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return new ArrayList<BluetoothDevice>(); 38713450df2b9264ef2220418f308037c19cec739a9Matthew Xie } 3882ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 3892ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh if (mService == null) Log.w(TAG, "Proxy not attached to service"); 3902ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return new ArrayList<BluetoothDevice>(); 3912ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 3922ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 393fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh private static class BluetoothHealthCallbackWrapper extends IBluetoothHealthCallback.Stub { 394fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh private BluetoothHealthCallback mCallback; 395fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh 396fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh public BluetoothHealthCallbackWrapper(BluetoothHealthCallback callback) { 397fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh mCallback = callback; 398fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh } 399fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh 400fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh @Override 401fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh public void onHealthAppConfigurationStatusChange(BluetoothHealthAppConfiguration config, 402fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh int status) { 403eb9d34630f74d0260690287f2df57c0cd3d7ba1dJaikumar Ganesh mCallback.onHealthAppConfigurationStatusChange(config, status); 404fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh } 405fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh 406fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh @Override 407fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh public void onHealthChannelStateChange(BluetoothHealthAppConfiguration config, 408fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh BluetoothDevice device, int prevState, int newState, 409eb9d34630f74d0260690287f2df57c0cd3d7ba1dJaikumar Ganesh ParcelFileDescriptor fd, int channelId) { 410eb9d34630f74d0260690287f2df57c0cd3d7ba1dJaikumar Ganesh mCallback.onHealthChannelStateChange(config, device, prevState, newState, fd, 411eb9d34630f74d0260690287f2df57c0cd3d7ba1dJaikumar Ganesh channelId); 412fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh } 413fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh } 414fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh 4152ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh /** Health Channel Connection State - Disconnected */ 4162ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public static final int STATE_CHANNEL_DISCONNECTED = 0; 4172ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh /** Health Channel Connection State - Connecting */ 4182ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public static final int STATE_CHANNEL_CONNECTING = 1; 4192ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh /** Health Channel Connection State - Connected */ 4202ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public static final int STATE_CHANNEL_CONNECTED = 2; 4212ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh /** Health Channel Connection State - Disconnecting */ 4222ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh public static final int STATE_CHANNEL_DISCONNECTING = 3; 4232ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 4242ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh /** Health App Configuration registration success */ 425eb9d34630f74d0260690287f2df57c0cd3d7ba1dJaikumar Ganesh public static final int APP_CONFIG_REGISTRATION_SUCCESS = 0; 4262ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh /** Health App Configuration registration failure */ 427eb9d34630f74d0260690287f2df57c0cd3d7ba1dJaikumar Ganesh public static final int APP_CONFIG_REGISTRATION_FAILURE = 1; 4282ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh /** Health App Configuration un-registration success */ 429eb9d34630f74d0260690287f2df57c0cd3d7ba1dJaikumar Ganesh public static final int APP_CONFIG_UNREGISTRATION_SUCCESS = 2; 4302ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh /** Health App Configuration un-registration failure */ 431eb9d34630f74d0260690287f2df57c0cd3d7ba1dJaikumar Ganesh public static final int APP_CONFIG_UNREGISTRATION_FAILURE = 3; 4322ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 43313450df2b9264ef2220418f308037c19cec739a9Matthew Xie private Context mContext; 4342ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh private ServiceListener mServiceListener; 43513450df2b9264ef2220418f308037c19cec739a9Matthew Xie private IBluetoothHealth mService; 4362ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh BluetoothAdapter mAdapter; 4372ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 4382ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh /** 4392ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh * Create a BluetoothHealth proxy object. 4402ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh */ 44113450df2b9264ef2220418f308037c19cec739a9Matthew Xie /*package*/ BluetoothHealth(Context context, ServiceListener l) { 44213450df2b9264ef2220418f308037c19cec739a9Matthew Xie mContext = context; 4432ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mServiceListener = l; 4442ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh mAdapter = BluetoothAdapter.getDefaultAdapter(); 44513450df2b9264ef2220418f308037c19cec739a9Matthew Xie if (!context.bindService(new Intent(IBluetoothHealth.class.getName()), mConnection, 0)) { 44613450df2b9264ef2220418f308037c19cec739a9Matthew Xie Log.e(TAG, "Could not bind to Bluetooth Health Service"); 4472ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 4482ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 4492ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 4509bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh /*package*/ void close() { 45113450df2b9264ef2220418f308037c19cec739a9Matthew Xie if (DBG) log("close()"); 45213450df2b9264ef2220418f308037c19cec739a9Matthew Xie if (mConnection != null) { 45313450df2b9264ef2220418f308037c19cec739a9Matthew Xie mContext.unbindService(mConnection); 45413450df2b9264ef2220418f308037c19cec739a9Matthew Xie mConnection = null; 45513450df2b9264ef2220418f308037c19cec739a9Matthew Xie } 4569bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh mServiceListener = null; 4579bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh } 4589bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh 45913450df2b9264ef2220418f308037c19cec739a9Matthew Xie private ServiceConnection mConnection = new ServiceConnection() { 46013450df2b9264ef2220418f308037c19cec739a9Matthew Xie public void onServiceConnected(ComponentName className, IBinder service) { 46113450df2b9264ef2220418f308037c19cec739a9Matthew Xie if (DBG) Log.d(TAG, "Proxy object connected"); 46213450df2b9264ef2220418f308037c19cec739a9Matthew Xie mService = IBluetoothHealth.Stub.asInterface(service); 46313450df2b9264ef2220418f308037c19cec739a9Matthew Xie 46413450df2b9264ef2220418f308037c19cec739a9Matthew Xie if (mServiceListener != null) { 46513450df2b9264ef2220418f308037c19cec739a9Matthew Xie mServiceListener.onServiceConnected(BluetoothProfile.HEALTH, BluetoothHealth.this); 46613450df2b9264ef2220418f308037c19cec739a9Matthew Xie } 46713450df2b9264ef2220418f308037c19cec739a9Matthew Xie } 46813450df2b9264ef2220418f308037c19cec739a9Matthew Xie public void onServiceDisconnected(ComponentName className) { 46913450df2b9264ef2220418f308037c19cec739a9Matthew Xie if (DBG) Log.d(TAG, "Proxy object disconnected"); 47013450df2b9264ef2220418f308037c19cec739a9Matthew Xie mService = null; 47113450df2b9264ef2220418f308037c19cec739a9Matthew Xie if (mServiceListener != null) { 47213450df2b9264ef2220418f308037c19cec739a9Matthew Xie mServiceListener.onServiceDisconnected(BluetoothProfile.HEALTH); 47313450df2b9264ef2220418f308037c19cec739a9Matthew Xie } 47413450df2b9264ef2220418f308037c19cec739a9Matthew Xie } 47513450df2b9264ef2220418f308037c19cec739a9Matthew Xie }; 47613450df2b9264ef2220418f308037c19cec739a9Matthew Xie 4772ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh private boolean isEnabled() { 4782ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 4792ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 4802ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh if (adapter != null && adapter.getState() == BluetoothAdapter.STATE_ON) return true; 4812ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh log("Bluetooth is Not enabled"); 4822ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return false; 4832ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 4842ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 4852ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh private boolean isValidDevice(BluetoothDevice device) { 4862ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh if (device == null) return false; 4872ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 4882ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; 4892ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return false; 4902ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 4912ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 4922ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh private boolean checkAppParam(String name, int role, int channelType, 493fb658c72a3a76dac334c39070d1501a2575c1069Jaikumar Ganesh BluetoothHealthCallback callback) { 4942ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh if (name == null || (role != SOURCE_ROLE && role != SINK_ROLE) || 4952ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh (channelType != CHANNEL_TYPE_RELIABLE && 4962ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh channelType != CHANNEL_TYPE_STREAMING && 4972ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh channelType != CHANNEL_TYPE_ANY) || callback == null) { 4982ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return false; 4992ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 5002ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh if (role == SOURCE_ROLE && channelType == CHANNEL_TYPE_ANY) return false; 5012ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh return true; 5022ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 5032ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh 5042ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh private static void log(String msg) { 5052ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh Log.d(TAG, msg); 5062ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh } 5072ea1e85dcb57d17f5782dbafa1d25eb51c630e4bJaikumar Ganesh} 508