BluetoothGatt.java revision 55d19e495e2b3cd744724f2d12c399217e3c565c
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
199fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wangimport android.bluetooth.le.ScanResult;
209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.content.Context;
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 *
359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <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
45ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private final Context mContext;
469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private IBluetoothGatt mService;
479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private BluetoothGattCallback mCallback;
489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private int mClientIf;
499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private boolean mAuthRetry = false;
50ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private BluetoothDevice mDevice;
51ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private boolean mAutoConnect;
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;
56ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie
57ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private static final int CONN_STATE_IDLE = 0;
58ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private static final int CONN_STATE_CONNECTING = 1;
59ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private static final int CONN_STATE_CONNECTED = 2;
60ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private static final int CONN_STATE_DISCONNECTING = 3;
6133ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    private static final int CONN_STATE_CLOSED = 4;
629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private List<BluetoothGattService> mServices;
649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
65ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    /** A GATT operation completed successfully */
669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_SUCCESS = 0;
679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
68ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    /** GATT read operation is not permitted */
699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_READ_NOT_PERMITTED = 0x2;
709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
71ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    /** GATT write operation is not permitted */
729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_WRITE_NOT_PERMITTED = 0x3;
739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /** Insufficient authentication for a given operation */
759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_INSUFFICIENT_AUTHENTICATION = 0x5;
769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /** The given request is not supported */
789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_REQUEST_NOT_SUPPORTED = 0x6;
799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /** Insufficient encryption for a given operation */
819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_INSUFFICIENT_ENCRYPTION = 0xf;
829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /** A read or write operation was requested with an invalid offset */
849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_INVALID_OFFSET = 0x7;
859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /** A write operation exceeds the maximum length of the attribute */
879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_INVALID_ATTRIBUTE_LENGTH = 0xd;
889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8945a0a1a689518df7e2c904b902e28f6d68b76e2aAndre Eisenbach    /** A remote device connection is congested. */
90dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach    public static final int GATT_CONNECTION_CONGESTED = 0x8f;
91dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach
9290ca807f7b2037499112d1c49c4b0793cc780540Matthew Xie    /** A GATT operation failed, errors other than the above */
9390ca807f7b2037499112d1c49c4b0793cc780540Matthew Xie    public static final int GATT_FAILURE = 0x101;
9490ca807f7b2037499112d1c49c4b0793cc780540Matthew Xie
959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
966ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * Connection paramter update - Use the connection paramters recommended by the
976ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * Bluetooth SIG. This is the default value if no connection parameter update
986ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * is requested.
996ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     */
1006ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach    public static final int GATT_CONNECTION_BALANCED = 0;
1016ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach
1026ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach    /**
1036ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * Connection paramter update - Request a high priority, low latency connection.
1046ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * An application should only request high priority connection paramters to transfer
1056ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * large amounts of data over LE quickly. Once the transfer is complete, the application
1066ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * should request {@link BluetoothGatt#GATT_CONNECTION_BALANCED} connectoin parameters
1076ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * to reduce energy use.
1086ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     */
1096ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach    public static final int GATT_CONNECTION_HIGH_PRIORITY = 1;
1106ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach
1116ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach    /** Connection paramter update - Request low power, reduced data rate connection parameters. */
1126ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach    public static final int GATT_CONNECTION_LOW_POWER = 2;
1136ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach
1146ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach    /**
1159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * No authentication required.
1169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @hide
1179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /*package*/ static final int AUTHENTICATION_NONE = 0;
1199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Authentication requested; no man-in-the-middle protection required.
1229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @hide
1239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /*package*/ static final int AUTHENTICATION_NO_MITM = 1;
1259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Authentication with man-in-the-middle protection requested.
1289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @hide
1299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /*package*/ static final int AUTHENTICATION_MITM = 2;
1319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Bluetooth GATT interface callbacks
1349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private final IBluetoothGattCallback mBluetoothGattCallback =
1369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        new IBluetoothGattCallback.Stub() {
1379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
1389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Application interface registered - app is ready to go
1399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
1409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
1419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onClientRegistered(int status, int clientIf) {
1429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onClientRegistered() - status=" + status
1439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    + " clientIf=" + clientIf);
144ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (VDBG) {
145ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    synchronized(mStateLock) {
146ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        if (mConnState != CONN_STATE_CONNECTING) {
147ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                            Log.e(TAG, "Bad connection state: " + mConnState);
148ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        }
149ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    }
150ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
1519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                mClientIf = clientIf;
152ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (status != GATT_SUCCESS) {
15333ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onConnectionStateChange(BluetoothGatt.this, GATT_FAILURE,
154ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                                                      BluetoothProfile.STATE_DISCONNECTED);
155ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    synchronized(mStateLock) {
156ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        mConnState = CONN_STATE_IDLE;
157ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    }
158ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
159ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
1609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
161ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    mService.clientConnect(mClientIf, mDevice.getAddress(),
162b88fa824ab6337684de9aa8437c4952df4f1a75eGanesh Ganapathi Batta                                           !mAutoConnect, mTransport); // autoConnect is inverse of "isDirect"
163ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                } catch (RemoteException e) {
164ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    Log.e(TAG,"",e);
1659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
1669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
1679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
1699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Client connection state changed
1709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
1719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
1729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onClientConnectionState(int status, int clientIf,
1739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                boolean connected, String address) {
1749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onClientConnectionState() - status=" + status
1759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                 + " clientIf=" + clientIf + " device=" + address);
176ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
177ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
178ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
179ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                int profileState = connected ? BluetoothProfile.STATE_CONNECTED :
180ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                                               BluetoothProfile.STATE_DISCONNECTED;
1819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
18233ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onConnectionStateChange(BluetoothGatt.this, status, profileState);
1839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
1840998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
1859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
186ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie
187ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                synchronized(mStateLock) {
188ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    if (connected) {
189ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        mConnState = CONN_STATE_CONNECTED;
190ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    } else {
191ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        mConnState = CONN_STATE_IDLE;
192ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    }
193ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
194cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
195cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                synchronized(mDeviceBusy) {
196cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                    mDeviceBusy = false;
197cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                }
1989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
1999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
2019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Callback reporting an LE scan result.
2029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
2039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
2049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onScanResult(String address, int rssi, byte[] advData) {
205ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                // no op
2069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
2079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
2099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * A new GATT service has been discovered.
2109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * The service is added to the internal list and the search
2119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * continues.
2129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
2139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
2149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onGetService(String address, int srvcType,
2159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                     int srvcInstId, ParcelUuid srvcUuid) {
21655d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach                if (VDBG) Log.d(TAG, "onGetService() - Device=" + address + " UUID=" + srvcUuid);
217ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
218ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
219ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
220ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                mServices.add(new BluetoothGattService(mDevice, srvcUuid.getUuid(),
2219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                       srvcInstId, srvcType));
2229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
2239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
2259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * An included service has been found durig GATT discovery.
2269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * The included service is added to the respective parent.
2279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
2289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
2299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onGetIncludedService(String address, int srvcType,
2309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                             int srvcInstId, ParcelUuid srvcUuid,
2319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                             int inclSrvcType, int inclSrvcInstId,
2329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                             ParcelUuid inclSrvcUuid) {
23355d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach                if (VDBG) Log.d(TAG, "onGetIncludedService() - Device=" + address
2349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    + " UUID=" + srvcUuid + " Included=" + inclSrvcUuid);
2359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
236ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
237ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
238ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
239ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice,
2409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        srvcUuid.getUuid(), srvcInstId, srvcType);
241ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService includedService = getService(mDevice,
2429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        inclSrvcUuid.getUuid(), inclSrvcInstId, inclSrvcType);
2439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service != null && includedService != null) {
2459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    service.addIncludedService(includedService);
2469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
2479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
2489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
2509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * A new GATT characteristic has been discovered.
2519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Add the new characteristic to the relevant service and continue
2529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * the remote device inspection.
2539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
2549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
2559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onGetCharacteristic(String address, int srvcType,
2569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int srvcInstId, ParcelUuid srvcUuid,
2579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charInstId, ParcelUuid charUuid,
2589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charProps) {
25955d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach                if (VDBG) Log.d(TAG, "onGetCharacteristic() - Device=" + address + " UUID=" +
2609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                               charUuid);
2619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
262ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
263ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
264ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
265ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
2669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                          srvcInstId, srvcType);
2679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service != null) {
2689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    service.addCharacteristic(new BluetoothGattCharacteristic(
2699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                           service, charUuid.getUuid(), charInstId, charProps, 0));
2709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
2719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
2729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
2749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * A new GATT descriptor has been discovered.
2759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Finally, add the descriptor to the related characteristic.
2769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * This should conclude the remote device update.
2779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
2789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
2799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onGetDescriptor(String address, int srvcType,
2809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int srvcInstId, ParcelUuid srvcUuid,
2819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charInstId, ParcelUuid charUuid,
28225b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                             int descrInstId, ParcelUuid descUuid) {
28355d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach                if (VDBG) Log.d(TAG, "onGetDescriptor() - Device=" + address + " UUID=" + descUuid);
2849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
285ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
286ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
287ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
288ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
2899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                          srvcInstId, srvcType);
2909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service == null) return;
2919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic characteristic = service.getCharacteristic(
2932975c683bc43582a7dcf4e25501649ad3e566707Mike J. Chen                    charUuid.getUuid(), charInstId);
2949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (characteristic == null) return;
2959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                characteristic.addDescriptor(new BluetoothGattDescriptor(
29725b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                    characteristic, descUuid.getUuid(), descrInstId, 0));
2989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
2999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
3019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Remote search has been completed.
3029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * The internal object structure should now reflect the state
3039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * of the remote device database. Let the application know that
3049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * we are done at this point.
3059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
3069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
3079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onSearchComplete(String address, int status) {
3089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onSearchComplete() = Device=" + address + " Status=" + status);
309ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
310ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
311ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
3129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
31333ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onServicesDiscovered(BluetoothGatt.this, status);
3149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
3150998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
3169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
3179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
3189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
3209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Remote characteristic has been read.
3219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Updates the internal value.
3229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
3239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
3249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onCharacteristicRead(String address, int status, int srvcType,
3259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int srvcInstId, ParcelUuid srvcUuid,
3269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charInstId, ParcelUuid charUuid, byte[] value) {
32755d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach                if (VDBG) Log.d(TAG, "onCharacteristicRead() - Device=" + address
3289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            + " UUID=" + charUuid + " Status=" + status);
3299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
330ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
331ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
332ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
333cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
334cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                synchronized(mDeviceBusy) {
335cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                    mDeviceBusy = false;
336cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                }
337cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
3389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if ((status == GATT_INSUFFICIENT_AUTHENTICATION
3399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  || status == GATT_INSUFFICIENT_ENCRYPTION)
3409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  && mAuthRetry == false) {
3419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    try {
3429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mAuthRetry = true;
3439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mService.readCharacteristic(mClientIf, address,
3449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            srvcType, srvcInstId, srvcUuid,
3459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            charInstId, charUuid, AUTHENTICATION_MITM);
3469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        return;
3479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    } catch (RemoteException e) {
3489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        Log.e(TAG,"",e);
3499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    }
3509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
3519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                mAuthRetry = false;
3539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
354ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
3559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                          srvcInstId, srvcType);
3569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service == null) return;
3579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic characteristic = service.getCharacteristic(
3599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        charUuid.getUuid(), charInstId);
3609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (characteristic == null) return;
3619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (status == 0) characteristic.setValue(value);
3639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
36533ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onCharacteristicRead(BluetoothGatt.this, characteristic, status);
3669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
3670998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
3689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
3699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
3709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
3729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Characteristic has been written to the remote device.
3739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Let the app know how we did...
3749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
3759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
3769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onCharacteristicWrite(String address, int status, int srvcType,
3779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int srvcInstId, ParcelUuid srvcUuid,
3789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charInstId, ParcelUuid charUuid) {
37955d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach                if (VDBG) Log.d(TAG, "onCharacteristicWrite() - Device=" + address
3809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            + " UUID=" + charUuid + " Status=" + status);
3819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
382ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
383ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
384ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
385cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
386cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                synchronized(mDeviceBusy) {
387cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                    mDeviceBusy = false;
388cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                }
389cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
390ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
3919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                          srvcInstId, srvcType);
3929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service == null) return;
3939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic characteristic = service.getCharacteristic(
3959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        charUuid.getUuid(), charInstId);
3969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (characteristic == null) return;
3979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if ((status == GATT_INSUFFICIENT_AUTHENTICATION
3999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  || status == GATT_INSUFFICIENT_ENCRYPTION)
4009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  && mAuthRetry == false) {
4019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    try {
4029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mAuthRetry = true;
4039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mService.writeCharacteristic(mClientIf, address,
4049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            srvcType, srvcInstId, srvcUuid, charInstId, charUuid,
4059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            characteristic.getWriteType(), AUTHENTICATION_MITM,
4069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            characteristic.getValue());
4079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        return;
4089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    } catch (RemoteException e) {
4099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        Log.e(TAG,"",e);
4109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    }
4119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
4129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                mAuthRetry = false;
4149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
41633ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onCharacteristicWrite(BluetoothGatt.this, characteristic, status);
4179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
4180998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
4199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
4209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
4219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
4239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Remote characteristic has been updated.
4249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Updates the internal value.
4259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
4269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
4279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onNotify(String address, int srvcType,
4289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int srvcInstId, ParcelUuid srvcUuid,
4299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charInstId, ParcelUuid charUuid,
4309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             byte[] value) {
43155d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach                if (VDBG) Log.d(TAG, "onNotify() - Device=" + address + " UUID=" + charUuid);
4329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
433ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
434ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
435ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
436ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
4379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                          srvcInstId, srvcType);
4389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service == null) return;
4399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic characteristic = service.getCharacteristic(
4419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        charUuid.getUuid(), charInstId);
4429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (characteristic == null) return;
4439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                characteristic.setValue(value);
4459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
44733ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onCharacteristicChanged(BluetoothGatt.this, characteristic);
4489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
4490998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
4509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
4519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
4529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
4549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Descriptor has been read.
4559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
4569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
4579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onDescriptorRead(String address, int status, int srvcType,
4589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int srvcInstId, ParcelUuid srvcUuid,
4599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charInstId, ParcelUuid charUuid,
46025b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                             int descrInstId, ParcelUuid descrUuid,
46125b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                             byte[] value) {
46255d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach                if (VDBG) Log.d(TAG, "onDescriptorRead() - Device=" + address + " UUID=" + charUuid);
4639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
464ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
465ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
466ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
467cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
468cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                synchronized(mDeviceBusy) {
469cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                    mDeviceBusy = false;
470cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                }
471cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
472ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
4739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                          srvcInstId, srvcType);
4749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service == null) return;
4759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic characteristic = service.getCharacteristic(
4779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        charUuid.getUuid(), charInstId);
4789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (characteristic == null) return;
4799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
48125b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                        descrUuid.getUuid(), descrInstId);
4829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (descriptor == null) return;
4839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (status == 0) descriptor.setValue(value);
4859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if ((status == GATT_INSUFFICIENT_AUTHENTICATION
4879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  || status == GATT_INSUFFICIENT_ENCRYPTION)
4889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  && mAuthRetry == false) {
4899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    try {
4909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mAuthRetry = true;
4919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mService.readDescriptor(mClientIf, address,
4929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            srvcType, srvcInstId, srvcUuid, charInstId, charUuid,
49325b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                            descrInstId, descrUuid, AUTHENTICATION_MITM);
4949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    } catch (RemoteException e) {
4959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        Log.e(TAG,"",e);
4969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    }
4979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
4989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                mAuthRetry = true;
5009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
50233ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onDescriptorRead(BluetoothGatt.this, descriptor, status);
5039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
5040998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
5059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
5069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
5079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
5099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Descriptor write operation complete.
5109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
5119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
5129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onDescriptorWrite(String address, int status, int srvcType,
5139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int srvcInstId, ParcelUuid srvcUuid,
5149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charInstId, ParcelUuid charUuid,
51525b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                             int descrInstId, ParcelUuid descrUuid) {
51655d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach                if (VDBG) Log.d(TAG, "onDescriptorWrite() - Device=" + address + " UUID=" + charUuid);
5179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
518ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
519ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
520ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
521cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
522cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                synchronized(mDeviceBusy) {
523cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                    mDeviceBusy = false;
524cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                }
525cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
526ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
5279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                          srvcInstId, srvcType);
5289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service == null) return;
5299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic characteristic = service.getCharacteristic(
5319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        charUuid.getUuid(), charInstId);
5329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (characteristic == null) return;
5339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
53525b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                        descrUuid.getUuid(), descrInstId);
5369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (descriptor == null) return;
5379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if ((status == GATT_INSUFFICIENT_AUTHENTICATION
5399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  || status == GATT_INSUFFICIENT_ENCRYPTION)
5409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  && mAuthRetry == false) {
5419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    try {
5429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mAuthRetry = true;
5439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mService.writeDescriptor(mClientIf, address,
5449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            srvcType, srvcInstId, srvcUuid, charInstId, charUuid,
54525b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                            descrInstId, descrUuid, characteristic.getWriteType(),
5469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            AUTHENTICATION_MITM, descriptor.getValue());
5479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    } catch (RemoteException e) {
5489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        Log.e(TAG,"",e);
5499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    }
5509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
5519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                mAuthRetry = false;
5539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
55533ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onDescriptorWrite(BluetoothGatt.this, descriptor, status);
5569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
5570998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
5589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
5599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
5609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
5629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Prepared write transaction completed (or aborted)
5639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
5649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
5659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onExecuteWrite(String address, int status) {
56655d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach                if (VDBG) Log.d(TAG, "onExecuteWrite() - Device=" + address
5679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    + " status=" + status);
568ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
569ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
570ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
571cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
572cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                synchronized(mDeviceBusy) {
573cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                    mDeviceBusy = false;
574cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                }
575cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
5769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
57733ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onReliableWriteCompleted(BluetoothGatt.this, status);
5789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
5790998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
5809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
5819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
5829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
5849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Remote device RSSI has been read
5859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
5869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
5879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onReadRemoteRssi(String address, int rssi, int status) {
58855d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach                if (VDBG) Log.d(TAG, "onReadRemoteRssi() - Device=" + address +
5899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            " rssi=" + rssi + " status=" + status);
590ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
591ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
592ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
5939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
59433ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onReadRemoteRssi(BluetoothGatt.this, rssi, status);
5959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
5960998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
5979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
5989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
599f305589f22f3fa1d73f2e29009d382c9a4f5c293Wei Wang
600f305589f22f3fa1d73f2e29009d382c9a4f5c293Wei Wang            /**
601f305589f22f3fa1d73f2e29009d382c9a4f5c293Wei Wang             * Advertise state change callback
602f305589f22f3fa1d73f2e29009d382c9a4f5c293Wei Wang             * @hide
603f305589f22f3fa1d73f2e29009d382c9a4f5c293Wei Wang             */
604f305589f22f3fa1d73f2e29009d382c9a4f5c293Wei Wang            public void onAdvertiseStateChange(int state, int status) {
605f305589f22f3fa1d73f2e29009d382c9a4f5c293Wei Wang                if (DBG) Log.d(TAG, "onAdvertiseStateChange() - state = "
606f305589f22f3fa1d73f2e29009d382c9a4f5c293Wei Wang                        + state + " status=" + status);
607adf6aff5b03b1e3ca4636f9887225a7f906d1238Wei Wang            }
608adf6aff5b03b1e3ca4636f9887225a7f906d1238Wei Wang
609adf6aff5b03b1e3ca4636f9887225a7f906d1238Wei Wang            /**
610adf6aff5b03b1e3ca4636f9887225a7f906d1238Wei Wang             * @hide
611adf6aff5b03b1e3ca4636f9887225a7f906d1238Wei Wang             */
612adf6aff5b03b1e3ca4636f9887225a7f906d1238Wei Wang            @Override
613adf6aff5b03b1e3ca4636f9887225a7f906d1238Wei Wang            public void onMultiAdvertiseCallback(int status) {
614adf6aff5b03b1e3ca4636f9887225a7f906d1238Wei Wang                // no op.
615adf6aff5b03b1e3ca4636f9887225a7f906d1238Wei Wang            }
616580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach
617580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach            /**
618580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach             * Callback invoked when the MTU for a given connection changes
619580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach             * @hide
620580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach             */
621580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach            public void onConfigureMTU(String address, int mtu, int status) {
622580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                if (DBG) Log.d(TAG, "onConfigureMTU() - Device=" + address +
623580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                            " mtu=" + mtu + " status=" + status);
624580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                if (!address.equals(mDevice.getAddress())) {
625580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                    return;
626580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                }
627580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                try {
628580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                    mCallback.onConfigureMTU(BluetoothGatt.this, mtu, status);
629580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                } catch (Exception ex) {
630580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                    Log.w(TAG, "Unhandled exception in callback", ex);
631580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                }
632f305589f22f3fa1d73f2e29009d382c9a4f5c293Wei Wang            }
633dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach
634dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach            /**
635dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach             * Callback indicating the remote device connection is congested.
636dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach             * @hide
637dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach             */
638dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach            public void onConnectionCongested(String address, boolean congested) {
639dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach                if (DBG) Log.d(TAG, "onConnectionCongested() - Device=" + address
640dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach                        + " congested=" + congested);
641dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach                if (!address.equals(mDevice.getAddress())) return;
642dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach                try {
643dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach                    mCallback.onConnectionCongested(BluetoothGatt.this, congested);
644dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach                } catch (Exception ex) {
645dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach                    Log.w(TAG, "Unhandled exception in callback", ex);
646dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach                }
647dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach            }
6489fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang
6499fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang            @Override
6509fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang            public void onBatchScanResults(List<ScanResult> results) {
6519fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang                // no op
6529fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang            }
6538f2e74cac282afa0bcf98f5d7131268147d12efePrerepa Viswanadham
6548f2e74cac282afa0bcf98f5d7131268147d12efePrerepa Viswanadham            /**
6558f2e74cac282afa0bcf98f5d7131268147d12efePrerepa Viswanadham             * @hide
6568f2e74cac282afa0bcf98f5d7131268147d12efePrerepa Viswanadham             */
6578f2e74cac282afa0bcf98f5d7131268147d12efePrerepa Viswanadham            @Override
6588f2e74cac282afa0bcf98f5d7131268147d12efePrerepa Viswanadham            public void onFoundOrLost(boolean onFound, String address, int rssi,
6598f2e74cac282afa0bcf98f5d7131268147d12efePrerepa Viswanadham                    byte[] advData) {
6608f2e74cac282afa0bcf98f5d7131268147d12efePrerepa Viswanadham                // no op.
6618f2e74cac282afa0bcf98f5d7131268147d12efePrerepa Viswanadham            }
6629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        };
6639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
664b88fa824ab6337684de9aa8437c4952df4f1a75eGanesh Ganapathi Batta    /*package*/ BluetoothGatt(Context context, IBluetoothGatt iGatt, BluetoothDevice device,
665b88fa824ab6337684de9aa8437c4952df4f1a75eGanesh Ganapathi Batta                                int transport) {
6669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        mContext = context;
667ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        mService = iGatt;
668ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        mDevice = device;
669b88fa824ab6337684de9aa8437c4952df4f1a75eGanesh Ganapathi Batta        mTransport = transport;
6709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        mServices = new ArrayList<BluetoothGattService>();
6719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
672ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        mConnState = CONN_STATE_IDLE;
6739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
6749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
67633ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * Close this Bluetooth GATT client.
677b30f91e38c19f6728d836293446d4b9c76705e7fMatthew Xie     *
678b30f91e38c19f6728d836293446d4b9c76705e7fMatthew Xie     * Application should call this method as early as possible after it is done with
679b30f91e38c19f6728d836293446d4b9c76705e7fMatthew Xie     * this GATT client.
6809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
68133ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    public void close() {
6829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "close()");
6839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        unregisterApp();
68533ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie        mConnState = CONN_STATE_CLOSED;
6869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
6879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
6899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Returns a service by UUID, instance and type.
6909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @hide
6919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
6929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /*package*/ BluetoothGattService getService(BluetoothDevice device, UUID uuid,
6939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                int instanceId, int type) {
6949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        for(BluetoothGattService svc : mServices) {
6959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            if (svc.getDevice().equals(device) &&
6969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                svc.getType() == type &&
6979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                svc.getInstanceId() == instanceId &&
6989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                svc.getUuid().equals(uuid)) {
6999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                return svc;
7009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
7019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
7029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return null;
7039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
7049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
7059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
7069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
707ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Register an application callback to start using GATT.
7089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
709ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * <p>This is an asynchronous call. The callback {@link BluetoothGattCallback#onAppRegistered}
710ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * is used to notify success or failure if the function returns true.
7119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
7129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
7139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
714ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @param callback GATT callback handler that will receive asynchronous callbacks.
715ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @return If true, the callback will be called to notify success or failure,
716ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     *         false on immediate error
7179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
718ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private boolean registerApp(BluetoothGattCallback callback) {
7199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "registerApp()");
7209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null) return false;
7219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
7229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        mCallback = callback;
7239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        UUID uuid = UUID.randomUUID();
7249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "registerApp() - UUID=" + uuid);
7259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
7269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
7279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.registerClient(new ParcelUuid(uuid), mBluetoothGattCallback);
7289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
7299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
7309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
7319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
7329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
7339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
7349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
7359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
7369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
7379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Unregister the current application and callbacks.
7389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
739ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private void unregisterApp() {
7409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "unregisterApp() - mClientIf=" + mClientIf);
7419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return;
7429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
7439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
7449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mCallback = null;
7459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.unregisterClient(mClientIf);
7469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mClientIf = 0;
7479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
7489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
7499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
7509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
7519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
7529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
753ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Initiate a connection to a Bluetooth GATT capable device.
7549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
7559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>The connection may not be established right away, but will be
7569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * completed when the remote device is available. A
7579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * {@link BluetoothGattCallback#onConnectionStateChange} callback will be
7589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * invoked when the connection state changes as a result of this function.
7599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
7606ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * <p>The autoConnect parameter determines whether to actively connect to
7619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * the remote device, or rather passively scan and finalize the connection
7629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * when the remote device is in range/available. Generally, the first ever
7639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * connection to a device should be direct (autoConnect set to false) and
7649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * subsequent connections to known devices should be invoked with the
765ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * autoConnect parameter set to true.
7669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
7679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
7689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
7699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param device Remote device to connect to
7709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param autoConnect Whether to directly connect to the remote device (false)
7719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *                    or to automatically connect as soon as the remote
7729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *                    device becomes available (true).
7739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the connection attempt was initiated successfully
7749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
775ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    /*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallback callback) {
776ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "connect() - device: " + mDevice.getAddress() + ", auto: " + autoConnect);
777ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        synchronized(mStateLock) {
778ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            if (mConnState != CONN_STATE_IDLE) {
779ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                throw new IllegalStateException("Not idle");
780ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            }
781ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mConnState = CONN_STATE_CONNECTING;
782ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        }
783ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (!registerApp(callback)) {
784ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            synchronized(mStateLock) {
785ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                mConnState = CONN_STATE_IDLE;
786ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            }
787ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            Log.e(TAG, "Failed to register callback");
7889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
7899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
7909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
791ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        // the connection will continue after successful callback registration
792ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        mAutoConnect = autoConnect;
7939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
7949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
7959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
7969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
7979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Disconnects an established connection, or cancels a connection attempt
7989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * currently in progress.
7999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
8019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
802ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public void disconnect() {
803ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "cancelOpen() - device: " + mDevice.getAddress());
8049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return;
8059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
807ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.clientDisconnect(mClientIf, mDevice.getAddress());
8089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
8099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
8109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
81133ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    }
81233ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie
81333ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    /**
81433ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * Connect back to remote device.
81533ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     *
81633ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * <p>This method is used to re-connect to a remote device after the
81733ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * connection has been dropped. If the device is not in range, the
81833ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * re-connection will be triggered once the device is back in range.
81933ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     *
82033ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * @return true, if the connection attempt was initiated successfully
82133ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     */
82233ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    public boolean connect() {
82333ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie        try {
82433ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie            mService.clientConnect(mClientIf, mDevice.getAddress(),
825b88fa824ab6337684de9aa8437c4952df4f1a75eGanesh Ganapathi Batta                                   false, mTransport); // autoConnect is inverse of "isDirect"
82633ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie            return true;
82733ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie        } catch (RemoteException e) {
82833ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie            Log.e(TAG,"",e);
82933ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie            return false;
83033ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie        }
83133ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    }
83233ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie
83333ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    /**
83433ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * Return the remote bluetooth device this GATT client targets to
83533ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     *
83633ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * @return remote bluetooth device
83733ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     */
83833ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    public BluetoothDevice getDevice() {
83933ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie        return mDevice;
8409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
8419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
8439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Discovers services offered by a remote device as well as their
8449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * characteristics and descriptors.
8459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>This is an asynchronous operation. Once service discovery is completed,
8479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * the {@link BluetoothGattCallback#onServicesDiscovered} callback is
8489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * triggered. If the discovery was successful, the remote services can be
8499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * retrieved using the {@link #getServices} function.
8509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
8529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the remote service discovery has been started
8549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
855ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public boolean discoverServices() {
856ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "discoverServices() - device: " + mDevice.getAddress());
8579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
8589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        mServices.clear();
8609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
862ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.discoverServices(mClientIf, mDevice.getAddress());
8639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
8649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
8659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
8669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
8679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
8699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
8709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
8729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Returns a list of GATT services offered by the remote device.
8739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>This function requires that service discovery has been completed
8759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * for the given device.
8769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
8789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return List of services on the remote device. Returns an empty list
8809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *         if service discovery has not yet been performed.
8819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
882ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public List<BluetoothGattService> getServices() {
8839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        List<BluetoothGattService> result =
8849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ArrayList<BluetoothGattService>();
8859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        for (BluetoothGattService service : mServices) {
887ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            if (service.getDevice().equals(mDevice)) {
8889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                result.add(service);
8899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
8909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
8919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return result;
8939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
8949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
8969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Returns a {@link BluetoothGattService}, if the requested UUID is
8979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * supported by the remote device.
8989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>This function requires that service discovery has been completed
9009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * for the given device.
9019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>If multiple instances of the same service (as identified by UUID)
9039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * exist, the first instance of the service is returned.
9049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
9069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param uuid UUID of the requested service
9089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return BluetoothGattService if supported, or null if the requested
9099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *         service is not offered by the remote device.
9109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
911ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public BluetoothGattService getService(UUID uuid) {
9129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        for (BluetoothGattService service : mServices) {
913ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            if (service.getDevice().equals(mDevice) &&
9149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                service.getUuid().equals(uuid)) {
9159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                return service;
9169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
9179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
9189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return null;
9209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
9219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
9239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Reads the requested characteristic from the associated remote device.
9249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>This is an asynchronous operation. The result of the read operation
9269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * is reported by the {@link BluetoothGattCallback#onCharacteristicRead}
9279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * callback.
9289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
9309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param characteristic Characteristic to read from the remote device
9329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the read operation was initiated successfully
9339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
9349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public boolean readCharacteristic(BluetoothGattCharacteristic characteristic) {
9359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if ((characteristic.getProperties() &
9369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic.PROPERTY_READ) == 0) return false;
9379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
93855d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach        if (VDBG) Log.d(TAG, "readCharacteristic() - uuid: " + characteristic.getUuid());
9399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
9409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattService service = characteristic.getService();
9429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (service == null) return false;
9439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothDevice device = service.getDevice();
9459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (device == null) return false;
9469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
947cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        synchronized(mDeviceBusy) {
948cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            if (mDeviceBusy) return false;
949cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = true;
950cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        }
951cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
9529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
9539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.readCharacteristic(mClientIf, device.getAddress(),
9549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                service.getType(), service.getInstanceId(),
9559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ParcelUuid(service.getUuid()), characteristic.getInstanceId(),
9569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ParcelUuid(characteristic.getUuid()), AUTHENTICATION_NONE);
9579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
9589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
959cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = false;
9609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
9619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
9629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
9649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
9659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
967ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Writes a given characteristic and its values to the associated remote device.
9689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Once the write operation has been completed, the
9709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * {@link BluetoothGattCallback#onCharacteristicWrite} callback is invoked,
9719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * reporting the result of the operation.
9729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
9749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param characteristic Characteristic to write on the remote device
9769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the write operation was initiated successfully
9779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
9789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public boolean writeCharacteristic(BluetoothGattCharacteristic characteristic) {
9799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE) == 0
9809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            && (characteristic.getProperties() &
9819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) == 0) return false;
9829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
98355d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach        if (VDBG) Log.d(TAG, "writeCharacteristic() - uuid: " + characteristic.getUuid());
9849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
9859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattService service = characteristic.getService();
9879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (service == null) return false;
9889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothDevice device = service.getDevice();
9909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (device == null) return false;
9919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
992cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        synchronized(mDeviceBusy) {
993cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            if (mDeviceBusy) return false;
994cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = true;
995cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        }
996cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
9979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
9989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.writeCharacteristic(mClientIf, device.getAddress(),
9999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                service.getType(), service.getInstanceId(),
10009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ParcelUuid(service.getUuid()), characteristic.getInstanceId(),
10019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ParcelUuid(characteristic.getUuid()),
10029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                characteristic.getWriteType(), AUTHENTICATION_NONE,
10039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                characteristic.getValue());
10049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
10059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
1006cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = false;
10079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
10089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
10099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
10119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
10129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
10149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Reads the value for a given descriptor from the associated remote device.
10159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Once the read operation has been completed, the
10179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * {@link BluetoothGattCallback#onDescriptorRead} callback is
10189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * triggered, signaling the result of the operation.
10199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
10219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param descriptor Descriptor value to read from the remote device
10239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the read operation was initiated successfully
10249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
10259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public boolean readDescriptor(BluetoothGattDescriptor descriptor) {
102655d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach        if (VDBG) Log.d(TAG, "readDescriptor() - uuid: " + descriptor.getUuid());
10279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
10289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic();
10309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (characteristic == null) return false;
10319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattService service = characteristic.getService();
10339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (service == null) return false;
10349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothDevice device = service.getDevice();
10369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (device == null) return false;
10379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1038cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        synchronized(mDeviceBusy) {
1039cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            if (mDeviceBusy) return false;
1040cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = true;
1041cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        }
1042cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
10439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
104425b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach            mService.readDescriptor(mClientIf, device.getAddress(), service.getType(),
104525b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                service.getInstanceId(), new ParcelUuid(service.getUuid()),
104625b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                characteristic.getInstanceId(), new ParcelUuid(characteristic.getUuid()),
104725b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                descriptor.getInstanceId(), new ParcelUuid(descriptor.getUuid()),
104825b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                AUTHENTICATION_NONE);
10499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
10509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
1051cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = false;
10529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
10539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
10549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
10569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
10579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
10599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Write the value of a given descriptor to the associated remote device.
10609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>A {@link BluetoothGattCallback#onDescriptorWrite} callback is
10629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * triggered to report the result of the write operation.
10639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
10659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param descriptor Descriptor to write to the associated remote device
10679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the write operation was initiated successfully
10689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
10699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public boolean writeDescriptor(BluetoothGattDescriptor descriptor) {
107055d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach        if (VDBG) Log.d(TAG, "writeDescriptor() - uuid: " + descriptor.getUuid());
10719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
10729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic();
10749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (characteristic == null) return false;
10759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattService service = characteristic.getService();
10779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (service == null) return false;
10789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothDevice device = service.getDevice();
10809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (device == null) return false;
10819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1082cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        synchronized(mDeviceBusy) {
1083cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            if (mDeviceBusy) return false;
1084cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = true;
1085cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        }
1086cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
10879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
108825b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach            mService.writeDescriptor(mClientIf, device.getAddress(), service.getType(),
108925b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                service.getInstanceId(), new ParcelUuid(service.getUuid()),
109025b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                characteristic.getInstanceId(), new ParcelUuid(characteristic.getUuid()),
109125b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                descriptor.getInstanceId(), new ParcelUuid(descriptor.getUuid()),
10929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                characteristic.getWriteType(), AUTHENTICATION_NONE,
10939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                descriptor.getValue());
10949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
10959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
1096cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = false;
10979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
10989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
10999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
11019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
11029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
11049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Initiates a reliable write transaction for a given remote device.
11059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Once a reliable write transaction has been initiated, all calls
11079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * to {@link #writeCharacteristic} are sent to the remote device for
11089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * verification and queued up for atomic execution. The application will
11099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * receive an {@link BluetoothGattCallback#onCharacteristicWrite} callback
11109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * in response to every {@link #writeCharacteristic} call and is responsible
11119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * for verifying if the value has been transmitted accurately.
11129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>After all characteristics have been queued up and verified,
11149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * {@link #executeReliableWrite} will execute all writes. If a characteristic
11159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * was not written correctly, calling {@link #abortReliableWrite} will
11169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * cancel the current transaction without commiting any values on the
11179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * remote device.
11189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
11209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the reliable write transaction has been initiated
11229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1123ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public boolean beginReliableWrite() {
112455d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach        if (VDBG) Log.d(TAG, "beginReliableWrite() - device: " + mDevice.getAddress());
11259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
11269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
1128ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.beginReliableWrite(mClientIf, mDevice.getAddress());
11299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
11309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
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     * Executes a reliable write transaction for a given remote device.
11399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>This function will commit all queued up characteristic write
11419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * operations for a given remote device.
11429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>A {@link BluetoothGattCallback#onReliableWriteCompleted} callback is
11449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * invoked to indicate whether the transaction has been executed correctly.
11459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
11479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the request to execute the transaction has been sent
11499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1150ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public boolean executeReliableWrite() {
115155d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach        if (VDBG) Log.d(TAG, "executeReliableWrite() - device: " + mDevice.getAddress());
11529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
11539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1154cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        synchronized(mDeviceBusy) {
1155cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            if (mDeviceBusy) return false;
1156cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = true;
1157cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        }
1158cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
11599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
1160ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.endReliableWrite(mClientIf, mDevice.getAddress(), true);
11619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
11629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
1163cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = false;
11649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
11659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
11669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
11689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
11699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
11719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Cancels a reliable write transaction for a given device.
11729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Calling this function will discard all queued characteristic write
11749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * operations for a given remote device.
11759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
11779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
117848f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du    public void abortReliableWrite() {
117955d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach        if (VDBG) Log.d(TAG, "abortReliableWrite() - device: " + mDevice.getAddress());
11809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return;
11819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
1183ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.endReliableWrite(mClientIf, mDevice.getAddress(), false);
11849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
11859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
11869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
11879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
11889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1190b7b7d7a05c164a56dd4155de4e84fc25ba706728John Du     * @deprecated Use {@link #abortReliableWrite()}
119148f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du     */
119248f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du    public void abortReliableWrite(BluetoothDevice mDevice) {
119348f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du        abortReliableWrite();
119448f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du    }
119548f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du
119648f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du    /**
11979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Enable or disable notifications/indications for a given characteristic.
11989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Once notifications are enabled for a characteristic, a
12009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * {@link BluetoothGattCallback#onCharacteristicChanged} callback will be
12019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * triggered if the remote device indicates that the given characteristic
12029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * has changed.
12039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
12049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
12059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
12069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param characteristic The characteristic for which to enable notifications
12079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param enable Set to true to enable notifications/indications
12089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the requested notification status was set successfully
12099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
12109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public boolean setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
12119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                              boolean enable) {
12129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "setCharacteristicNotification() - uuid: " + characteristic.getUuid()
12139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                         + " enable: " + enable);
12149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
12159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattService service = characteristic.getService();
12179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (service == null) return false;
12189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothDevice device = service.getDevice();
12209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (device == null) return false;
12219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
12239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.registerForNotification(mClientIf, device.getAddress(),
12249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                service.getType(), service.getInstanceId(),
12259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ParcelUuid(service.getUuid()), characteristic.getInstanceId(),
12269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ParcelUuid(characteristic.getUuid()),
12279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                enable);
12289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
12299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
12309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
12319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
12329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
12349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
12359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
12379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Clears the internal cache and forces a refresh of the services from the
12389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * remote device.
12399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @hide
12409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1241ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public boolean refresh() {
1242ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "refresh() - device: " + mDevice.getAddress());
12439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
12449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
1246ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.refreshDevice(mClientIf, mDevice.getAddress());
12479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
12489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
12499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
12509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
12519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
12539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
12549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
12569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Read the RSSI for a connected remote device.
12579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
12589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>The {@link BluetoothGattCallback#onReadRemoteRssi} callback will be
12599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * invoked when the RSSI value has been read.
12609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
12619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
12629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
12639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the RSSI value has been requested successfully
12649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1265ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public boolean readRemoteRssi() {
1266ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "readRssi() - device: " + mDevice.getAddress());
12679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
12689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
1270ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.readRemoteRssi(mClientIf, mDevice.getAddress());
12719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
12729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
12739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
12749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
12759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
12779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
12789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1280580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     * Configure the MTU used for a given connection.
1281580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     *
1282580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     * <p>When performing a write request operation (write without response),
1283580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     * the data sent is truncated to the MTU size. This function may be used
1284580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     * to request a larget MTU size to be able to send more data at once.
1285580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     *
1286580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     * <p>A {@link BluetoothGattCallback#onConfigureMTU} callback will indicate
1287580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     * whether this operation was successful.
1288580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     *
1289580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
1290580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     *
1291580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     * @return true, if the new MTU value has been requested successfully
1292580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     */
1293580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach    public boolean configureMTU(int mtu) {
1294580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach        if (DBG) Log.d(TAG, "configureMTU() - device: " + mDevice.getAddress()
1295580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                            + " mtu: " + mtu);
1296580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach        if (mService == null || mClientIf == 0) return false;
1297580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach
1298580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach        try {
1299580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach            mService.configureMTU(mClientIf, mDevice.getAddress(), mtu);
1300580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach        } catch (RemoteException e) {
1301580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach            Log.e(TAG,"",e);
1302580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach            return false;
1303580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach        }
1304580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach
1305580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach        return true;
1306580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach    }
1307580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach
1308580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach    /**
13096ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * Request a connection parameter update.
13106ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     *
13116ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * <p>This function will send a connection parameter update request to the
13126ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * remote device.
13136ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     *
13146ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * @param connectionPriority Request a specific connection priority. Must be one of
13156ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     *          {@link BluetoothGatt#GATT_CONNECTION_BALANCED},
13166ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     *          {@link BluetoothGatt#GATT_CONNECTION_HIGH_PRIORITY}
13176ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     *          or {@link BluetoothGatt#GATT_CONNECTION_LOW_POWER}.
13186ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * @throws IllegalArgumentException If the parameters are outside of their
13196ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     *                                  specified range.
13206ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     */
13216ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach    public boolean requestConnectionParameterUpdate(int connectionPriority) {
13226ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach        if (connectionPriority < GATT_CONNECTION_BALANCED ||
13236ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach            connectionPriority > GATT_CONNECTION_LOW_POWER) {
13246ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach            throw new IllegalArgumentException("connectionPriority not within valid range");
13256ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach        }
13266ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach
13276ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach        if (DBG) Log.d(TAG, "requestConnectionParameterUpdate() - params: " + connectionPriority);
13286ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach        if (mService == null || mClientIf == 0) return false;
13296ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach
13306ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach        try {
13316ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach            mService.connectionParameterUpdate(mClientIf, mDevice.getAddress(), connectionPriority);
13326ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach        } catch (RemoteException e) {
13336ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach            Log.e(TAG,"",e);
13346ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach            return false;
13356ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach        }
13366ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach
13376ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach        return true;
13386ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach    }
13396ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach
13406ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach    /**
1341ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
1342ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * with {@link BluetoothProfile#GATT} as argument
13439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
1344ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @throws UnsupportedOperationException
13459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
13469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    @Override
13479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public int getConnectionState(BluetoothDevice device) {
1348ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        throw new UnsupportedOperationException("Use BluetoothManager#getConnectionState instead.");
13499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
13509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
13519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1352ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
1353ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * with {@link BluetoothProfile#GATT} as argument
13549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
1355ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @throws UnsupportedOperationException
13569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
13579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    @Override
13589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public List<BluetoothDevice> getConnectedDevices() {
1359ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        throw new UnsupportedOperationException
1360ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            ("Use BluetoothManager#getConnectedDevices instead.");
13619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
13629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
13639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1364ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Not supported - please use
1365ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * {@link BluetoothManager#getDevicesMatchingConnectionStates(int, int[])}
1366ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * with {@link BluetoothProfile#GATT} as first argument
13679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
1368ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @throws UnsupportedOperationException
13699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
13709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    @Override
13719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
1372ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        throw new UnsupportedOperationException
1373ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            ("Use BluetoothManager#getDevicesMatchingConnectionStates instead.");
13749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
13759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta}
1376