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