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
19b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowskiimport android.os.Handler;
209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.os.ParcelUuid;
219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.os.RemoteException;
229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.util.Log;
239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport java.util.ArrayList;
259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport java.util.List;
269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport java.util.UUID;
279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta/**
29ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * Public API for the Bluetooth GATT Profile.
309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta *
31ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * <p>This class provides Bluetooth GATT functionality to enable communication
329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * with Bluetooth Smart or Smart Ready devices.
339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta *
34d64bb883d822e1db445e09e77150ffd281e83cbeJakub Pawlowski * <p>To connect to a remote peripheral device, create a {@link BluetoothGattCallback}
3533ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie * and call {@link BluetoothDevice#connectGatt} to get a instance of this class.
36ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * GATT capable devices can be discovered using the Bluetooth device discovery or BLE
37ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * scan process.
389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */
399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battapublic final class BluetoothGatt implements BluetoothProfile {
409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private static final String TAG = "BluetoothGatt";
419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private static final boolean DBG = true;
4255d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach    private static final boolean VDBG = false;
439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private IBluetoothGatt mService;
45d64bb883d822e1db445e09e77150ffd281e83cbeJakub Pawlowski    private BluetoothGattCallback mCallback;
46b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski    private Handler mHandler;
479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private int mClientIf;
48ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private BluetoothDevice mDevice;
49ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private boolean mAutoConnect;
503854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung    private int mAuthRetryState;
51ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private int mConnState;
52ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private final Object mStateLock = new Object();
53cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach    private Boolean mDeviceBusy = false;
54b88fa824ab6337684de9aa8437c4952df4f1a75eGanesh Ganapathi Batta    private int mTransport;
55db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski    private int mPhy;
56ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie
573854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung    private static final int AUTH_RETRY_STATE_IDLE = 0;
583854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung    private static final int AUTH_RETRY_STATE_NO_MITM = 1;
593854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung    private static final int AUTH_RETRY_STATE_MITM = 2;
603854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung
61ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private static final int CONN_STATE_IDLE = 0;
62ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private static final int CONN_STATE_CONNECTING = 1;
63ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private static final int CONN_STATE_CONNECTED = 2;
64ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private static final int CONN_STATE_DISCONNECTING = 3;
6533ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    private static final int CONN_STATE_CLOSED = 4;
669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private List<BluetoothGattService> mServices;
689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
69ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    /** A GATT operation completed successfully */
709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_SUCCESS = 0;
719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
72ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    /** GATT read operation is not permitted */
739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_READ_NOT_PERMITTED = 0x2;
749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
75ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    /** GATT write operation is not permitted */
769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_WRITE_NOT_PERMITTED = 0x3;
779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /** Insufficient authentication for a given operation */
799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_INSUFFICIENT_AUTHENTICATION = 0x5;
809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /** The given request is not supported */
829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_REQUEST_NOT_SUPPORTED = 0x6;
839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /** Insufficient encryption for a given operation */
859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_INSUFFICIENT_ENCRYPTION = 0xf;
869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /** A read or write operation was requested with an invalid offset */
889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_INVALID_OFFSET = 0x7;
899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /** A write operation exceeds the maximum length of the attribute */
919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_INVALID_ATTRIBUTE_LENGTH = 0xd;
929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9345a0a1a689518df7e2c904b902e28f6d68b76e2aAndre Eisenbach    /** A remote device connection is congested. */
94dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach    public static final int GATT_CONNECTION_CONGESTED = 0x8f;
95dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach
9690ca807f7b2037499112d1c49c4b0793cc780540Matthew Xie    /** A GATT operation failed, errors other than the above */
9790ca807f7b2037499112d1c49c4b0793cc780540Matthew Xie    public static final int GATT_FAILURE = 0x101;
9890ca807f7b2037499112d1c49c4b0793cc780540Matthew Xie
999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1006ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * Connection paramter update - Use the connection paramters recommended by the
1016ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * Bluetooth SIG. This is the default value if no connection parameter update
1026ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * is requested.
1036ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     */
1044072da041da2911dd56635b530b276671ce0199dAndre Eisenbach    public static final int CONNECTION_PRIORITY_BALANCED = 0;
1056ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach
1066ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach    /**
1076ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * Connection paramter update - Request a high priority, low latency connection.
1086ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * An application should only request high priority connection paramters to transfer
1096ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * large amounts of data over LE quickly. Once the transfer is complete, the application
1104072da041da2911dd56635b530b276671ce0199dAndre Eisenbach     * should request {@link BluetoothGatt#CONNECTION_PRIORITY_BALANCED} connectoin parameters
1116ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * to reduce energy use.
1126ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     */
1134072da041da2911dd56635b530b276671ce0199dAndre Eisenbach    public static final int CONNECTION_PRIORITY_HIGH = 1;
1146ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach
1156ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach    /** Connection paramter update - Request low power, reduced data rate connection parameters. */
1164072da041da2911dd56635b530b276671ce0199dAndre Eisenbach    public static final int CONNECTION_PRIORITY_LOW_POWER = 2;
1176ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach
1186ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach    /**
1199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * No authentication required.
1209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @hide
1219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /*package*/ static final int AUTHENTICATION_NONE = 0;
1239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Authentication requested; no man-in-the-middle protection required.
1269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @hide
1279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /*package*/ static final int AUTHENTICATION_NO_MITM = 1;
1299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Authentication with man-in-the-middle protection requested.
1329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @hide
1339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /*package*/ static final int AUTHENTICATION_MITM = 2;
1359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
137d64bb883d822e1db445e09e77150ffd281e83cbeJakub Pawlowski     * Bluetooth GATT callbacks. Overrides the default BluetoothGattCallback implementation.
1389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
139d7116bea0698f58e93003d2046411a2624dd1ab1Jakub Pawlowski    private final IBluetoothGattCallback mBluetoothGattCallback =
140d7116bea0698f58e93003d2046411a2624dd1ab1Jakub Pawlowski        new IBluetoothGattCallback.Stub() {
1419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
1429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Application interface registered - app is ready to go
1439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
1449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
145326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski            @Override
1469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onClientRegistered(int status, int clientIf) {
1479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onClientRegistered() - status=" + status
1489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    + " clientIf=" + clientIf);
149ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (VDBG) {
150ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    synchronized(mStateLock) {
151ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        if (mConnState != CONN_STATE_CONNECTING) {
152ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                            Log.e(TAG, "Bad connection state: " + mConnState);
153ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        }
154ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    }
155ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
1569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                mClientIf = clientIf;
157ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (status != GATT_SUCCESS) {
1586bdc550e27e2c4e7b32bb91085eaac898d7d1156Ruben Brunk                    runOrQueueCallback(new Runnable() {
159b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                        @Override
160b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                        public void run() {
1610e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                            if (mCallback != null) {
1620e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                                mCallback.onConnectionStateChange(BluetoothGatt.this, GATT_FAILURE,
1630e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                                                  BluetoothProfile.STATE_DISCONNECTED);
1640e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                            }
165b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                        }
166b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    });
167b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski
168ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    synchronized(mStateLock) {
169ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        mConnState = CONN_STATE_IDLE;
170ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    }
171ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
172ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
1739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
174ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    mService.clientConnect(mClientIf, mDevice.getAddress(),
175db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski                                           !mAutoConnect, mTransport, mPhy); // autoConnect is inverse of "isDirect"
176ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                } catch (RemoteException e) {
177ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    Log.e(TAG,"",e);
1789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
1799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
1809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
182db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski             * Phy update callback
183db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski             * @hide
184db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski             */
185db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski            @Override
186db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski            public void onPhyUpdate(String address, int txPhy, int rxPhy, int status) {
187db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski                if (DBG) Log.d(TAG, "onPhyUpdate() - status=" + status
188db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski                                 + " address=" + address + " txPhy=" + txPhy + " rxPhy=" + rxPhy);
189db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski                if (!address.equals(mDevice.getAddress())) {
190db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski                    return;
191db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski                }
192db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski
1936bdc550e27e2c4e7b32bb91085eaac898d7d1156Ruben Brunk                runOrQueueCallback(new Runnable() {
194b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    @Override
195b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    public void run() {
1960e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                        if (mCallback != null) {
1970e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                            mCallback.onPhyUpdate(BluetoothGatt.this, txPhy, rxPhy, status);
1980e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                        }
199b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    }
200b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                });
201db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski            }
202db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski
203db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski            /**
204db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski             * Phy read callback
205db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski             * @hide
206db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski             */
207db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski            @Override
208db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski            public void onPhyRead(String address, int txPhy, int rxPhy, int status) {
209db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski                if (DBG) Log.d(TAG, "onPhyRead() - status=" + status
210db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski                                 + " address=" + address + " txPhy=" + txPhy + " rxPhy=" + rxPhy);
211db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski                if (!address.equals(mDevice.getAddress())) {
212db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski                    return;
213db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski                }
214db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski
2156bdc550e27e2c4e7b32bb91085eaac898d7d1156Ruben Brunk                runOrQueueCallback(new Runnable() {
216b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    @Override
217b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    public void run() {
2180e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                        if (mCallback != null) {
2190e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                            mCallback.onPhyRead(BluetoothGatt.this, txPhy, rxPhy, status);
2200e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                        }
221b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    }
222b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                });
223db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski            }
224db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski
225db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski            /**
2269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Client connection state changed
2279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
2289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
229326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski            @Override
2309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onClientConnectionState(int status, int clientIf,
2319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                boolean connected, String address) {
2329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onClientConnectionState() - status=" + status
2339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                 + " clientIf=" + clientIf + " device=" + address);
234ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
235ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
236ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
237ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                int profileState = connected ? BluetoothProfile.STATE_CONNECTED :
238ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                                               BluetoothProfile.STATE_DISCONNECTED;
239b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski
2406bdc550e27e2c4e7b32bb91085eaac898d7d1156Ruben Brunk                runOrQueueCallback(new Runnable() {
241b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    @Override
242b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    public void run() {
2430e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                        if (mCallback != null) {
2440e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                            mCallback.onConnectionStateChange(BluetoothGatt.this, status,
2450e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                                                              profileState);
2460e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                        }
247b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    }
248b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                });
249ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie
250ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                synchronized(mStateLock) {
251ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    if (connected) {
252ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        mConnState = CONN_STATE_CONNECTED;
253ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    } else {
254ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        mConnState = CONN_STATE_IDLE;
255ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    }
256ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
257cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
258cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                synchronized(mDeviceBusy) {
259cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                    mDeviceBusy = false;
260cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                }
2619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
2629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
2649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Remote search has been completed.
2659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * The internal object structure should now reflect the state
2669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * of the remote device database. Let the application know that
2679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * we are done at this point.
2689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
2699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
270326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski            @Override
271bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski            public void onSearchComplete(String address, List<BluetoothGattService> services,
272bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski                                         int status) {
2739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onSearchComplete() = Device=" + address + " Status=" + status);
274ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
275ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
276ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
277bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski
278bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski                for (BluetoothGattService s : services) {
279bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski                    //services we receive don't have device set properly.
280bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski                    s.setDevice(mDevice);
281bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski                }
282bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski
283bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski                mServices.addAll(services);
284bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski
285bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski                // Fix references to included services, as they doesn't point to right objects.
286bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski                for (BluetoothGattService fixedService : mServices) {
287bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski                    ArrayList<BluetoothGattService> includedServices =
288bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski                        new ArrayList(fixedService.getIncludedServices());
289bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski                    fixedService.getIncludedServices().clear();
290bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski
291bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski                    for(BluetoothGattService brokenRef : includedServices) {
292bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski                        BluetoothGattService includedService = getService(mDevice,
293bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski                            brokenRef.getUuid(), brokenRef.getInstanceId(), brokenRef.getType());
294bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski                        if (includedService != null) {
295bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski                            fixedService.addIncludedService(includedService);
296bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski                        } else {
297bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski                            Log.e(TAG, "Broken GATT database: can't find included service.");
298bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski                        }
299bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski                    }
300bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski                }
301bf0faed3597b92d950febafcf555ad05529559d6Jakub Pawlowski
3026bdc550e27e2c4e7b32bb91085eaac898d7d1156Ruben Brunk                runOrQueueCallback(new Runnable() {
303b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    @Override
304b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    public void run() {
3050e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                        if (mCallback != null) {
3060e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                            mCallback.onServicesDiscovered(BluetoothGatt.this, status);
3070e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                        }
308b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    }
309b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                });
3109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
3119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
3139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Remote characteristic has been read.
3149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Updates the internal value.
3159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
3169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
317326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski            @Override
318c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski            public void onCharacteristicRead(String address, int status, int handle, byte[] value) {
31955d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach                if (VDBG) Log.d(TAG, "onCharacteristicRead() - Device=" + address
320c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski                            + " handle=" + handle + " Status=" + status);
321c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski
322ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
323ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
324ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
325cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
326cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                synchronized(mDeviceBusy) {
327cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                    mDeviceBusy = false;
328cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                }
329cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
3309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if ((status == GATT_INSUFFICIENT_AUTHENTICATION
3319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  || status == GATT_INSUFFICIENT_ENCRYPTION)
3323854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung                  && (mAuthRetryState != AUTH_RETRY_STATE_MITM)) {
3339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    try {
3343854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung                        final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE) ?
3353854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung                                AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM;
3363854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung                        mService.readCharacteristic(mClientIf, address, handle, authReq);
3373854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung                        mAuthRetryState++;
3389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        return;
3399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    } catch (RemoteException e) {
3409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        Log.e(TAG,"",e);
3419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    }
3429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
3439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3443854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung                mAuthRetryState = AUTH_RETRY_STATE_IDLE;
3459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
346c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski                BluetoothGattCharacteristic characteristic = getCharacteristicById(mDevice, handle);
347c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski                if (characteristic == null) {
348c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski                    Log.w(TAG, "onCharacteristicRead() failed to find characteristic!");
349c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski                    return;
350c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski                }
3519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (status == 0) characteristic.setValue(value);
3539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3546bdc550e27e2c4e7b32bb91085eaac898d7d1156Ruben Brunk                runOrQueueCallback(new Runnable() {
355b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    @Override
356b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    public void run() {
3570e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                        if (mCallback != null) {
3580e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                            mCallback.onCharacteristicRead(BluetoothGatt.this, characteristic,
3590e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                                                           status);
3600e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                        }
361b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    }
362b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                });
3639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
3649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
3669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Characteristic has been written to the remote device.
3679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Let the app know how we did...
3689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
3699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
370326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski            @Override
371c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski            public void onCharacteristicWrite(String address, int status, int handle) {
37255d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach                if (VDBG) Log.d(TAG, "onCharacteristicWrite() - Device=" + address
373c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski                            + " handle=" + handle + " Status=" + status);
3749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
375ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
376ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
377ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
378cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
379cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                synchronized(mDeviceBusy) {
380cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                    mDeviceBusy = false;
381cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                }
382cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
383c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski                BluetoothGattCharacteristic characteristic = getCharacteristicById(mDevice, handle);
3849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (characteristic == null) return;
3859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if ((status == GATT_INSUFFICIENT_AUTHENTICATION
3879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  || status == GATT_INSUFFICIENT_ENCRYPTION)
3883854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung                  && (mAuthRetryState != AUTH_RETRY_STATE_MITM)) {
3899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    try {
3903854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung                        final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE) ?
3913854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung                                AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM;
392c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski                        mService.writeCharacteristic(mClientIf, address, handle,
3933854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung                            characteristic.getWriteType(), authReq, characteristic.getValue());
3943854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung                        mAuthRetryState++;
3959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        return;
3969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    } catch (RemoteException e) {
3979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        Log.e(TAG,"",e);
3989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    }
3999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
4009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4013854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung                mAuthRetryState = AUTH_RETRY_STATE_IDLE;
4029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4036bdc550e27e2c4e7b32bb91085eaac898d7d1156Ruben Brunk                runOrQueueCallback(new Runnable() {
404b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    @Override
405b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    public void run() {
4060e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                        if (mCallback != null) {
4070e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                            mCallback.onCharacteristicWrite(BluetoothGatt.this, characteristic,
4080e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                                                            status);
4090e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                        }
410b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    }
411b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                });
4129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
4139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
4159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Remote characteristic has been updated.
4169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Updates the internal value.
4179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
4189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
419326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski            @Override
420c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski            public void onNotify(String address, int handle, byte[] value) {
421c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski                if (VDBG) Log.d(TAG, "onNotify() - Device=" + address + " handle=" + handle);
4229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
423ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
424ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
425ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
4269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
427c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski                BluetoothGattCharacteristic characteristic = getCharacteristicById(mDevice, handle);
4289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (characteristic == null) return;
4299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                characteristic.setValue(value);
4319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4326bdc550e27e2c4e7b32bb91085eaac898d7d1156Ruben Brunk                runOrQueueCallback(new Runnable() {
433b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    @Override
434b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    public void run() {
4350e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                        if (mCallback != null) {
4360e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                            mCallback.onCharacteristicChanged(BluetoothGatt.this, characteristic);
4370e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                        }
438b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    }
439b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                });
4409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
4419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
4439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Descriptor has been read.
4449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
4459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
446326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski            @Override
447c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski            public void onDescriptorRead(String address, int status, int handle, byte[] value) {
448c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski                if (VDBG) Log.d(TAG, "onDescriptorRead() - Device=" + address + " handle=" + handle);
4499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
450ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
451ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
452ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
453cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
454cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                synchronized(mDeviceBusy) {
455cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                    mDeviceBusy = false;
456cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                }
457cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
458c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski                BluetoothGattDescriptor descriptor = getDescriptorById(mDevice, handle);
4599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (descriptor == null) return;
4609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (status == 0) descriptor.setValue(value);
4629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if ((status == GATT_INSUFFICIENT_AUTHENTICATION
4649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  || status == GATT_INSUFFICIENT_ENCRYPTION)
4653854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung                  && (mAuthRetryState != AUTH_RETRY_STATE_MITM)) {
4669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    try {
4673854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung                        final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE) ?
4683854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung                                AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM;
4693854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung                        mService.readDescriptor(mClientIf, address, handle, authReq);
4703854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung                        mAuthRetryState++;
471d65e8f4b6b37b274fcd5b7701a73eaef7c4ba8b4Andre Eisenbach                        return;
4729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    } catch (RemoteException e) {
4739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        Log.e(TAG,"",e);
4749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    }
4759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
4769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4773854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung                mAuthRetryState = AUTH_RETRY_STATE_IDLE;
4789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4796bdc550e27e2c4e7b32bb91085eaac898d7d1156Ruben Brunk                runOrQueueCallback(new Runnable() {
480b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    @Override
481b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    public void run() {
4820e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                        if (mCallback != null) {
4830e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                            mCallback.onDescriptorRead(BluetoothGatt.this, descriptor, status);
4840e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                        }
485b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    }
486b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                });
4879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
4889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
4909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Descriptor write operation complete.
4919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
4929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
493326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski            @Override
494c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski            public void onDescriptorWrite(String address, int status, int handle) {
495c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski                if (VDBG) Log.d(TAG, "onDescriptorWrite() - Device=" + address + " handle=" + handle);
4969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
497ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
498ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
499ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
500cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
501cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                synchronized(mDeviceBusy) {
502cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                    mDeviceBusy = false;
503cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                }
504cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
505c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski                BluetoothGattDescriptor descriptor = getDescriptorById(mDevice, handle);
5069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (descriptor == null) return;
5079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if ((status == GATT_INSUFFICIENT_AUTHENTICATION
5099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  || status == GATT_INSUFFICIENT_ENCRYPTION)
5103854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung                  && (mAuthRetryState != AUTH_RETRY_STATE_MITM)) {
5119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    try {
5123854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung                        final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE) ?
5133854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung                                AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM;
514c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski                        mService.writeDescriptor(mClientIf, address, handle,
5153854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung                            authReq, descriptor.getValue());
5163854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung                        mAuthRetryState++;
517d65e8f4b6b37b274fcd5b7701a73eaef7c4ba8b4Andre Eisenbach                        return;
5189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    } catch (RemoteException e) {
5199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        Log.e(TAG,"",e);
5209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    }
5219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
5229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5233854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung                mAuthRetryState = AUTH_RETRY_STATE_IDLE;
5249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5256bdc550e27e2c4e7b32bb91085eaac898d7d1156Ruben Brunk                runOrQueueCallback(new Runnable() {
526b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    @Override
527b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    public void run() {
5280e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                        if (mCallback != null) {
5290e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                            mCallback.onDescriptorWrite(BluetoothGatt.this, descriptor, status);
5300e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                        }
531b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    }
532b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                });
5339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
5349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
5369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Prepared write transaction completed (or aborted)
5379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
5389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
539326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski            @Override
5409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onExecuteWrite(String address, int status) {
54155d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach                if (VDBG) Log.d(TAG, "onExecuteWrite() - Device=" + address
5429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    + " status=" + status);
543ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
544ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
545ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
546cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
547cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                synchronized(mDeviceBusy) {
548cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                    mDeviceBusy = false;
549cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                }
550cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
5516bdc550e27e2c4e7b32bb91085eaac898d7d1156Ruben Brunk                runOrQueueCallback(new Runnable() {
552b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    @Override
553b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    public void run() {
5540e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                        if (mCallback != null) {
5550e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                           mCallback.onReliableWriteCompleted(BluetoothGatt.this, status);
5560e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                        }
557b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    }
558b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                });
5599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
5609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
5629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Remote device RSSI has been read
5639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
5649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
565326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski            @Override
5669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onReadRemoteRssi(String address, int rssi, int status) {
56755d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach                if (VDBG) Log.d(TAG, "onReadRemoteRssi() - Device=" + address +
5689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            " rssi=" + rssi + " status=" + status);
569ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
570ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
571ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
5726bdc550e27e2c4e7b32bb91085eaac898d7d1156Ruben Brunk                runOrQueueCallback(new Runnable() {
573b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    @Override
574b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    public void run() {
5750e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                        if (mCallback != null) {
5760e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                            mCallback.onReadRemoteRssi(BluetoothGatt.this, rssi, status);
5770e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                        }
578b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    }
579b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                });
5809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
581f305589f22f3fa1d73f2e29009d382c9a4f5c293Wei Wang
582f305589f22f3fa1d73f2e29009d382c9a4f5c293Wei Wang            /**
583580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach             * Callback invoked when the MTU for a given connection changes
584580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach             * @hide
585580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach             */
586326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski            @Override
587580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach            public void onConfigureMTU(String address, int mtu, int status) {
588580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                if (DBG) Log.d(TAG, "onConfigureMTU() - Device=" + address +
589580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                            " mtu=" + mtu + " status=" + status);
590580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                if (!address.equals(mDevice.getAddress())) {
591580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                    return;
592580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                }
593b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski
5946bdc550e27e2c4e7b32bb91085eaac898d7d1156Ruben Brunk                runOrQueueCallback(new Runnable() {
595b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    @Override
596b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    public void run() {
5970e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                        if (mCallback != null) {
5980e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                            mCallback.onMtuChanged(BluetoothGatt.this, mtu, status);
5990e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                        }
600b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    }
601b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                });
602f305589f22f3fa1d73f2e29009d382c9a4f5c293Wei Wang            }
603326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski
604326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski            /**
605326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski             * Callback invoked when the given connection is updated
606326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski             * @hide
607326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski             */
608326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski            @Override
609326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski            public void onConnectionUpdated(String address, int interval, int latency,
610326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski                                            int timeout, int status) {
611326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski                if (DBG) Log.d(TAG, "onConnectionUpdated() - Device=" + address +
612326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski                            " interval=" + interval + " latency=" + latency +
613326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski                            " timeout=" + timeout + " status=" + status);
614326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski                if (!address.equals(mDevice.getAddress())) {
615326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski                    return;
616326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski                }
617b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski
6186bdc550e27e2c4e7b32bb91085eaac898d7d1156Ruben Brunk                runOrQueueCallback(new Runnable() {
619b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    @Override
620b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    public void run() {
6210e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                        if (mCallback != null) {
6220e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                            mCallback.onConnectionUpdated(BluetoothGatt.this, interval, latency,
6230e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                                                          timeout, status);
6240e0e75793decad48ba210c46718ab97545397096Jakub Pawlowski                        }
625b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                    }
626b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                });
627326f7b31b9ab7bf82e3c05f9b606d10ece306dc0Jakub Pawlowski            }
6289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        };
6299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
630adc26ec1b4060358d918d1bdf491f5192b35c2d3Jeremy Klein    /*package*/ BluetoothGatt(IBluetoothGatt iGatt, BluetoothDevice device,
631db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski                                int transport, int phy) {
632ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        mService = iGatt;
633ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        mDevice = device;
634b88fa824ab6337684de9aa8437c4952df4f1a75eGanesh Ganapathi Batta        mTransport = transport;
635db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski        mPhy = phy;
6369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        mServices = new ArrayList<BluetoothGattService>();
6379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
638ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        mConnState = CONN_STATE_IDLE;
6393854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung        mAuthRetryState = AUTH_RETRY_STATE_IDLE;
6409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
6419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
64333ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * Close this Bluetooth GATT client.
644b30f91e38c19f6728d836293446d4b9c76705e7fMatthew Xie     *
645b30f91e38c19f6728d836293446d4b9c76705e7fMatthew Xie     * Application should call this method as early as possible after it is done with
646b30f91e38c19f6728d836293446d4b9c76705e7fMatthew Xie     * this GATT client.
6479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
64833ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    public void close() {
6499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "close()");
6509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        unregisterApp();
65233ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie        mConnState = CONN_STATE_CLOSED;
6533854e2267487ecd129bdd0711c6d9dfbf8f7ed0dJacky Cheung        mAuthRetryState = AUTH_RETRY_STATE_IDLE;
6549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
6559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
6579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Returns a service by UUID, instance and type.
6589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @hide
6599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
6609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /*package*/ BluetoothGattService getService(BluetoothDevice device, UUID uuid,
6619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                int instanceId, int type) {
6629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        for(BluetoothGattService svc : mServices) {
6639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            if (svc.getDevice().equals(device) &&
6649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                svc.getType() == type &&
6659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                svc.getInstanceId() == instanceId &&
6669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                svc.getUuid().equals(uuid)) {
6679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                return svc;
6689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
6699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
6709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return null;
6719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
6729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
675c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski     * Returns a characteristic with id equal to instanceId.
676c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski     * @hide
677c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski     */
678c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski    /*package*/ BluetoothGattCharacteristic getCharacteristicById(BluetoothDevice device, int instanceId) {
679c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski        for(BluetoothGattService svc : mServices) {
680c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski            for(BluetoothGattCharacteristic charac : svc.getCharacteristics()) {
681c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski                if (charac.getInstanceId() == instanceId)
682c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski                    return charac;
683c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski            }
684c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski        }
685c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski        return null;
686c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski    }
687c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski
688c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski    /**
689c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski     * Returns a descriptor with id equal to instanceId.
690c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski     * @hide
691c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski     */
692c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski    /*package*/ BluetoothGattDescriptor getDescriptorById(BluetoothDevice device, int instanceId) {
693c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski        for(BluetoothGattService svc : mServices) {
694c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski            for(BluetoothGattCharacteristic charac : svc.getCharacteristics()) {
695c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski                for(BluetoothGattDescriptor desc : charac.getDescriptors()) {
696c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski                    if (desc.getInstanceId() == instanceId)
697c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski                        return desc;
698c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski                }
699c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski            }
700c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski        }
701c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski        return null;
702c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski    }
703c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski
704c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski    /**
7056bdc550e27e2c4e7b32bb91085eaac898d7d1156Ruben Brunk     * Queue the runnable on a {@link Handler} provided by the user, or execute the runnable
7066bdc550e27e2c4e7b32bb91085eaac898d7d1156Ruben Brunk     * immediately if no Handler was provided.
7076bdc550e27e2c4e7b32bb91085eaac898d7d1156Ruben Brunk     */
7086bdc550e27e2c4e7b32bb91085eaac898d7d1156Ruben Brunk    private void runOrQueueCallback(final Runnable cb) {
7096bdc550e27e2c4e7b32bb91085eaac898d7d1156Ruben Brunk        if (mHandler == null) {
7106bdc550e27e2c4e7b32bb91085eaac898d7d1156Ruben Brunk          try {
7116bdc550e27e2c4e7b32bb91085eaac898d7d1156Ruben Brunk            cb.run();
7126bdc550e27e2c4e7b32bb91085eaac898d7d1156Ruben Brunk          } catch (Exception ex) {
7136bdc550e27e2c4e7b32bb91085eaac898d7d1156Ruben Brunk            Log.w(TAG, "Unhandled exception in callback", ex);
7146bdc550e27e2c4e7b32bb91085eaac898d7d1156Ruben Brunk          }
7156bdc550e27e2c4e7b32bb91085eaac898d7d1156Ruben Brunk        } else {
7166bdc550e27e2c4e7b32bb91085eaac898d7d1156Ruben Brunk          mHandler.post(cb);
7176bdc550e27e2c4e7b32bb91085eaac898d7d1156Ruben Brunk        }
7186bdc550e27e2c4e7b32bb91085eaac898d7d1156Ruben Brunk    }
7196bdc550e27e2c4e7b32bb91085eaac898d7d1156Ruben Brunk
7206bdc550e27e2c4e7b32bb91085eaac898d7d1156Ruben Brunk    /**
721ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Register an application callback to start using GATT.
7229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
723d64bb883d822e1db445e09e77150ffd281e83cbeJakub Pawlowski     * <p>This is an asynchronous call. The callback {@link BluetoothGattCallback#onAppRegistered}
724ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * is used to notify success or failure if the function returns true.
7259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
7269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
7279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
728ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @param callback GATT callback handler that will receive asynchronous callbacks.
729ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @return If true, the callback will be called to notify success or failure,
730ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     *         false on immediate error
7319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
732b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski    private boolean registerApp(BluetoothGattCallback callback, Handler handler) {
7339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "registerApp()");
7349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null) return false;
7359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
7369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        mCallback = callback;
737b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski        mHandler = handler;
7389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        UUID uuid = UUID.randomUUID();
7399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "registerApp() - UUID=" + uuid);
7409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
7419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
742d64bb883d822e1db445e09e77150ffd281e83cbeJakub Pawlowski            mService.registerClient(new ParcelUuid(uuid), mBluetoothGattCallback);
7439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
7449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
7459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
7469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
7479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
7489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
7499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
7509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
7519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
7529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Unregister the current application and callbacks.
7539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
754ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private void unregisterApp() {
7559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "unregisterApp() - mClientIf=" + mClientIf);
7569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return;
7579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
7589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
7599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mCallback = null;
7609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.unregisterClient(mClientIf);
7619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mClientIf = 0;
7629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
7639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
7649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
7659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
7669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
7679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
768ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Initiate a connection to a Bluetooth GATT capable device.
7699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
7709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>The connection may not be established right away, but will be
7719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * completed when the remote device is available. A
772d64bb883d822e1db445e09e77150ffd281e83cbeJakub Pawlowski     * {@link BluetoothGattCallback#onConnectionStateChange} callback will be
7739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * invoked when the connection state changes as a result of this function.
7749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
7756ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * <p>The autoConnect parameter determines whether to actively connect to
7769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * the remote device, or rather passively scan and finalize the connection
7779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * when the remote device is in range/available. Generally, the first ever
7789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * connection to a device should be direct (autoConnect set to false) and
7799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * subsequent connections to known devices should be invoked with the
780ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * autoConnect parameter set to true.
7819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
7829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
7839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
7849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param device Remote device to connect to
7859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param autoConnect Whether to directly connect to the remote device (false)
7869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *                    or to automatically connect as soon as the remote
7879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *                    device becomes available (true).
7889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the connection attempt was initiated successfully
7899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
790b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski    /*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallback callback,
791b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski                                Handler handler) {
792ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "connect() - device: " + mDevice.getAddress() + ", auto: " + autoConnect);
793ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        synchronized(mStateLock) {
794ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            if (mConnState != CONN_STATE_IDLE) {
795ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                throw new IllegalStateException("Not idle");
796ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            }
797ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mConnState = CONN_STATE_CONNECTING;
798ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        }
799d35167adcaa40cb54df8e392379dfdfe98bcdba2Sungki Kim
800d35167adcaa40cb54df8e392379dfdfe98bcdba2Sungki Kim        mAutoConnect = autoConnect;
801d35167adcaa40cb54df8e392379dfdfe98bcdba2Sungki Kim
802b0f647492f6d262d13825b14bbada140effe8394Jakub Pawlowski        if (!registerApp(callback, handler)) {
803ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            synchronized(mStateLock) {
804ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                mConnState = CONN_STATE_IDLE;
805ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            }
806ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            Log.e(TAG, "Failed to register callback");
8079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
8089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
8099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
810d35167adcaa40cb54df8e392379dfdfe98bcdba2Sungki Kim        // The connection will continue in the onClientRegistered callback
8119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
8129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
8139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
8159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Disconnects an established connection, or cancels a connection attempt
8169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * currently in progress.
8179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
8199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
820ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public void disconnect() {
821ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "cancelOpen() - device: " + mDevice.getAddress());
8229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return;
8239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
825ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.clientDisconnect(mClientIf, mDevice.getAddress());
8269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
8279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
8289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
82933ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    }
83033ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie
83133ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    /**
83233ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * Connect back to remote device.
83333ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     *
83433ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * <p>This method is used to re-connect to a remote device after the
83533ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * connection has been dropped. If the device is not in range, the
83633ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * re-connection will be triggered once the device is back in range.
83733ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     *
83833ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * @return true, if the connection attempt was initiated successfully
83933ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     */
84033ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    public boolean connect() {
84133ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie        try {
84233ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie            mService.clientConnect(mClientIf, mDevice.getAddress(),
843db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski                                   false, mTransport, mPhy); // autoConnect is inverse of "isDirect"
84433ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie            return true;
84533ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie        } catch (RemoteException e) {
84633ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie            Log.e(TAG,"",e);
84733ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie            return false;
84833ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie        }
84933ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    }
85033ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie
85133ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    /**
852db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski     * Set the preferred connection PHY for this app. Please note that this is just a
853f752ace75a931f7a645a8e65462b91a7185ed1d4Jakub Pawlowski     * recommendation, whether the PHY change will happen depends on other applications peferences,
854db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski     * local and remote controller capabilities. Controller can override these settings.
855db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski     * <p>
856d64bb883d822e1db445e09e77150ffd281e83cbeJakub Pawlowski     * {@link BluetoothGattCallback#onPhyUpdate} will be triggered as a result of this call, even
857db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski     * if no PHY change happens. It is also triggered when remote device updates the PHY.
858db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski     *
859db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski     * @param txPhy preferred transmitter PHY. Bitwise OR of any of
860a51513747aee764628871d2919f434dcbe38b67cJakub Pawlowski     *             {@link BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK},
861a51513747aee764628871d2919f434dcbe38b67cJakub Pawlowski     *             and {@link BluetoothDevice#PHY_LE_CODED_MASK}.
862db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski     * @param rxPhy preferred receiver PHY. Bitwise OR of any of
863a51513747aee764628871d2919f434dcbe38b67cJakub Pawlowski     *             {@link BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK},
864a51513747aee764628871d2919f434dcbe38b67cJakub Pawlowski     *             and {@link BluetoothDevice#PHY_LE_CODED_MASK}.
865db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski     * @param phyOptions preferred coding to use when transmitting on the LE Coded PHY. Can be one
866db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski     *             of {@link BluetoothDevice#PHY_OPTION_NO_PREFERRED},
867db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski     *             {@link BluetoothDevice#PHY_OPTION_S2} or {@link BluetoothDevice#PHY_OPTION_S8}
868db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski     */
869db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski    public void setPreferredPhy(int txPhy, int rxPhy, int phyOptions) {
870db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski        try {
871db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski            mService.clientSetPreferredPhy(mClientIf, mDevice.getAddress(), txPhy, rxPhy,
872db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski                                           phyOptions);
873db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski        } catch (RemoteException e) {
874db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski            Log.e(TAG,"",e);
875db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski        }
876db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski    }
877db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski
878db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski    /**
879db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski     * Read the current transmitter PHY and receiver PHY of the connection. The values are returned
880d64bb883d822e1db445e09e77150ffd281e83cbeJakub Pawlowski     * in {@link BluetoothGattCallback#onPhyRead}
881db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski     */
882db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski    public void readPhy() {
883db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski        try {
884db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski            mService.clientReadPhy(mClientIf, mDevice.getAddress());
885db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski        } catch (RemoteException e) {
886db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski            Log.e(TAG,"",e);
887db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski        }
888db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski    }
889db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski
890db5a87d50db9d4b3d642603f6c329b83ee5851f6Jakub Pawlowski    /**
89133ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * Return the remote bluetooth device this GATT client targets to
89233ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     *
89333ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * @return remote bluetooth device
89433ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     */
89533ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    public BluetoothDevice getDevice() {
89633ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie        return mDevice;
8979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
8989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
9009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Discovers services offered by a remote device as well as their
9019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * characteristics and descriptors.
9029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>This is an asynchronous operation. Once service discovery is completed,
904d64bb883d822e1db445e09e77150ffd281e83cbeJakub Pawlowski     * the {@link BluetoothGattCallback#onServicesDiscovered} callback is
9059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * triggered. If the discovery was successful, the remote services can be
9069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * retrieved using the {@link #getServices} function.
9079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
9099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the remote service discovery has been started
9119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
912ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public boolean discoverServices() {
913ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "discoverServices() - device: " + mDevice.getAddress());
9149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
9159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        mServices.clear();
9179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
919ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.discoverServices(mClientIf, mDevice.getAddress());
9209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
9219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
9229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
9239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
9249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
9269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
9279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
92909ad0b27bbc7d2ca2acacd9ef3b1e855eaef9ea9Jakub Pawlowski     * Discovers a service by UUID. This is exposed only for passing PTS tests.
93009ad0b27bbc7d2ca2acacd9ef3b1e855eaef9ea9Jakub Pawlowski     * It should never be used by real applications. The service is not searched
93109ad0b27bbc7d2ca2acacd9ef3b1e855eaef9ea9Jakub Pawlowski     * for characteristics and descriptors, or returned in any callback.
93209ad0b27bbc7d2ca2acacd9ef3b1e855eaef9ea9Jakub Pawlowski     *
93309ad0b27bbc7d2ca2acacd9ef3b1e855eaef9ea9Jakub Pawlowski     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
93409ad0b27bbc7d2ca2acacd9ef3b1e855eaef9ea9Jakub Pawlowski     *
93509ad0b27bbc7d2ca2acacd9ef3b1e855eaef9ea9Jakub Pawlowski     * @return true, if the remote service discovery has been started
93609ad0b27bbc7d2ca2acacd9ef3b1e855eaef9ea9Jakub Pawlowski     * @hide
93709ad0b27bbc7d2ca2acacd9ef3b1e855eaef9ea9Jakub Pawlowski     */
93809ad0b27bbc7d2ca2acacd9ef3b1e855eaef9ea9Jakub Pawlowski    public boolean discoverServiceByUuid(UUID uuid) {
93909ad0b27bbc7d2ca2acacd9ef3b1e855eaef9ea9Jakub Pawlowski        if (DBG) Log.d(TAG, "discoverServiceByUuid() - device: " + mDevice.getAddress());
94009ad0b27bbc7d2ca2acacd9ef3b1e855eaef9ea9Jakub Pawlowski        if (mService == null || mClientIf == 0) return false;
94109ad0b27bbc7d2ca2acacd9ef3b1e855eaef9ea9Jakub Pawlowski
94209ad0b27bbc7d2ca2acacd9ef3b1e855eaef9ea9Jakub Pawlowski        mServices.clear();
94309ad0b27bbc7d2ca2acacd9ef3b1e855eaef9ea9Jakub Pawlowski
94409ad0b27bbc7d2ca2acacd9ef3b1e855eaef9ea9Jakub Pawlowski        try {
94509ad0b27bbc7d2ca2acacd9ef3b1e855eaef9ea9Jakub Pawlowski            mService.discoverServiceByUuid(mClientIf, mDevice.getAddress(), new ParcelUuid(uuid));
94609ad0b27bbc7d2ca2acacd9ef3b1e855eaef9ea9Jakub Pawlowski        } catch (RemoteException e) {
94709ad0b27bbc7d2ca2acacd9ef3b1e855eaef9ea9Jakub Pawlowski            Log.e(TAG, "", e);
94809ad0b27bbc7d2ca2acacd9ef3b1e855eaef9ea9Jakub Pawlowski            return false;
94909ad0b27bbc7d2ca2acacd9ef3b1e855eaef9ea9Jakub Pawlowski        }
95009ad0b27bbc7d2ca2acacd9ef3b1e855eaef9ea9Jakub Pawlowski        return true;
95109ad0b27bbc7d2ca2acacd9ef3b1e855eaef9ea9Jakub Pawlowski    }
95209ad0b27bbc7d2ca2acacd9ef3b1e855eaef9ea9Jakub Pawlowski
95309ad0b27bbc7d2ca2acacd9ef3b1e855eaef9ea9Jakub Pawlowski    /**
9549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Returns a list of GATT services offered by the remote device.
9559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>This function requires that service discovery has been completed
9579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * for the given device.
9589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
9609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return List of services on the remote device. Returns an empty list
9629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *         if service discovery has not yet been performed.
9639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
964ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public List<BluetoothGattService> getServices() {
9659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        List<BluetoothGattService> result =
9669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ArrayList<BluetoothGattService>();
9679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        for (BluetoothGattService service : mServices) {
969ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            if (service.getDevice().equals(mDevice)) {
9709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                result.add(service);
9719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
9729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
9739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return result;
9759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
9769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
9789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Returns a {@link BluetoothGattService}, if the requested UUID is
9799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * supported by the remote device.
9809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>This function requires that service discovery has been completed
9829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * for the given device.
9839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>If multiple instances of the same service (as identified by UUID)
9859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * exist, the first instance of the service is returned.
9869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
9889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param uuid UUID of the requested service
9909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return BluetoothGattService if supported, or null if the requested
9919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *         service is not offered by the remote device.
9929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
993ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public BluetoothGattService getService(UUID uuid) {
9949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        for (BluetoothGattService service : mServices) {
995ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            if (service.getDevice().equals(mDevice) &&
9969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                service.getUuid().equals(uuid)) {
9979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                return service;
9989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
9999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
10009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return null;
10029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
10039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
10059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Reads the requested characteristic from the associated remote device.
10069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>This is an asynchronous operation. The result of the read operation
1008d64bb883d822e1db445e09e77150ffd281e83cbeJakub Pawlowski     * is reported by the {@link BluetoothGattCallback#onCharacteristicRead}
10099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * callback.
10109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
10129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param characteristic Characteristic to read from the remote device
10149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the read operation was initiated successfully
10159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
10169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public boolean readCharacteristic(BluetoothGattCharacteristic characteristic) {
10179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if ((characteristic.getProperties() &
10189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic.PROPERTY_READ) == 0) return false;
10199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
102055d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach        if (VDBG) Log.d(TAG, "readCharacteristic() - uuid: " + characteristic.getUuid());
10219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
10229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattService service = characteristic.getService();
10249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (service == null) return false;
10259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothDevice device = service.getDevice();
10279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (device == null) return false;
10289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1029cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        synchronized(mDeviceBusy) {
1030cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            if (mDeviceBusy) return false;
1031cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = true;
1032cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        }
1033cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
10349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
10359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.readCharacteristic(mClientIf, device.getAddress(),
1036c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski                characteristic.getInstanceId(), AUTHENTICATION_NONE);
10379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
10389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
1039cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = false;
10409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
10419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
10429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
10449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
10459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1047ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski     * Reads the characteristic using its UUID from the associated remote device.
1048ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski     *
1049ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski     * <p>This is an asynchronous operation. The result of the read operation
1050ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski     * is reported by the {@link BluetoothGattCallback#onCharacteristicRead}
1051ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski     * callback.
1052ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski     *
1053ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
1054ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski     *
1055ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski     * @param uuid UUID of characteristic to read from the remote device
1056ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski     * @return true, if the read operation was initiated successfully
1057ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski     * @hide
1058ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski     */
1059ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski    public boolean readUsingCharacteristicUuid(UUID uuid, int startHandle, int endHandle) {
1060ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski        if (VDBG) Log.d(TAG, "readUsingCharacteristicUuid() - uuid: " + uuid);
1061ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski        if (mService == null || mClientIf == 0) return false;
1062ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski
1063ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski        synchronized(mDeviceBusy) {
1064ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski            if (mDeviceBusy) return false;
1065ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski            mDeviceBusy = true;
1066ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski        }
1067ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski
1068ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski        try {
1069ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski            mService.readUsingCharacteristicUuid(mClientIf, mDevice.getAddress(),
1070ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski                new ParcelUuid(uuid), startHandle, endHandle, AUTHENTICATION_NONE);
1071ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski        } catch (RemoteException e) {
1072ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski            Log.e(TAG,"",e);
1073ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski            mDeviceBusy = false;
1074ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski            return false;
1075ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski        }
1076ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski
1077ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski        return true;
1078ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski    }
1079ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski
1080ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski
1081ce21cb903ceaf8a5d916a89c4d07689887007be2Jakub Pawlowski    /**
1082ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Writes a given characteristic and its values to the associated remote device.
10839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Once the write operation has been completed, the
1085d64bb883d822e1db445e09e77150ffd281e83cbeJakub Pawlowski     * {@link BluetoothGattCallback#onCharacteristicWrite} callback is invoked,
10869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * reporting the result of the operation.
10879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
10899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param characteristic Characteristic to write on the remote device
10919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the write operation was initiated successfully
10929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
10939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public boolean writeCharacteristic(BluetoothGattCharacteristic characteristic) {
10949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE) == 0
10959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            && (characteristic.getProperties() &
10969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) == 0) return false;
10979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
109855d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach        if (VDBG) Log.d(TAG, "writeCharacteristic() - uuid: " + characteristic.getUuid());
1099ff5e5db319785d23d672af95ac2dff3f37827cfdPrerepa Viswanadham        if (mService == null || mClientIf == 0 || characteristic.getValue() == null) return false;
11009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattService service = characteristic.getService();
11029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (service == null) return false;
11039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothDevice device = service.getDevice();
11059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (device == null) return false;
11069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1107cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        synchronized(mDeviceBusy) {
1108cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            if (mDeviceBusy) return false;
1109cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = true;
1110cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        }
1111cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
11129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
11139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.writeCharacteristic(mClientIf, device.getAddress(),
1114c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski                characteristic.getInstanceId(), characteristic.getWriteType(),
1115c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski                AUTHENTICATION_NONE, characteristic.getValue());
11169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
11179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
1118cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = false;
11199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
11209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
11219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
11239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
11249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
11269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Reads the value for a given descriptor from the associated remote device.
11279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Once the read operation has been completed, the
1129d64bb883d822e1db445e09e77150ffd281e83cbeJakub Pawlowski     * {@link BluetoothGattCallback#onDescriptorRead} callback is
11309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * triggered, signaling the result of the operation.
11319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
11339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param descriptor Descriptor value to read from the remote device
11359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the read operation was initiated successfully
11369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
11379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public boolean readDescriptor(BluetoothGattDescriptor descriptor) {
113855d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach        if (VDBG) Log.d(TAG, "readDescriptor() - uuid: " + descriptor.getUuid());
11399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
11409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic();
11429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (characteristic == null) return false;
11439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattService service = characteristic.getService();
11459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (service == null) return false;
11469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothDevice device = service.getDevice();
11489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (device == null) return false;
11499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1150cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        synchronized(mDeviceBusy) {
1151cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            if (mDeviceBusy) return false;
1152cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = true;
1153cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        }
1154cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
11559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
1156c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski            mService.readDescriptor(mClientIf, device.getAddress(),
1157c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski                descriptor.getInstanceId(), AUTHENTICATION_NONE);
11589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
11599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
1160cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = false;
11619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
11629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
11639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
11659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
11669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
11689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Write the value of a given descriptor to the associated remote device.
11699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
1170d64bb883d822e1db445e09e77150ffd281e83cbeJakub Pawlowski     * <p>A {@link BluetoothGattCallback#onDescriptorWrite} callback is
11719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * triggered to report the result of the write operation.
11729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
11749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param descriptor Descriptor to write to the associated remote device
11769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the write operation was initiated successfully
11779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
11789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public boolean writeDescriptor(BluetoothGattDescriptor descriptor) {
117955d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach        if (VDBG) Log.d(TAG, "writeDescriptor() - uuid: " + descriptor.getUuid());
1180ff5e5db319785d23d672af95ac2dff3f37827cfdPrerepa Viswanadham        if (mService == null || mClientIf == 0 || descriptor.getValue() == null) return false;
11819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic();
11839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (characteristic == null) return false;
11849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattService service = characteristic.getService();
11869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (service == null) return false;
11879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothDevice device = service.getDevice();
11899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (device == null) return false;
11909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1191cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        synchronized(mDeviceBusy) {
1192cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            if (mDeviceBusy) return false;
1193cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = true;
1194cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        }
1195cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
11969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
1197c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski            mService.writeDescriptor(mClientIf, device.getAddress(), descriptor.getInstanceId(),
11988e970d6ab4850ca23163bad5773cf5cc2e7ff896Jakub Pawlowski                AUTHENTICATION_NONE, descriptor.getValue());
11999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
12009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
1201cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = false;
12029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
12039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
12049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
12069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
12079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
12099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Initiates a reliable write transaction for a given remote device.
12109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
12119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Once a reliable write transaction has been initiated, all calls
12129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * to {@link #writeCharacteristic} are sent to the remote device for
12139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * verification and queued up for atomic execution. The application will
1214d64bb883d822e1db445e09e77150ffd281e83cbeJakub Pawlowski     * receive an {@link BluetoothGattCallback#onCharacteristicWrite} callback
12159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * in response to every {@link #writeCharacteristic} call and is responsible
12169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * for verifying if the value has been transmitted accurately.
12179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
12189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>After all characteristics have been queued up and verified,
12199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * {@link #executeReliableWrite} will execute all writes. If a characteristic
12209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * was not written correctly, calling {@link #abortReliableWrite} will
12219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * cancel the current transaction without commiting any values on the
12229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * remote device.
12239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
12249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
12259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
12269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the reliable write transaction has been initiated
12279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1228ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public boolean beginReliableWrite() {
122955d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach        if (VDBG) Log.d(TAG, "beginReliableWrite() - device: " + mDevice.getAddress());
12309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
12319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
1233ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.beginReliableWrite(mClientIf, mDevice.getAddress());
12349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
12359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
12369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
12379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
12389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
12409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
12419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
12439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Executes a reliable write transaction for a given remote device.
12449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
12459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>This function will commit all queued up characteristic write
12469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * operations for a given remote device.
12479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
1248d64bb883d822e1db445e09e77150ffd281e83cbeJakub Pawlowski     * <p>A {@link BluetoothGattCallback#onReliableWriteCompleted} callback is
12499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * invoked to indicate whether the transaction has been executed correctly.
12509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
12519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
12529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
12539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the request to execute the transaction has been sent
12549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1255ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public boolean executeReliableWrite() {
125655d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach        if (VDBG) Log.d(TAG, "executeReliableWrite() - device: " + mDevice.getAddress());
12579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
12589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1259cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        synchronized(mDeviceBusy) {
1260cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            if (mDeviceBusy) return false;
1261cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = true;
1262cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        }
1263cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
12649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
1265ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.endReliableWrite(mClientIf, mDevice.getAddress(), true);
12669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
12679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
1268cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = false;
12699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
12709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
12719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
12739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
12749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
12769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Cancels a reliable write transaction for a given device.
12779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
12789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Calling this function will discard all queued characteristic write
12799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * operations for a given remote device.
12809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
12819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
12829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
128348f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du    public void abortReliableWrite() {
128455d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach        if (VDBG) Log.d(TAG, "abortReliableWrite() - device: " + mDevice.getAddress());
12859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return;
12869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
1288ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.endReliableWrite(mClientIf, mDevice.getAddress(), false);
12899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
12909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
12919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
12929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
12939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1295b7b7d7a05c164a56dd4155de4e84fc25ba706728John Du     * @deprecated Use {@link #abortReliableWrite()}
129648f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du     */
1297514c5ef8d5774d8820ed1bf90fe53af1606cf106Aurimas Liutikas    @Deprecated
129848f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du    public void abortReliableWrite(BluetoothDevice mDevice) {
129948f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du        abortReliableWrite();
130048f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du    }
130148f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du
130248f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du    /**
13039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Enable or disable notifications/indications for a given characteristic.
13049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
13059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Once notifications are enabled for a characteristic, a
1306d64bb883d822e1db445e09e77150ffd281e83cbeJakub Pawlowski     * {@link BluetoothGattCallback#onCharacteristicChanged} callback will be
13079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * triggered if the remote device indicates that the given characteristic
13089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * has changed.
13099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
13109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
13119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
13129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param characteristic The characteristic for which to enable notifications
13139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param enable Set to true to enable notifications/indications
13149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the requested notification status was set successfully
13159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
13169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public boolean setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
13179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                              boolean enable) {
13189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "setCharacteristicNotification() - uuid: " + characteristic.getUuid()
13199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                         + " enable: " + enable);
13209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
13219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
13229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattService service = characteristic.getService();
13239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (service == null) return false;
13249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
13259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothDevice device = service.getDevice();
13269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (device == null) return false;
13279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
13289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
13299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.registerForNotification(mClientIf, device.getAddress(),
1330c9d13c3e3eab9c6568abaef55ab86fb5d2c46ad1Jakub Pawlowski                characteristic.getInstanceId(), enable);
13319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
13329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
13339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
13349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
13359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
13369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
13379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
13389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
13399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
13409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Clears the internal cache and forces a refresh of the services from the
13419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * remote device.
13429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @hide
13439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1344ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public boolean refresh() {
1345ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "refresh() - device: " + mDevice.getAddress());
13469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
13479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
13489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
1349ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.refreshDevice(mClientIf, mDevice.getAddress());
13509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
13519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
13529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
13539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
13549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
13559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
13569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
13579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
13589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
13599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Read the RSSI for a connected remote device.
13609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
1361d64bb883d822e1db445e09e77150ffd281e83cbeJakub Pawlowski     * <p>The {@link BluetoothGattCallback#onReadRemoteRssi} callback will be
13629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * invoked when the RSSI value has been read.
13639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
13649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
13659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
13669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the RSSI value has been requested successfully
13679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1368ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public boolean readRemoteRssi() {
1369ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "readRssi() - device: " + mDevice.getAddress());
13709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
13719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
13729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
1373ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.readRemoteRssi(mClientIf, mDevice.getAddress());
13749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
13759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
13769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
13779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
13789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
13799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
13809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
13819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
13829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
13834072da041da2911dd56635b530b276671ce0199dAndre Eisenbach     * Request an MTU size used for a given connection.
1384580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     *
1385580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     * <p>When performing a write request operation (write without response),
1386580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     * the data sent is truncated to the MTU size. This function may be used
13874072da041da2911dd56635b530b276671ce0199dAndre Eisenbach     * to request a larger MTU size to be able to send more data at once.
1388580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     *
1389d64bb883d822e1db445e09e77150ffd281e83cbeJakub Pawlowski     * <p>A {@link BluetoothGattCallback#onMtuChanged} callback will indicate
1390580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     * whether this operation was successful.
1391580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     *
1392580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
1393580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     *
1394580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     * @return true, if the new MTU value has been requested successfully
1395580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     */
13964072da041da2911dd56635b530b276671ce0199dAndre Eisenbach    public boolean requestMtu(int mtu) {
1397580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach        if (DBG) Log.d(TAG, "configureMTU() - device: " + mDevice.getAddress()
1398580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                            + " mtu: " + mtu);
1399580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach        if (mService == null || mClientIf == 0) return false;
1400580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach
1401580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach        try {
1402580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach            mService.configureMTU(mClientIf, mDevice.getAddress(), mtu);
1403580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach        } catch (RemoteException e) {
1404580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach            Log.e(TAG,"",e);
1405580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach            return false;
1406580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach        }
1407580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach
1408580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach        return true;
1409580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach    }
1410580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach
1411580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach    /**
14126ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * Request a connection parameter update.
14136ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     *
14146ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * <p>This function will send a connection parameter update request to the
14156ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * remote device.
14166ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     *
14176ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * @param connectionPriority Request a specific connection priority. Must be one of
14184072da041da2911dd56635b530b276671ce0199dAndre Eisenbach     *          {@link BluetoothGatt#CONNECTION_PRIORITY_BALANCED},
14194072da041da2911dd56635b530b276671ce0199dAndre Eisenbach     *          {@link BluetoothGatt#CONNECTION_PRIORITY_HIGH}
14204072da041da2911dd56635b530b276671ce0199dAndre Eisenbach     *          or {@link BluetoothGatt#CONNECTION_PRIORITY_LOW_POWER}.
14216ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * @throws IllegalArgumentException If the parameters are outside of their
14226ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     *                                  specified range.
14236ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     */
14244072da041da2911dd56635b530b276671ce0199dAndre Eisenbach    public boolean requestConnectionPriority(int connectionPriority) {
14254072da041da2911dd56635b530b276671ce0199dAndre Eisenbach        if (connectionPriority < CONNECTION_PRIORITY_BALANCED ||
14264072da041da2911dd56635b530b276671ce0199dAndre Eisenbach            connectionPriority > CONNECTION_PRIORITY_LOW_POWER) {
14276ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach            throw new IllegalArgumentException("connectionPriority not within valid range");
14286ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach        }
14296ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach
14304072da041da2911dd56635b530b276671ce0199dAndre Eisenbach        if (DBG) Log.d(TAG, "requestConnectionPriority() - params: " + connectionPriority);
14316ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach        if (mService == null || mClientIf == 0) return false;
14326ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach
14336ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach        try {
14346ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach            mService.connectionParameterUpdate(mClientIf, mDevice.getAddress(), connectionPriority);
14356ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach        } catch (RemoteException e) {
14366ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach            Log.e(TAG,"",e);
14376ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach            return false;
14386ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach        }
14396ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach
14406ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach        return true;
14416ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach    }
14426ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach
14436ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach    /**
1444ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
1445ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * with {@link BluetoothProfile#GATT} as argument
14469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
1447ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @throws UnsupportedOperationException
14489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
14499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    @Override
14509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public int getConnectionState(BluetoothDevice device) {
1451ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        throw new UnsupportedOperationException("Use BluetoothManager#getConnectionState instead.");
14529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
14539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
14549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1455ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
1456ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * with {@link BluetoothProfile#GATT} as argument
14579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
1458ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @throws UnsupportedOperationException
14599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
14609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    @Override
14619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public List<BluetoothDevice> getConnectedDevices() {
1462ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        throw new UnsupportedOperationException
1463ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            ("Use BluetoothManager#getConnectedDevices instead.");
14649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
14659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
14669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1467ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Not supported - please use
1468ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * {@link BluetoothManager#getDevicesMatchingConnectionStates(int, int[])}
1469ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * with {@link BluetoothProfile#GATT} as first argument
14709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
1471ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @throws UnsupportedOperationException
14729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
14739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    @Override
14749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
1475ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        throw new UnsupportedOperationException
1476ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            ("Use BluetoothManager#getDevicesMatchingConnectionStates instead.");
14779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
14789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta}
1479