BluetoothGatt.java revision ce21cb903ceaf8a5d916a89c4d07689887007be2
19908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta/* 29908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Copyright (C) 2013 The Android Open Source Project 39908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 49908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Licensed under the Apache License, Version 2.0 (the "License"); 59908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * you may not use this file except in compliance with the License. 69908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * You may obtain a copy of the License at 79908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 89908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * http://www.apache.org/licenses/LICENSE-2.0 99908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Unless required by applicable law or agreed to in writing, software 119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * distributed under the License is distributed on an "AS IS" BASIS, 129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * See the License for the specific language governing permissions and 149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * limitations under the License. 159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battapackage android.bluetooth; 189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.content.Context; 20b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowskiimport android.os.Handler; 219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.os.ParcelUuid; 229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.os.RemoteException; 239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.util.Log; 249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport java.util.ArrayList; 269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport java.util.List; 279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport java.util.UUID; 289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta/** 30ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * Public API for the Bluetooth GATT Profile. 319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 32ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * <p>This class provides Bluetooth GATT functionality to enable communication 339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * with Bluetooth Smart or Smart Ready devices. 349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 35d64bb883d822e1db445e09e77150ffd281e83cbeJakub Pawlowski * <p>To connect to a remote peripheral device, create a {@link BluetoothGattCallback} 3633ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie * and call {@link BluetoothDevice#connectGatt} to get a instance of this class. 37ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * GATT capable devices can be discovered using the Bluetooth device discovery or BLE 38ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * scan process. 399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battapublic final class BluetoothGatt implements BluetoothProfile { 419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta private static final String TAG = "BluetoothGatt"; 429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta private static final boolean DBG = true; 4355d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach private static final boolean VDBG = false; 449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta private IBluetoothGatt mService; 46d64bb883d822e1db445e09e77150ffd281e83cbeJakub Pawlowski private BluetoothGattCallback mCallback; 47b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski private Handler mHandler; 489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta private int mClientIf; 49ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie private BluetoothDevice mDevice; 50ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie private boolean mAutoConnect; 513854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung private int mAuthRetryState; 52ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie private int mConnState; 53ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie private final Object mStateLock = new Object(); 54cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach private Boolean mDeviceBusy = false; 55b88fa824ab6337684de9aa8437c4952df4f1a75eGanesh Ganapathi Batta private int mTransport; 56db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski private int mPhy; 57ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie 583854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung private static final int AUTH_RETRY_STATE_IDLE = 0; 593854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung private static final int AUTH_RETRY_STATE_NO_MITM = 1; 603854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung private static final int AUTH_RETRY_STATE_MITM = 2; 613854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung 62ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie private static final int CONN_STATE_IDLE = 0; 63ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie private static final int CONN_STATE_CONNECTING = 1; 64ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie private static final int CONN_STATE_CONNECTED = 2; 65ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie private static final int CONN_STATE_DISCONNECTING = 3; 6633ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie private static final int CONN_STATE_CLOSED = 4; 679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta private List<BluetoothGattService> mServices; 699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 70ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie /** A GATT operation completed successfully */ 719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public static final int GATT_SUCCESS = 0; 729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 73ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie /** GATT read operation is not permitted */ 749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public static final int GATT_READ_NOT_PERMITTED = 0x2; 759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 76ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie /** GATT write operation is not permitted */ 779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public static final int GATT_WRITE_NOT_PERMITTED = 0x3; 789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** Insufficient authentication for a given operation */ 809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public static final int GATT_INSUFFICIENT_AUTHENTICATION = 0x5; 819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** The given request is not supported */ 839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public static final int GATT_REQUEST_NOT_SUPPORTED = 0x6; 849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** Insufficient encryption for a given operation */ 869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public static final int GATT_INSUFFICIENT_ENCRYPTION = 0xf; 879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** A read or write operation was requested with an invalid offset */ 899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public static final int GATT_INVALID_OFFSET = 0x7; 909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** A write operation exceeds the maximum length of the attribute */ 929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public static final int GATT_INVALID_ATTRIBUTE_LENGTH = 0xd; 939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 9445a0a1a689518df7e2c904b902e28f6d68b76e2aAndre Eisenbach /** A remote device connection is congested. */ 95dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach public static final int GATT_CONNECTION_CONGESTED = 0x8f; 96dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach 9790ca807f7b2037499112d1c49c4b0793cc780540Matthew Xie /** A GATT operation failed, errors other than the above */ 9890ca807f7b2037499112d1c49c4b0793cc780540Matthew Xie public static final int GATT_FAILURE = 0x101; 9990ca807f7b2037499112d1c49c4b0793cc780540Matthew Xie 1009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 1016ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach * Connection paramter update - Use the connection paramters recommended by the 1026ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach * Bluetooth SIG. This is the default value if no connection parameter update 1036ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach * is requested. 1046ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach */ 1054072da041da2911dd56635b530b276671ce0199dAndre Eisenbach public static final int CONNECTION_PRIORITY_BALANCED = 0; 1066ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach 1076ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach /** 1086ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach * Connection paramter update - Request a high priority, low latency connection. 1096ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach * An application should only request high priority connection paramters to transfer 1106ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach * large amounts of data over LE quickly. Once the transfer is complete, the application 1114072da041da2911dd56635b530b276671ce0199dAndre Eisenbach * should request {@link BluetoothGatt#CONNECTION_PRIORITY_BALANCED} connectoin parameters 1126ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach * to reduce energy use. 1136ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach */ 1144072da041da2911dd56635b530b276671ce0199dAndre Eisenbach public static final int CONNECTION_PRIORITY_HIGH = 1; 1156ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach 1166ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach /** Connection paramter update - Request low power, reduced data rate connection parameters. */ 1174072da041da2911dd56635b530b276671ce0199dAndre Eisenbach public static final int CONNECTION_PRIORITY_LOW_POWER = 2; 1186ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach 1196ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach /** 1209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * No authentication required. 1219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @hide 1229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 1239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /*package*/ static final int AUTHENTICATION_NONE = 0; 1249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 1259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 1269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Authentication requested; no man-in-the-middle protection required. 1279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @hide 1289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 1299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /*package*/ static final int AUTHENTICATION_NO_MITM = 1; 1309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 1319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 1329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Authentication with man-in-the-middle protection requested. 1339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @hide 1349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 1359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /*package*/ static final int AUTHENTICATION_MITM = 2; 1369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 1379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 138d64bb883d822e1db445e09e77150ffd281e83cbeJakub Pawlowski * Bluetooth GATT callbacks. Overrides the default BluetoothGattCallback implementation. 1399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 140d7116bea0698f58e93003d2046411a2624dd1ab1Jakub Pawlowski private final IBluetoothGattCallback mBluetoothGattCallback = 141d7116bea0698f58e93003d2046411a2624dd1ab1Jakub Pawlowski new IBluetoothGattCallback.Stub() { 1429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 1439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Application interface registered - app is ready to go 1449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @hide 1459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 146326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski @Override 1479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public void onClientRegistered(int status, int clientIf) { 1489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (DBG) Log.d(TAG, "onClientRegistered() - status=" + status 1499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta + " clientIf=" + clientIf); 150ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (VDBG) { 151ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie synchronized(mStateLock) { 152ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (mConnState != CONN_STATE_CONNECTING) { 153ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie Log.e(TAG, "Bad connection state: " + mConnState); 154ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 155ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 156ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 1579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mClientIf = clientIf; 158ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (status != GATT_SUCCESS) { 159b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski mHandler.post(new Runnable() { 160b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski @Override 161b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski public void run() { 162b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski mCallback.onConnectionStateChange(BluetoothGatt.this, GATT_FAILURE, 163b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski BluetoothProfile.STATE_DISCONNECTED); 164b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski } 165b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski }); 166b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski 167ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie synchronized(mStateLock) { 168ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie mConnState = CONN_STATE_IDLE; 169ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 170ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie return; 171ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 1729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta try { 173ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie mService.clientConnect(mClientIf, mDevice.getAddress(), 174db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski !mAutoConnect, mTransport, mPhy); // autoConnect is inverse of "isDirect" 175ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } catch (RemoteException e) { 176ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie Log.e(TAG,"",e); 1779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 1789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 1799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 1809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 181db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski * Phy update callback 182db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski * @hide 183db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski */ 184db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski @Override 185db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski public void onPhyUpdate(String address, int txPhy, int rxPhy, int status) { 186db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski if (DBG) Log.d(TAG, "onPhyUpdate() - status=" + status 187db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski + " address=" + address + " txPhy=" + txPhy + " rxPhy=" + rxPhy); 188db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski if (!address.equals(mDevice.getAddress())) { 189db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski return; 190db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski } 191db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski 192b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski mHandler.post(new Runnable() { 193b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski @Override 194b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski public void run() { 195b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski mCallback.onPhyUpdate(BluetoothGatt.this, txPhy, rxPhy, status); 196b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski } 197b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski }); 198db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski } 199db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski 200db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski /** 201db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski * Phy read callback 202db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski * @hide 203db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski */ 204db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski @Override 205db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski public void onPhyRead(String address, int txPhy, int rxPhy, int status) { 206db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski if (DBG) Log.d(TAG, "onPhyRead() - status=" + status 207db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski + " address=" + address + " txPhy=" + txPhy + " rxPhy=" + rxPhy); 208db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski if (!address.equals(mDevice.getAddress())) { 209db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski return; 210db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski } 211db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski 212b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski mHandler.post(new Runnable() { 213b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski @Override 214b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski public void run() { 215b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski mCallback.onPhyRead(BluetoothGatt.this, txPhy, rxPhy, status); 216b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski } 217b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski }); 218db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski } 219db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski 220db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski /** 2219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Client connection state changed 2229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @hide 2239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 224326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski @Override 2259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public void onClientConnectionState(int status, int clientIf, 2269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta boolean connected, String address) { 2279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (DBG) Log.d(TAG, "onClientConnectionState() - status=" + status 2289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta + " clientIf=" + clientIf + " device=" + address); 229ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (!address.equals(mDevice.getAddress())) { 230ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie return; 231ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 232ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie int profileState = connected ? BluetoothProfile.STATE_CONNECTED : 233ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie BluetoothProfile.STATE_DISCONNECTED; 234b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski 235b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski mHandler.post(new Runnable() { 236b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski @Override 237b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski public void run() { 238b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski mCallback.onConnectionStateChange(BluetoothGatt.this, status, profileState); 239b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski } 240b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski }); 241ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie 242ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie synchronized(mStateLock) { 243ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (connected) { 244ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie mConnState = CONN_STATE_CONNECTED; 245ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } else { 246ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie mConnState = CONN_STATE_IDLE; 247ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 248ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 249cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach 250cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach synchronized(mDeviceBusy) { 251cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach mDeviceBusy = false; 252cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach } 2539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 2549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 2559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 2569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Remote search has been completed. 2579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * The internal object structure should now reflect the state 2589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * of the remote device database. Let the application know that 2599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * we are done at this point. 2609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @hide 2619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 262326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski @Override 263bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski public void onSearchComplete(String address, List<BluetoothGattService> services, 264bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski int status) { 2659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (DBG) Log.d(TAG, "onSearchComplete() = Device=" + address + " Status=" + status); 266ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (!address.equals(mDevice.getAddress())) { 267ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie return; 268ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 269bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski 270bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski for (BluetoothGattService s : services) { 271bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski //services we receive don't have device set properly. 272bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski s.setDevice(mDevice); 273bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski } 274bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski 275bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski mServices.addAll(services); 276bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski 277bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski // Fix references to included services, as they doesn't point to right objects. 278bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski for (BluetoothGattService fixedService : mServices) { 279bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski ArrayList<BluetoothGattService> includedServices = 280bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski new ArrayList(fixedService.getIncludedServices()); 281bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski fixedService.getIncludedServices().clear(); 282bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski 283bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski for(BluetoothGattService brokenRef : includedServices) { 284bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski BluetoothGattService includedService = getService(mDevice, 285bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski brokenRef.getUuid(), brokenRef.getInstanceId(), brokenRef.getType()); 286bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski if (includedService != null) { 287bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski fixedService.addIncludedService(includedService); 288bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski } else { 289bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski Log.e(TAG, "Broken GATT database: can't find included service."); 290bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski } 291bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski } 292bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski } 293bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski 294b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski mHandler.post(new Runnable() { 295b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski @Override 296b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski public void run() { 297b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski mCallback.onServicesDiscovered(BluetoothGatt.this, status); 298b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski } 299b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski }); 3009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 3019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 3029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 3039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Remote characteristic has been read. 3049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Updates the internal value. 3059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @hide 3069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 307326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski @Override 308c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski public void onCharacteristicRead(String address, int status, int handle, byte[] value) { 30955d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach if (VDBG) Log.d(TAG, "onCharacteristicRead() - Device=" + address 310c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski + " handle=" + handle + " Status=" + status); 311c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski 312ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (!address.equals(mDevice.getAddress())) { 313ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie return; 314ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 315cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach 316cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach synchronized(mDeviceBusy) { 317cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach mDeviceBusy = false; 318cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach } 319cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach 3209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if ((status == GATT_INSUFFICIENT_AUTHENTICATION 3219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta || status == GATT_INSUFFICIENT_ENCRYPTION) 3223854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung && (mAuthRetryState != AUTH_RETRY_STATE_MITM)) { 3239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta try { 3243854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE) ? 3253854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM; 3263854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung mService.readCharacteristic(mClientIf, address, handle, authReq); 3273854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung mAuthRetryState++; 3289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return; 3299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } catch (RemoteException e) { 3309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta Log.e(TAG,"",e); 3319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 3329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 3339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 3343854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung mAuthRetryState = AUTH_RETRY_STATE_IDLE; 3359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 336c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski BluetoothGattCharacteristic characteristic = getCharacteristicById(mDevice, handle); 337c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski if (characteristic == null) { 338c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski Log.w(TAG, "onCharacteristicRead() failed to find characteristic!"); 339c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski return; 340c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski } 3419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 3429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (status == 0) characteristic.setValue(value); 3439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 344b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski mHandler.post(new Runnable() { 345b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski @Override 346b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski public void run() { 347b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski mCallback.onCharacteristicRead(BluetoothGatt.this, characteristic, status); 348b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski } 349b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski }); 3509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 3519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 3529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 3539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Characteristic has been written to the remote device. 3549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Let the app know how we did... 3559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @hide 3569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 357326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski @Override 358c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski public void onCharacteristicWrite(String address, int status, int handle) { 35955d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach if (VDBG) Log.d(TAG, "onCharacteristicWrite() - Device=" + address 360c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski + " handle=" + handle + " Status=" + status); 3619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 362ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (!address.equals(mDevice.getAddress())) { 363ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie return; 364ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 365cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach 366cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach synchronized(mDeviceBusy) { 367cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach mDeviceBusy = false; 368cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach } 369cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach 370c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski BluetoothGattCharacteristic characteristic = getCharacteristicById(mDevice, handle); 3719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (characteristic == null) return; 3729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 3739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if ((status == GATT_INSUFFICIENT_AUTHENTICATION 3749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta || status == GATT_INSUFFICIENT_ENCRYPTION) 3753854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung && (mAuthRetryState != AUTH_RETRY_STATE_MITM)) { 3769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta try { 3773854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE) ? 3783854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM; 379c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski mService.writeCharacteristic(mClientIf, address, handle, 3803854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung characteristic.getWriteType(), authReq, characteristic.getValue()); 3813854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung mAuthRetryState++; 3829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return; 3839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } catch (RemoteException e) { 3849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta Log.e(TAG,"",e); 3859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 3869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 3879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 3883854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung mAuthRetryState = AUTH_RETRY_STATE_IDLE; 3899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 390b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski mHandler.post(new Runnable() { 391b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski @Override 392b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski public void run() { 393b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski mCallback.onCharacteristicWrite(BluetoothGatt.this, characteristic, status); 394b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski } 395b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski }); 3969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 3979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 3989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 3999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Remote characteristic has been updated. 4009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Updates the internal value. 4019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @hide 4029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 403326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski @Override 404c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski public void onNotify(String address, int handle, byte[] value) { 405c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski if (VDBG) Log.d(TAG, "onNotify() - Device=" + address + " handle=" + handle); 4069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 407ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (!address.equals(mDevice.getAddress())) { 408ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie return; 409ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 4109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 411c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski BluetoothGattCharacteristic characteristic = getCharacteristicById(mDevice, handle); 4129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (characteristic == null) return; 4139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 4149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta characteristic.setValue(value); 4159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 416b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski mHandler.post(new Runnable() { 417b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski @Override 418b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski public void run() { 419b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski mCallback.onCharacteristicChanged(BluetoothGatt.this, characteristic); 420b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski } 421b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski }); 4229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 4239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 4249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 4259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Descriptor has been read. 4269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @hide 4279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 428326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski @Override 429c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski public void onDescriptorRead(String address, int status, int handle, byte[] value) { 430c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski if (VDBG) Log.d(TAG, "onDescriptorRead() - Device=" + address + " handle=" + handle); 4319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 432ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (!address.equals(mDevice.getAddress())) { 433ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie return; 434ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 435cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach 436cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach synchronized(mDeviceBusy) { 437cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach mDeviceBusy = false; 438cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach } 439cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach 440c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski BluetoothGattDescriptor descriptor = getDescriptorById(mDevice, handle); 4419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (descriptor == null) return; 4429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 4439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (status == 0) descriptor.setValue(value); 4449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 4459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if ((status == GATT_INSUFFICIENT_AUTHENTICATION 4469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta || status == GATT_INSUFFICIENT_ENCRYPTION) 4473854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung && (mAuthRetryState != AUTH_RETRY_STATE_MITM)) { 4489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta try { 4493854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE) ? 4503854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM; 4513854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung mService.readDescriptor(mClientIf, address, handle, authReq); 4523854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung mAuthRetryState++; 453d65e8f4b6b37b274fcd5b7701a73eaef7c4ba8b4Andre Eisenbach return; 4549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } catch (RemoteException e) { 4559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta Log.e(TAG,"",e); 4569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 4579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 4589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 4593854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung mAuthRetryState = AUTH_RETRY_STATE_IDLE; 4609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 461b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski mHandler.post(new Runnable() { 462b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski @Override 463b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski public void run() { 464b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski mCallback.onDescriptorRead(BluetoothGatt.this, descriptor, status); 465b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski } 466b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski }); 4679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 4689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 4699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 4709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Descriptor write operation complete. 4719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @hide 4729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 473326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski @Override 474c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski public void onDescriptorWrite(String address, int status, int handle) { 475c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski if (VDBG) Log.d(TAG, "onDescriptorWrite() - Device=" + address + " handle=" + handle); 4769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 477ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (!address.equals(mDevice.getAddress())) { 478ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie return; 479ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 480cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach 481cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach synchronized(mDeviceBusy) { 482cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach mDeviceBusy = false; 483cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach } 484cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach 485c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski BluetoothGattDescriptor descriptor = getDescriptorById(mDevice, handle); 4869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (descriptor == null) return; 4879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 4889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if ((status == GATT_INSUFFICIENT_AUTHENTICATION 4899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta || status == GATT_INSUFFICIENT_ENCRYPTION) 4903854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung && (mAuthRetryState != AUTH_RETRY_STATE_MITM)) { 4919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta try { 4923854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE) ? 4933854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM; 494c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski mService.writeDescriptor(mClientIf, address, handle, 4953854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung authReq, descriptor.getValue()); 4963854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung mAuthRetryState++; 497d65e8f4b6b37b274fcd5b7701a73eaef7c4ba8b4Andre Eisenbach return; 4989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } catch (RemoteException e) { 4999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta Log.e(TAG,"",e); 5009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 5019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 5029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 5033854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung mAuthRetryState = AUTH_RETRY_STATE_IDLE; 5049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 505b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski mHandler.post(new Runnable() { 506b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski @Override 507b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski public void run() { 508b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski mCallback.onDescriptorWrite(BluetoothGatt.this, descriptor, status); 509b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski } 510b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski }); 5119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 5129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 5139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 5149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Prepared write transaction completed (or aborted) 5159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @hide 5169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 517326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski @Override 5189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public void onExecuteWrite(String address, int status) { 51955d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach if (VDBG) Log.d(TAG, "onExecuteWrite() - Device=" + address 5209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta + " status=" + status); 521ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (!address.equals(mDevice.getAddress())) { 522ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie return; 523ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 524cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach 525cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach synchronized(mDeviceBusy) { 526cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach mDeviceBusy = false; 527cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach } 528cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach 529b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski mHandler.post(new Runnable() { 530b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski @Override 531b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski public void run() { 532b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski mCallback.onReliableWriteCompleted(BluetoothGatt.this, status); 533b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski } 534b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski }); 5359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 5369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 5379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 5389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Remote device RSSI has been read 5399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @hide 5409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 541326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski @Override 5429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public void onReadRemoteRssi(String address, int rssi, int status) { 54355d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach if (VDBG) Log.d(TAG, "onReadRemoteRssi() - Device=" + address + 5449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta " rssi=" + rssi + " status=" + status); 545ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (!address.equals(mDevice.getAddress())) { 546ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie return; 547ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 548b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski mHandler.post(new Runnable() { 549b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski @Override 550b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski public void run() { 551b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski mCallback.onReadRemoteRssi(BluetoothGatt.this, rssi, status); 552b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski } 553b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski }); 5549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 555f305589f22f3fa1d73f2e29009d382c9a4f5c293Wei Wang 556f305589f22f3fa1d73f2e29009d382c9a4f5c293Wei Wang /** 557580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach * Callback invoked when the MTU for a given connection changes 558580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach * @hide 559580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach */ 560326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski @Override 561580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach public void onConfigureMTU(String address, int mtu, int status) { 562580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach if (DBG) Log.d(TAG, "onConfigureMTU() - Device=" + address + 563580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach " mtu=" + mtu + " status=" + status); 564580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach if (!address.equals(mDevice.getAddress())) { 565580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach return; 566580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach } 567b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski 568b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski mHandler.post(new Runnable() { 569b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski @Override 570b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski public void run() { 571b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski mCallback.onMtuChanged(BluetoothGatt.this, mtu, status); 572b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski } 573b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski }); 574f305589f22f3fa1d73f2e29009d382c9a4f5c293Wei Wang } 575326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski 576326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski /** 577326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski * Callback invoked when the given connection is updated 578326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski * @hide 579326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski */ 580326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski @Override 581326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski public void onConnectionUpdated(String address, int interval, int latency, 582326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski int timeout, int status) { 583326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski if (DBG) Log.d(TAG, "onConnectionUpdated() - Device=" + address + 584326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski " interval=" + interval + " latency=" + latency + 585326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski " timeout=" + timeout + " status=" + status); 586326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski if (!address.equals(mDevice.getAddress())) { 587326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski return; 588326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski } 589b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski 590b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski mHandler.post(new Runnable() { 591b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski @Override 592b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski public void run() { 593b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski mCallback.onConnectionUpdated(BluetoothGatt.this, interval, latency, 594b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski timeout, status); 595b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski } 596b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski }); 597326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski } 5989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta }; 5999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 600adc26ec1b4060358d918d1bdf491f5192b35c2d3Jeremy Klein /*package*/ BluetoothGatt(IBluetoothGatt iGatt, BluetoothDevice device, 601db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski int transport, int phy) { 602ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie mService = iGatt; 603ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie mDevice = device; 604b88fa824ab6337684de9aa8437c4952df4f1a75eGanesh Ganapathi Batta mTransport = transport; 605db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski mPhy = phy; 6069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mServices = new ArrayList<BluetoothGattService>(); 6079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 608ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie mConnState = CONN_STATE_IDLE; 6093854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung mAuthRetryState = AUTH_RETRY_STATE_IDLE; 6109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 6119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 6129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 61333ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie * Close this Bluetooth GATT client. 614b30f91e38c19f6728d836293446d4b9c76705e7fMatthew Xie * 615b30f91e38c19f6728d836293446d4b9c76705e7fMatthew Xie * Application should call this method as early as possible after it is done with 616b30f91e38c19f6728d836293446d4b9c76705e7fMatthew Xie * this GATT client. 6179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 61833ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie public void close() { 6199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (DBG) Log.d(TAG, "close()"); 6209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 6219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta unregisterApp(); 62233ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie mConnState = CONN_STATE_CLOSED; 6233854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung mAuthRetryState = AUTH_RETRY_STATE_IDLE; 6249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 6259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 6269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 6279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Returns a service by UUID, instance and type. 6289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @hide 6299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 6309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /*package*/ BluetoothGattService getService(BluetoothDevice device, UUID uuid, 6319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta int instanceId, int type) { 6329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta for(BluetoothGattService svc : mServices) { 6339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (svc.getDevice().equals(device) && 6349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta svc.getType() == type && 6359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta svc.getInstanceId() == instanceId && 6369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta svc.getUuid().equals(uuid)) { 6379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return svc; 6389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 6399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 6409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return null; 6419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 6429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 6439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 6449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 645c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski * Returns a characteristic with id equal to instanceId. 646c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski * @hide 647c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski */ 648c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski /*package*/ BluetoothGattCharacteristic getCharacteristicById(BluetoothDevice device, int instanceId) { 649c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski for(BluetoothGattService svc : mServices) { 650c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski for(BluetoothGattCharacteristic charac : svc.getCharacteristics()) { 651c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski if (charac.getInstanceId() == instanceId) 652c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski return charac; 653c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski } 654c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski } 655c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski return null; 656c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski } 657c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski 658c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski /** 659c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski * Returns a descriptor with id equal to instanceId. 660c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski * @hide 661c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski */ 662c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski /*package*/ BluetoothGattDescriptor getDescriptorById(BluetoothDevice device, int instanceId) { 663c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski for(BluetoothGattService svc : mServices) { 664c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski for(BluetoothGattCharacteristic charac : svc.getCharacteristics()) { 665c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski for(BluetoothGattDescriptor desc : charac.getDescriptors()) { 666c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski if (desc.getInstanceId() == instanceId) 667c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski return desc; 668c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski } 669c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski } 670c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski } 671c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski return null; 672c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski } 673c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski 674c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski /** 675ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * Register an application callback to start using GATT. 6769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 677d64bb883d822e1db445e09e77150ffd281e83cbeJakub Pawlowski * <p>This is an asynchronous call. The callback {@link BluetoothGattCallback#onAppRegistered} 678ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * is used to notify success or failure if the function returns true. 6799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 6809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 6819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 682ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * @param callback GATT callback handler that will receive asynchronous callbacks. 683ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * @return If true, the callback will be called to notify success or failure, 684ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * false on immediate error 6859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 686b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski private boolean registerApp(BluetoothGattCallback callback, Handler handler) { 6879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (DBG) Log.d(TAG, "registerApp()"); 6889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (mService == null) return false; 6899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 6909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mCallback = callback; 691b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski mHandler = handler; 6929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta UUID uuid = UUID.randomUUID(); 6939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (DBG) Log.d(TAG, "registerApp() - UUID=" + uuid); 6949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 6959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta try { 696d64bb883d822e1db445e09e77150ffd281e83cbeJakub Pawlowski mService.registerClient(new ParcelUuid(uuid), mBluetoothGattCallback); 6979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } catch (RemoteException e) { 6989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta Log.e(TAG,"",e); 6999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return false; 7009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 7019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 7029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return true; 7039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 7049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 7059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 7069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Unregister the current application and callbacks. 7079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 708ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie private void unregisterApp() { 7099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (DBG) Log.d(TAG, "unregisterApp() - mClientIf=" + mClientIf); 7109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (mService == null || mClientIf == 0) return; 7119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 7129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta try { 7139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mCallback = null; 7149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mService.unregisterClient(mClientIf); 7159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mClientIf = 0; 7169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } catch (RemoteException e) { 7179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta Log.e(TAG,"",e); 7189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 7199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 7209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 7219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 722ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * Initiate a connection to a Bluetooth GATT capable device. 7239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 7249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>The connection may not be established right away, but will be 7259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * completed when the remote device is available. A 726d64bb883d822e1db445e09e77150ffd281e83cbeJakub Pawlowski * {@link BluetoothGattCallback#onConnectionStateChange} callback will be 7279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * invoked when the connection state changes as a result of this function. 7289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 7296ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach * <p>The autoConnect parameter determines whether to actively connect to 7309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * the remote device, or rather passively scan and finalize the connection 7319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * when the remote device is in range/available. Generally, the first ever 7329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * connection to a device should be direct (autoConnect set to false) and 7339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * subsequent connections to known devices should be invoked with the 734ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * autoConnect parameter set to true. 7359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 7369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 7379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 7389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @param device Remote device to connect to 7399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @param autoConnect Whether to directly connect to the remote device (false) 7409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * or to automatically connect as soon as the remote 7419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * device becomes available (true). 7429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @return true, if the connection attempt was initiated successfully 7439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 744b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski /*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallback callback, 745b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski Handler handler) { 746ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (DBG) Log.d(TAG, "connect() - device: " + mDevice.getAddress() + ", auto: " + autoConnect); 747ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie synchronized(mStateLock) { 748ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (mConnState != CONN_STATE_IDLE) { 749ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie throw new IllegalStateException("Not idle"); 750ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 751ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie mConnState = CONN_STATE_CONNECTING; 752ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 753d35167adcaa40cb54df8e392379dfdfe98bcdba2Sungki Kim 754d35167adcaa40cb54df8e392379dfdfe98bcdba2Sungki Kim mAutoConnect = autoConnect; 755d35167adcaa40cb54df8e392379dfdfe98bcdba2Sungki Kim 756b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski if (!registerApp(callback, handler)) { 757ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie synchronized(mStateLock) { 758ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie mConnState = CONN_STATE_IDLE; 759ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 760ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie Log.e(TAG, "Failed to register callback"); 7619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return false; 7629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 7639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 764d35167adcaa40cb54df8e392379dfdfe98bcdba2Sungki Kim // The connection will continue in the onClientRegistered callback 7659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return true; 7669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 7679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 7689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 7699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Disconnects an established connection, or cancels a connection attempt 7709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * currently in progress. 7719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 7729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 7739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 774ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie public void disconnect() { 775ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (DBG) Log.d(TAG, "cancelOpen() - device: " + mDevice.getAddress()); 7769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (mService == null || mClientIf == 0) return; 7779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 7789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta try { 779ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie mService.clientDisconnect(mClientIf, mDevice.getAddress()); 7809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } catch (RemoteException e) { 7819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta Log.e(TAG,"",e); 7829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 78333ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie } 78433ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie 78533ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie /** 78633ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie * Connect back to remote device. 78733ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie * 78833ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie * <p>This method is used to re-connect to a remote device after the 78933ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie * connection has been dropped. If the device is not in range, the 79033ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie * re-connection will be triggered once the device is back in range. 79133ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie * 79233ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie * @return true, if the connection attempt was initiated successfully 79333ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie */ 79433ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie public boolean connect() { 79533ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie try { 79633ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie mService.clientConnect(mClientIf, mDevice.getAddress(), 797db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski false, mTransport, mPhy); // autoConnect is inverse of "isDirect" 79833ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie return true; 79933ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie } catch (RemoteException e) { 80033ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie Log.e(TAG,"",e); 80133ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie return false; 80233ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie } 80333ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie } 80433ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie 80533ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie /** 806db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski * Set the preferred connection PHY for this app. Please note that this is just a 807f752ace75a931f7a645a8e65462b91a7185ed1d4Jakub Pawlowski * recommendation, whether the PHY change will happen depends on other applications peferences, 808db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski * local and remote controller capabilities. Controller can override these settings. 809db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski * <p> 810d64bb883d822e1db445e09e77150ffd281e83cbeJakub Pawlowski * {@link BluetoothGattCallback#onPhyUpdate} will be triggered as a result of this call, even 811db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski * if no PHY change happens. It is also triggered when remote device updates the PHY. 812db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski * 813db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski * @param txPhy preferred transmitter PHY. Bitwise OR of any of 814a51513747aee764628871d2919f434dcbe38b67cJakub Pawlowski * {@link BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, 815a51513747aee764628871d2919f434dcbe38b67cJakub Pawlowski * and {@link BluetoothDevice#PHY_LE_CODED_MASK}. 816db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski * @param rxPhy preferred receiver PHY. Bitwise OR of any of 817a51513747aee764628871d2919f434dcbe38b67cJakub Pawlowski * {@link BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, 818a51513747aee764628871d2919f434dcbe38b67cJakub Pawlowski * and {@link BluetoothDevice#PHY_LE_CODED_MASK}. 819db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski * @param phyOptions preferred coding to use when transmitting on the LE Coded PHY. Can be one 820db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski * of {@link BluetoothDevice#PHY_OPTION_NO_PREFERRED}, 821db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski * {@link BluetoothDevice#PHY_OPTION_S2} or {@link BluetoothDevice#PHY_OPTION_S8} 822db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski */ 823db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski public void setPreferredPhy(int txPhy, int rxPhy, int phyOptions) { 824db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski try { 825db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski mService.clientSetPreferredPhy(mClientIf, mDevice.getAddress(), txPhy, rxPhy, 826db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski phyOptions); 827db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski } catch (RemoteException e) { 828db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski Log.e(TAG,"",e); 829db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski } 830db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski } 831db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski 832db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski /** 833db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski * Read the current transmitter PHY and receiver PHY of the connection. The values are returned 834d64bb883d822e1db445e09e77150ffd281e83cbeJakub Pawlowski * in {@link BluetoothGattCallback#onPhyRead} 835db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski */ 836db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski public void readPhy() { 837db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski try { 838db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski mService.clientReadPhy(mClientIf, mDevice.getAddress()); 839db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski } catch (RemoteException e) { 840db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski Log.e(TAG,"",e); 841db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski } 842db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski } 843db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski 844db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski /** 84533ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie * Return the remote bluetooth device this GATT client targets to 84633ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie * 84733ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie * @return remote bluetooth device 84833ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie */ 84933ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie public BluetoothDevice getDevice() { 85033ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie return mDevice; 8519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 8529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 8539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 8549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Discovers services offered by a remote device as well as their 8559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * characteristics and descriptors. 8569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 8579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>This is an asynchronous operation. Once service discovery is completed, 858d64bb883d822e1db445e09e77150ffd281e83cbeJakub Pawlowski * the {@link BluetoothGattCallback#onServicesDiscovered} callback is 8599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * triggered. If the discovery was successful, the remote services can be 8609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * retrieved using the {@link #getServices} function. 8619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 8629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 8639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 8649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @return true, if the remote service discovery has been started 8659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 866ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie public boolean discoverServices() { 867ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (DBG) Log.d(TAG, "discoverServices() - device: " + mDevice.getAddress()); 8689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (mService == null || mClientIf == 0) return false; 8699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 8709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mServices.clear(); 8719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 8729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta try { 873ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie mService.discoverServices(mClientIf, mDevice.getAddress()); 8749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } catch (RemoteException e) { 8759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta Log.e(TAG,"",e); 8769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return false; 8779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 8789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 8799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return true; 8809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 8819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 8829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 8839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Returns a list of GATT services offered by the remote device. 8849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 8859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>This function requires that service discovery has been completed 8869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * for the given device. 8879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 8889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 8899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 8909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @return List of services on the remote device. Returns an empty list 8919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * if service discovery has not yet been performed. 8929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 893ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie public List<BluetoothGattService> getServices() { 8949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta List<BluetoothGattService> result = 8959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta new ArrayList<BluetoothGattService>(); 8969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 8979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta for (BluetoothGattService service : mServices) { 898ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (service.getDevice().equals(mDevice)) { 8999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta result.add(service); 9009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 9019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 9029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 9039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return result; 9049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 9059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 9069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 9079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Returns a {@link BluetoothGattService}, if the requested UUID is 9089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * supported by the remote device. 9099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 9109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>This function requires that service discovery has been completed 9119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * for the given device. 9129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 9139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>If multiple instances of the same service (as identified by UUID) 9149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * exist, the first instance of the service is returned. 9159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 9169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 9179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 9189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @param uuid UUID of the requested service 9199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @return BluetoothGattService if supported, or null if the requested 9209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * service is not offered by the remote device. 9219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 922ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie public BluetoothGattService getService(UUID uuid) { 9239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta for (BluetoothGattService service : mServices) { 924ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (service.getDevice().equals(mDevice) && 9259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta service.getUuid().equals(uuid)) { 9269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return service; 9279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 9289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 9299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 9309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return null; 9319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 9329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 9339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 9349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Reads the requested characteristic from the associated remote device. 9359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 9369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>This is an asynchronous operation. The result of the read operation 937d64bb883d822e1db445e09e77150ffd281e83cbeJakub Pawlowski * is reported by the {@link BluetoothGattCallback#onCharacteristicRead} 9389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * callback. 9399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 9409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 9419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 9429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @param characteristic Characteristic to read from the remote device 9439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @return true, if the read operation was initiated successfully 9449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 9459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public boolean readCharacteristic(BluetoothGattCharacteristic characteristic) { 9469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if ((characteristic.getProperties() & 9479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta BluetoothGattCharacteristic.PROPERTY_READ) == 0) return false; 9489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 94955d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach if (VDBG) Log.d(TAG, "readCharacteristic() - uuid: " + characteristic.getUuid()); 9509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (mService == null || mClientIf == 0) return false; 9519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 9529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta BluetoothGattService service = characteristic.getService(); 9539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (service == null) return false; 9549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 9559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta BluetoothDevice device = service.getDevice(); 9569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (device == null) return false; 9579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 958cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach synchronized(mDeviceBusy) { 959cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach if (mDeviceBusy) return false; 960cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach mDeviceBusy = true; 961cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach } 962cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach 9639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta try { 9649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mService.readCharacteristic(mClientIf, device.getAddress(), 965c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski characteristic.getInstanceId(), AUTHENTICATION_NONE); 9669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } catch (RemoteException e) { 9679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta Log.e(TAG,"",e); 968cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach mDeviceBusy = false; 9699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return false; 9709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 9719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 9729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return true; 9739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 9749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 9759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 976ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski * Reads the characteristic using its UUID from the associated remote device. 977ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski * 978ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski * <p>This is an asynchronous operation. The result of the read operation 979ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski * is reported by the {@link BluetoothGattCallback#onCharacteristicRead} 980ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski * callback. 981ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski * 982ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 983ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski * 984ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski * @param uuid UUID of characteristic to read from the remote device 985ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski * @return true, if the read operation was initiated successfully 986ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski * @hide 987ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski */ 988ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski public boolean readUsingCharacteristicUuid(UUID uuid, int startHandle, int endHandle) { 989ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski if (VDBG) Log.d(TAG, "readUsingCharacteristicUuid() - uuid: " + uuid); 990ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski if (mService == null || mClientIf == 0) return false; 991ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski 992ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski synchronized(mDeviceBusy) { 993ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski if (mDeviceBusy) return false; 994ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski mDeviceBusy = true; 995ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski } 996ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski 997ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski try { 998ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski mService.readUsingCharacteristicUuid(mClientIf, mDevice.getAddress(), 999ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski new ParcelUuid(uuid), startHandle, endHandle, AUTHENTICATION_NONE); 1000ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski } catch (RemoteException e) { 1001ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski Log.e(TAG,"",e); 1002ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski mDeviceBusy = false; 1003ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski return false; 1004ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski } 1005ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski 1006ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski return true; 1007ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski } 1008ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski 1009ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski 1010ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski /** 1011ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * Writes a given characteristic and its values to the associated remote device. 10129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 10139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>Once the write operation has been completed, the 1014d64bb883d822e1db445e09e77150ffd281e83cbeJakub Pawlowski * {@link BluetoothGattCallback#onCharacteristicWrite} callback is invoked, 10159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * reporting the result of the operation. 10169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 10179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 10189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 10199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @param characteristic Characteristic to write on the remote device 10209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @return true, if the write operation was initiated successfully 10219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 10229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public boolean writeCharacteristic(BluetoothGattCharacteristic characteristic) { 10239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE) == 0 10249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta && (characteristic.getProperties() & 10259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) == 0) return false; 10269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 102755d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach if (VDBG) Log.d(TAG, "writeCharacteristic() - uuid: " + characteristic.getUuid()); 1028ff5e5db319785d23d672af95ac2dff3f37827cfdPrerepa Viswanadham if (mService == null || mClientIf == 0 || characteristic.getValue() == null) return false; 10299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 10309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta BluetoothGattService service = characteristic.getService(); 10319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (service == null) return false; 10329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 10339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta BluetoothDevice device = service.getDevice(); 10349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (device == null) return false; 10359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 1036cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach synchronized(mDeviceBusy) { 1037cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach if (mDeviceBusy) return false; 1038cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach mDeviceBusy = true; 1039cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach } 1040cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach 10419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta try { 10429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mService.writeCharacteristic(mClientIf, device.getAddress(), 1043c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski characteristic.getInstanceId(), characteristic.getWriteType(), 1044c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski AUTHENTICATION_NONE, characteristic.getValue()); 10459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } catch (RemoteException e) { 10469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta Log.e(TAG,"",e); 1047cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach mDeviceBusy = false; 10489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return false; 10499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 10509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 10519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return true; 10529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 10539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 10549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 10559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Reads the value for a given descriptor from the associated remote device. 10569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 10579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>Once the read operation has been completed, the 1058d64bb883d822e1db445e09e77150ffd281e83cbeJakub Pawlowski * {@link BluetoothGattCallback#onDescriptorRead} callback is 10599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * triggered, signaling the result of the operation. 10609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 10619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 10629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 10639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @param descriptor Descriptor value to read from the remote device 10649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @return true, if the read operation was initiated successfully 10659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 10669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public boolean readDescriptor(BluetoothGattDescriptor descriptor) { 106755d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach if (VDBG) Log.d(TAG, "readDescriptor() - uuid: " + descriptor.getUuid()); 10689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (mService == null || mClientIf == 0) return false; 10699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 10709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic(); 10719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (characteristic == null) return false; 10729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 10739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta BluetoothGattService service = characteristic.getService(); 10749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (service == null) return false; 10759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 10769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta BluetoothDevice device = service.getDevice(); 10779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (device == null) return false; 10789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 1079cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach synchronized(mDeviceBusy) { 1080cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach if (mDeviceBusy) return false; 1081cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach mDeviceBusy = true; 1082cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach } 1083cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach 10849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta try { 1085c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski mService.readDescriptor(mClientIf, device.getAddress(), 1086c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski descriptor.getInstanceId(), AUTHENTICATION_NONE); 10879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } catch (RemoteException e) { 10889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta Log.e(TAG,"",e); 1089cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach mDeviceBusy = false; 10909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return false; 10919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 10929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 10939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return true; 10949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 10959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 10969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 10979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Write the value of a given descriptor to the associated remote device. 10989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 1099d64bb883d822e1db445e09e77150ffd281e83cbeJakub Pawlowski * <p>A {@link BluetoothGattCallback#onDescriptorWrite} callback is 11009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * triggered to report the result of the write operation. 11019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 11029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 11039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 11049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @param descriptor Descriptor to write to the associated remote device 11059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @return true, if the write operation was initiated successfully 11069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 11079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public boolean writeDescriptor(BluetoothGattDescriptor descriptor) { 110855d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach if (VDBG) Log.d(TAG, "writeDescriptor() - uuid: " + descriptor.getUuid()); 1109ff5e5db319785d23d672af95ac2dff3f37827cfdPrerepa Viswanadham if (mService == null || mClientIf == 0 || descriptor.getValue() == null) return false; 11109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 11119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic(); 11129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (characteristic == null) return false; 11139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 11149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta BluetoothGattService service = characteristic.getService(); 11159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (service == null) return false; 11169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 11179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta BluetoothDevice device = service.getDevice(); 11189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (device == null) return false; 11199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 1120cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach synchronized(mDeviceBusy) { 1121cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach if (mDeviceBusy) return false; 1122cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach mDeviceBusy = true; 1123cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach } 1124cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach 11259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta try { 1126c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski mService.writeDescriptor(mClientIf, device.getAddress(), descriptor.getInstanceId(), 11278e970d6ab4850ca23163bad5773cf5cc2e7ff896Jakub Pawlowski AUTHENTICATION_NONE, descriptor.getValue()); 11289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } catch (RemoteException e) { 11299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta Log.e(TAG,"",e); 1130cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach mDeviceBusy = false; 11319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return false; 11329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 11339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 11349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return true; 11359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 11369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 11379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 11389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Initiates a reliable write transaction for a given remote device. 11399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 11409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>Once a reliable write transaction has been initiated, all calls 11419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * to {@link #writeCharacteristic} are sent to the remote device for 11429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * verification and queued up for atomic execution. The application will 1143d64bb883d822e1db445e09e77150ffd281e83cbeJakub Pawlowski * receive an {@link BluetoothGattCallback#onCharacteristicWrite} callback 11449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * in response to every {@link #writeCharacteristic} call and is responsible 11459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * for verifying if the value has been transmitted accurately. 11469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 11479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>After all characteristics have been queued up and verified, 11489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * {@link #executeReliableWrite} will execute all writes. If a characteristic 11499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * was not written correctly, calling {@link #abortReliableWrite} will 11509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * cancel the current transaction without commiting any values on the 11519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * remote device. 11529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 11539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 11549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 11559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @return true, if the reliable write transaction has been initiated 11569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 1157ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie public boolean beginReliableWrite() { 115855d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach if (VDBG) Log.d(TAG, "beginReliableWrite() - device: " + mDevice.getAddress()); 11599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (mService == null || mClientIf == 0) return false; 11609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 11619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta try { 1162ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie mService.beginReliableWrite(mClientIf, mDevice.getAddress()); 11639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } catch (RemoteException e) { 11649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta Log.e(TAG,"",e); 11659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return false; 11669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 11679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 11689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return true; 11699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 11709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 11719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 11729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Executes a reliable write transaction for a given remote device. 11739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 11749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>This function will commit all queued up characteristic write 11759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * operations for a given remote device. 11769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 1177d64bb883d822e1db445e09e77150ffd281e83cbeJakub Pawlowski * <p>A {@link BluetoothGattCallback#onReliableWriteCompleted} callback is 11789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * invoked to indicate whether the transaction has been executed correctly. 11799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 11809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 11819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 11829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @return true, if the request to execute the transaction has been sent 11839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 1184ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie public boolean executeReliableWrite() { 118555d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach if (VDBG) Log.d(TAG, "executeReliableWrite() - device: " + mDevice.getAddress()); 11869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (mService == null || mClientIf == 0) return false; 11879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 1188cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach synchronized(mDeviceBusy) { 1189cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach if (mDeviceBusy) return false; 1190cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach mDeviceBusy = true; 1191cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach } 1192cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach 11939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta try { 1194ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie mService.endReliableWrite(mClientIf, mDevice.getAddress(), true); 11959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } catch (RemoteException e) { 11969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta Log.e(TAG,"",e); 1197cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach mDeviceBusy = false; 11989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return false; 11999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 12009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 12019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return true; 12029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 12039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 12049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 12059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Cancels a reliable write transaction for a given device. 12069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 12079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>Calling this function will discard all queued characteristic write 12089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * operations for a given remote device. 12099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 12109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 12119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 121248f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du public void abortReliableWrite() { 121355d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach if (VDBG) Log.d(TAG, "abortReliableWrite() - device: " + mDevice.getAddress()); 12149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (mService == null || mClientIf == 0) return; 12159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 12169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta try { 1217ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie mService.endReliableWrite(mClientIf, mDevice.getAddress(), false); 12189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } catch (RemoteException e) { 12199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta Log.e(TAG,"",e); 12209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 12219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 12229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 12239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 1224b7b7d7a05c164a56dd4155de4e84fc25ba706728John Du * @deprecated Use {@link #abortReliableWrite()} 122548f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du */ 1226514c5ef8d5774d8820ed1bf90fe53af1606cf106Aurimas Liutikas @Deprecated 122748f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du public void abortReliableWrite(BluetoothDevice mDevice) { 122848f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du abortReliableWrite(); 122948f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du } 123048f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du 123148f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du /** 12329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Enable or disable notifications/indications for a given characteristic. 12339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 12349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>Once notifications are enabled for a characteristic, a 1235d64bb883d822e1db445e09e77150ffd281e83cbeJakub Pawlowski * {@link BluetoothGattCallback#onCharacteristicChanged} callback will be 12369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * triggered if the remote device indicates that the given characteristic 12379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * has changed. 12389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 12399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 12409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 12419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @param characteristic The characteristic for which to enable notifications 12429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @param enable Set to true to enable notifications/indications 12439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @return true, if the requested notification status was set successfully 12449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 12459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public boolean setCharacteristicNotification(BluetoothGattCharacteristic characteristic, 12469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta boolean enable) { 12479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (DBG) Log.d(TAG, "setCharacteristicNotification() - uuid: " + characteristic.getUuid() 12489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta + " enable: " + enable); 12499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (mService == null || mClientIf == 0) return false; 12509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 12519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta BluetoothGattService service = characteristic.getService(); 12529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (service == null) return false; 12539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 12549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta BluetoothDevice device = service.getDevice(); 12559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (device == null) return false; 12569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 12579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta try { 12589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mService.registerForNotification(mClientIf, device.getAddress(), 1259c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski characteristic.getInstanceId(), enable); 12609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } catch (RemoteException e) { 12619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta Log.e(TAG,"",e); 12629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return false; 12639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 12649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 12659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return true; 12669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 12679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 12689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 12699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Clears the internal cache and forces a refresh of the services from the 12709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * remote device. 12719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @hide 12729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 1273ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie public boolean refresh() { 1274ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (DBG) Log.d(TAG, "refresh() - device: " + mDevice.getAddress()); 12759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (mService == null || mClientIf == 0) return false; 12769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 12779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta try { 1278ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie mService.refreshDevice(mClientIf, mDevice.getAddress()); 12799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } catch (RemoteException e) { 12809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta Log.e(TAG,"",e); 12819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return false; 12829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 12839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 12849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return true; 12859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 12869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 12879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 12889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Read the RSSI for a connected remote device. 12899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 1290d64bb883d822e1db445e09e77150ffd281e83cbeJakub Pawlowski * <p>The {@link BluetoothGattCallback#onReadRemoteRssi} callback will be 12919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * invoked when the RSSI value has been read. 12929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 12939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 12949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 12959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @return true, if the RSSI value has been requested successfully 12969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 1297ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie public boolean readRemoteRssi() { 1298ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (DBG) Log.d(TAG, "readRssi() - device: " + mDevice.getAddress()); 12999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (mService == null || mClientIf == 0) return false; 13009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 13019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta try { 1302ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie mService.readRemoteRssi(mClientIf, mDevice.getAddress()); 13039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } catch (RemoteException e) { 13049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta Log.e(TAG,"",e); 13059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return false; 13069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 13079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 13089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return true; 13099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 13109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 13119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 13124072da041da2911dd56635b530b276671ce0199dAndre Eisenbach * Request an MTU size used for a given connection. 1313580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach * 1314580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach * <p>When performing a write request operation (write without response), 1315580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach * the data sent is truncated to the MTU size. This function may be used 13164072da041da2911dd56635b530b276671ce0199dAndre Eisenbach * to request a larger MTU size to be able to send more data at once. 1317580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach * 1318d64bb883d822e1db445e09e77150ffd281e83cbeJakub Pawlowski * <p>A {@link BluetoothGattCallback#onMtuChanged} callback will indicate 1319580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach * whether this operation was successful. 1320580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach * 1321580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 1322580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach * 1323580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach * @return true, if the new MTU value has been requested successfully 1324580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach */ 13254072da041da2911dd56635b530b276671ce0199dAndre Eisenbach public boolean requestMtu(int mtu) { 1326580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach if (DBG) Log.d(TAG, "configureMTU() - device: " + mDevice.getAddress() 1327580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach + " mtu: " + mtu); 1328580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach if (mService == null || mClientIf == 0) return false; 1329580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach 1330580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach try { 1331580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach mService.configureMTU(mClientIf, mDevice.getAddress(), mtu); 1332580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach } catch (RemoteException e) { 1333580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach Log.e(TAG,"",e); 1334580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach return false; 1335580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach } 1336580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach 1337580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach return true; 1338580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach } 1339580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach 1340580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach /** 13416ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach * Request a connection parameter update. 13426ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach * 13436ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach * <p>This function will send a connection parameter update request to the 13446ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach * remote device. 13456ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach * 13466ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach * @param connectionPriority Request a specific connection priority. Must be one of 13474072da041da2911dd56635b530b276671ce0199dAndre Eisenbach * {@link BluetoothGatt#CONNECTION_PRIORITY_BALANCED}, 13484072da041da2911dd56635b530b276671ce0199dAndre Eisenbach * {@link BluetoothGatt#CONNECTION_PRIORITY_HIGH} 13494072da041da2911dd56635b530b276671ce0199dAndre Eisenbach * or {@link BluetoothGatt#CONNECTION_PRIORITY_LOW_POWER}. 13506ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach * @throws IllegalArgumentException If the parameters are outside of their 13516ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach * specified range. 13526ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach */ 13534072da041da2911dd56635b530b276671ce0199dAndre Eisenbach public boolean requestConnectionPriority(int connectionPriority) { 13544072da041da2911dd56635b530b276671ce0199dAndre Eisenbach if (connectionPriority < CONNECTION_PRIORITY_BALANCED || 13554072da041da2911dd56635b530b276671ce0199dAndre Eisenbach connectionPriority > CONNECTION_PRIORITY_LOW_POWER) { 13566ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach throw new IllegalArgumentException("connectionPriority not within valid range"); 13576ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach } 13586ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach 13594072da041da2911dd56635b530b276671ce0199dAndre Eisenbach if (DBG) Log.d(TAG, "requestConnectionPriority() - params: " + connectionPriority); 13606ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach if (mService == null || mClientIf == 0) return false; 13616ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach 13626ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach try { 13636ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach mService.connectionParameterUpdate(mClientIf, mDevice.getAddress(), connectionPriority); 13646ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach } catch (RemoteException e) { 13656ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach Log.e(TAG,"",e); 13666ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach return false; 13676ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach } 13686ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach 13696ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach return true; 13706ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach } 13716ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach 13726ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach /** 1373ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)} 1374ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * with {@link BluetoothProfile#GATT} as argument 13759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 1376ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * @throws UnsupportedOperationException 13779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 13789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta @Override 13799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public int getConnectionState(BluetoothDevice device) { 1380ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie throw new UnsupportedOperationException("Use BluetoothManager#getConnectionState instead."); 13819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 13829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 13839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 1384ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)} 1385ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * with {@link BluetoothProfile#GATT} as argument 13869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 1387ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * @throws UnsupportedOperationException 13889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 13899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta @Override 13909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public List<BluetoothDevice> getConnectedDevices() { 1391ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie throw new UnsupportedOperationException 1392ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie ("Use BluetoothManager#getConnectedDevices instead."); 13939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 13949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 13959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 1396ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * Not supported - please use 1397ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * {@link BluetoothManager#getDevicesMatchingConnectionStates(int, int[])} 1398ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * with {@link BluetoothProfile#GATT} as first argument 13999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 1400ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * @throws UnsupportedOperationException 14019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 14029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta @Override 14039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 1404ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie throw new UnsupportedOperationException 1405ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie ("Use BluetoothManager#getDevicesMatchingConnectionStates instead."); 14069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 14079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta} 1408