19908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta/*
29908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Copyright (C) 2013 The Android Open Source Project
39908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta *
49908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Licensed under the Apache License, Version 2.0 (the "License");
59908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * you may not use this file except in compliance with the License.
69908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * You may obtain a copy of the License at
79908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta *
89908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta *      http://www.apache.org/licenses/LICENSE-2.0
99908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta *
109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Unless required by applicable law or agreed to in writing, software
119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * distributed under the License is distributed on an "AS IS" BASIS,
129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * See the License for the specific language governing permissions and
149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * limitations under the License.
159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */
169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battapackage android.bluetooth;
189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.content.Context;
209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.os.ParcelUuid;
219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.os.RemoteException;
229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.util.Log;
239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport java.util.ArrayList;
259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport java.util.List;
269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport java.util.UUID;
279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta/**
29ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * Public API for the Bluetooth GATT Profile.
309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta *
31ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * <p>This class provides Bluetooth GATT functionality to enable communication
329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * with Bluetooth Smart or Smart Ready devices.
339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta *
349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>To connect to a remote peripheral device, create a {@link BluetoothGattCallback}
3533ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie * and call {@link BluetoothDevice#connectGatt} to get a instance of this class.
36ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * GATT capable devices can be discovered using the Bluetooth device discovery or BLE
37ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * scan process.
389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */
399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battapublic final class BluetoothGatt implements BluetoothProfile {
409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private static final String TAG = "BluetoothGatt";
419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private static final boolean DBG = true;
4255d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach    private static final boolean VDBG = false;
439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
44ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private final Context mContext;
459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private IBluetoothGatt mService;
469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private BluetoothGattCallback mCallback;
479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private int mClientIf;
489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private boolean mAuthRetry = false;
49ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private BluetoothDevice mDevice;
50ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private boolean mAutoConnect;
51ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private int mConnState;
52ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private final Object mStateLock = new Object();
53cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach    private Boolean mDeviceBusy = false;
54b88fa824ab6337684de9aa8437c4952df4f1a75eGanesh Ganapathi Batta    private int mTransport;
55ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie
56ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private static final int CONN_STATE_IDLE = 0;
57ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private static final int CONN_STATE_CONNECTING = 1;
58ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private static final int CONN_STATE_CONNECTED = 2;
59ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private static final int CONN_STATE_DISCONNECTING = 3;
6033ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    private static final int CONN_STATE_CLOSED = 4;
619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private List<BluetoothGattService> mServices;
639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
64ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    /** A GATT operation completed successfully */
659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_SUCCESS = 0;
669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
67ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    /** GATT read operation is not permitted */
689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_READ_NOT_PERMITTED = 0x2;
699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
70ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    /** GATT write operation is not permitted */
719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_WRITE_NOT_PERMITTED = 0x3;
729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /** Insufficient authentication for a given operation */
749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_INSUFFICIENT_AUTHENTICATION = 0x5;
759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /** The given request is not supported */
779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_REQUEST_NOT_SUPPORTED = 0x6;
789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /** Insufficient encryption for a given operation */
809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_INSUFFICIENT_ENCRYPTION = 0xf;
819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /** A read or write operation was requested with an invalid offset */
839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_INVALID_OFFSET = 0x7;
849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /** A write operation exceeds the maximum length of the attribute */
869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_INVALID_ATTRIBUTE_LENGTH = 0xd;
879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8845a0a1a689518df7e2c904b902e28f6d68b76e2aAndre Eisenbach    /** A remote device connection is congested. */
89dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach    public static final int GATT_CONNECTION_CONGESTED = 0x8f;
90dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach
9190ca807f7b2037499112d1c49c4b0793cc780540Matthew Xie    /** A GATT operation failed, errors other than the above */
9290ca807f7b2037499112d1c49c4b0793cc780540Matthew Xie    public static final int GATT_FAILURE = 0x101;
9390ca807f7b2037499112d1c49c4b0793cc780540Matthew Xie
949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
956ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * Connection paramter update - Use the connection paramters recommended by the
966ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * Bluetooth SIG. This is the default value if no connection parameter update
976ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * is requested.
986ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     */
994072da041da2911dd56635b530b276671ce0199dAndre Eisenbach    public static final int CONNECTION_PRIORITY_BALANCED = 0;
1006ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach
1016ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach    /**
1026ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * Connection paramter update - Request a high priority, low latency connection.
1036ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * An application should only request high priority connection paramters to transfer
1046ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * large amounts of data over LE quickly. Once the transfer is complete, the application
1054072da041da2911dd56635b530b276671ce0199dAndre Eisenbach     * should request {@link BluetoothGatt#CONNECTION_PRIORITY_BALANCED} connectoin parameters
1066ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * to reduce energy use.
1076ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     */
1084072da041da2911dd56635b530b276671ce0199dAndre Eisenbach    public static final int CONNECTION_PRIORITY_HIGH = 1;
1096ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach
1106ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach    /** Connection paramter update - Request low power, reduced data rate connection parameters. */
1114072da041da2911dd56635b530b276671ce0199dAndre Eisenbach    public static final int CONNECTION_PRIORITY_LOW_POWER = 2;
1126ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach
1136ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach    /**
1149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * No authentication required.
1159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @hide
1169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /*package*/ static final int AUTHENTICATION_NONE = 0;
1189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Authentication requested; no man-in-the-middle protection required.
1219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @hide
1229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /*package*/ static final int AUTHENTICATION_NO_MITM = 1;
1249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Authentication with man-in-the-middle protection requested.
1279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @hide
1289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /*package*/ static final int AUTHENTICATION_MITM = 2;
1309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
132e0d4afb2d4caecb264852a35f6e3cfc1248e08c4Wei Wang     * Bluetooth GATT callbacks. Overrides the default BluetoothGattCallback implementation.
1339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private final IBluetoothGattCallback mBluetoothGattCallback =
135e0d4afb2d4caecb264852a35f6e3cfc1248e08c4Wei Wang        new BluetoothGattCallbackWrapper() {
1369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
1379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Application interface registered - app is ready to go
1389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
1399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
1409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onClientRegistered(int status, int clientIf) {
1419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onClientRegistered() - status=" + status
1429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    + " clientIf=" + clientIf);
143ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (VDBG) {
144ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    synchronized(mStateLock) {
145ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        if (mConnState != CONN_STATE_CONNECTING) {
146ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                            Log.e(TAG, "Bad connection state: " + mConnState);
147ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        }
148ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    }
149ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
1509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                mClientIf = clientIf;
151ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (status != GATT_SUCCESS) {
15233ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onConnectionStateChange(BluetoothGatt.this, GATT_FAILURE,
153ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                                                      BluetoothProfile.STATE_DISCONNECTED);
154ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    synchronized(mStateLock) {
155ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        mConnState = CONN_STATE_IDLE;
156ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    }
157ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
158ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
1599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
160ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    mService.clientConnect(mClientIf, mDevice.getAddress(),
161b88fa824ab6337684de9aa8437c4952df4f1a75eGanesh Ganapathi Batta                                           !mAutoConnect, mTransport); // autoConnect is inverse of "isDirect"
162ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                } catch (RemoteException e) {
163ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    Log.e(TAG,"",e);
1649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
1659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
1669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
1689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Client connection state changed
1699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
1709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
1719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onClientConnectionState(int status, int clientIf,
1729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                boolean connected, String address) {
1739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onClientConnectionState() - status=" + status
1749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                 + " clientIf=" + clientIf + " device=" + address);
175ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
176ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
177ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
178ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                int profileState = connected ? BluetoothProfile.STATE_CONNECTED :
179ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                                               BluetoothProfile.STATE_DISCONNECTED;
1809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
18133ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onConnectionStateChange(BluetoothGatt.this, status, profileState);
1829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
1830998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
1849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
185ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie
186ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                synchronized(mStateLock) {
187ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    if (connected) {
188ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        mConnState = CONN_STATE_CONNECTED;
189ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    } else {
190ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        mConnState = CONN_STATE_IDLE;
191ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    }
192ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
193cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
194cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                synchronized(mDeviceBusy) {
195cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                    mDeviceBusy = false;
196cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                }
1979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
1989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
2009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * A new GATT service has been discovered.
2019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * The service is added to the internal list and the search
2029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * continues.
2039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
2049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
2059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onGetService(String address, int srvcType,
2069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                     int srvcInstId, ParcelUuid srvcUuid) {
20755d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach                if (VDBG) Log.d(TAG, "onGetService() - Device=" + address + " UUID=" + srvcUuid);
208ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
209ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
210ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
211ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                mServices.add(new BluetoothGattService(mDevice, srvcUuid.getUuid(),
2129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                       srvcInstId, srvcType));
2139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
2149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
2169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * An included service has been found durig GATT discovery.
2179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * The included service is added to the respective parent.
2189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
2199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
2209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onGetIncludedService(String address, int srvcType,
2219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                             int srvcInstId, ParcelUuid srvcUuid,
2229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                             int inclSrvcType, int inclSrvcInstId,
2239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                             ParcelUuid inclSrvcUuid) {
22455d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach                if (VDBG) Log.d(TAG, "onGetIncludedService() - Device=" + address
2259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    + " UUID=" + srvcUuid + " Included=" + inclSrvcUuid);
2269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
227ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
228ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
229ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
230ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice,
2319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        srvcUuid.getUuid(), srvcInstId, srvcType);
232ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService includedService = getService(mDevice,
2339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        inclSrvcUuid.getUuid(), inclSrvcInstId, inclSrvcType);
2349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service != null && includedService != null) {
2369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    service.addIncludedService(includedService);
2379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
2389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
2399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
2419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * A new GATT characteristic has been discovered.
2429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Add the new characteristic to the relevant service and continue
2439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * the remote device inspection.
2449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
2459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
2469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onGetCharacteristic(String address, int srvcType,
2479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int srvcInstId, ParcelUuid srvcUuid,
2489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charInstId, ParcelUuid charUuid,
2499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charProps) {
25055d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach                if (VDBG) Log.d(TAG, "onGetCharacteristic() - Device=" + address + " UUID=" +
2519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                               charUuid);
2529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
253ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
254ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
255ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
256ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
2579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                          srvcInstId, srvcType);
2589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service != null) {
2599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    service.addCharacteristic(new BluetoothGattCharacteristic(
2609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                           service, charUuid.getUuid(), charInstId, charProps, 0));
2619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
2629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
2639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
2659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * A new GATT descriptor has been discovered.
2669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Finally, add the descriptor to the related characteristic.
2679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * This should conclude the remote device update.
2689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
2699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
2709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onGetDescriptor(String address, int srvcType,
2719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int srvcInstId, ParcelUuid srvcUuid,
2729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charInstId, ParcelUuid charUuid,
27325b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                             int descrInstId, ParcelUuid descUuid) {
27455d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach                if (VDBG) Log.d(TAG, "onGetDescriptor() - Device=" + address + " UUID=" + descUuid);
2759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
276ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
277ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
278ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
279ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
2809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                          srvcInstId, srvcType);
2819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service == null) return;
2829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic characteristic = service.getCharacteristic(
2842975c683bc43582a7dcf4e25501649ad3e566707Mike J. Chen                    charUuid.getUuid(), charInstId);
2859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (characteristic == null) return;
2869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                characteristic.addDescriptor(new BluetoothGattDescriptor(
28825b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                    characteristic, descUuid.getUuid(), descrInstId, 0));
2899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
2909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
2929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Remote search has been completed.
2939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * The internal object structure should now reflect the state
2949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * of the remote device database. Let the application know that
2959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * we are done at this point.
2969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
2979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
2989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onSearchComplete(String address, int status) {
2999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onSearchComplete() = Device=" + address + " Status=" + status);
300ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
301ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
302ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
3039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
30433ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onServicesDiscovered(BluetoothGatt.this, status);
3059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
3060998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
3079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
3089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
3099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
3119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Remote characteristic has been read.
3129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Updates the internal value.
3139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
3149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
3159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onCharacteristicRead(String address, int status, int srvcType,
3169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int srvcInstId, ParcelUuid srvcUuid,
3179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charInstId, ParcelUuid charUuid, byte[] value) {
31855d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach                if (VDBG) Log.d(TAG, "onCharacteristicRead() - Device=" + address
3199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            + " UUID=" + charUuid + " Status=" + status);
3209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
321ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
322ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
323ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
324cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
325cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                synchronized(mDeviceBusy) {
326cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                    mDeviceBusy = false;
327cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                }
328cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
3299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if ((status == GATT_INSUFFICIENT_AUTHENTICATION
3309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  || status == GATT_INSUFFICIENT_ENCRYPTION)
3319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  && mAuthRetry == false) {
3329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    try {
3339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mAuthRetry = true;
3349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mService.readCharacteristic(mClientIf, address,
3359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            srvcType, srvcInstId, srvcUuid,
3369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            charInstId, charUuid, AUTHENTICATION_MITM);
3379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        return;
3389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    } catch (RemoteException e) {
3399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        Log.e(TAG,"",e);
3409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    }
3419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
3429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                mAuthRetry = false;
3449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
345ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
3469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                          srvcInstId, srvcType);
3479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service == null) return;
3489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic characteristic = service.getCharacteristic(
3509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        charUuid.getUuid(), charInstId);
3519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (characteristic == null) return;
3529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (status == 0) characteristic.setValue(value);
3549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
35633ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onCharacteristicRead(BluetoothGatt.this, characteristic, status);
3579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
3580998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
3599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
3609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
3619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
3639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Characteristic has been written to the remote device.
3649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Let the app know how we did...
3659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
3669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
3679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onCharacteristicWrite(String address, int status, int srvcType,
3689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int srvcInstId, ParcelUuid srvcUuid,
3699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charInstId, ParcelUuid charUuid) {
37055d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach                if (VDBG) Log.d(TAG, "onCharacteristicWrite() - Device=" + address
3719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            + " UUID=" + charUuid + " Status=" + status);
3729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
373ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
374ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
375ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
376cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
377cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                synchronized(mDeviceBusy) {
378cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                    mDeviceBusy = false;
379cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                }
380cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
381ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
3829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                          srvcInstId, srvcType);
3839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service == null) return;
3849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic characteristic = service.getCharacteristic(
3869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        charUuid.getUuid(), charInstId);
3879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (characteristic == null) return;
3889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if ((status == GATT_INSUFFICIENT_AUTHENTICATION
3909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  || status == GATT_INSUFFICIENT_ENCRYPTION)
3919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  && mAuthRetry == false) {
3929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    try {
3939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mAuthRetry = true;
3949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mService.writeCharacteristic(mClientIf, address,
3959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            srvcType, srvcInstId, srvcUuid, charInstId, charUuid,
3969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            characteristic.getWriteType(), AUTHENTICATION_MITM,
3979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            characteristic.getValue());
3989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        return;
3999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    } catch (RemoteException e) {
4009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        Log.e(TAG,"",e);
4019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    }
4029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
4039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                mAuthRetry = false;
4059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
40733ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onCharacteristicWrite(BluetoothGatt.this, characteristic, status);
4089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
4090998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
4109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
4119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
4129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
4149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Remote characteristic has been updated.
4159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Updates the internal value.
4169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
4179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
4189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onNotify(String address, int srvcType,
4199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int srvcInstId, ParcelUuid srvcUuid,
4209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charInstId, ParcelUuid charUuid,
4219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             byte[] value) {
42255d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach                if (VDBG) Log.d(TAG, "onNotify() - Device=" + address + " UUID=" + charUuid);
4239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
424ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
425ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
426ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
427ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
4289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                          srvcInstId, srvcType);
4299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service == null) return;
4309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic characteristic = service.getCharacteristic(
4329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        charUuid.getUuid(), charInstId);
4339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (characteristic == null) return;
4349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                characteristic.setValue(value);
4369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
43833ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onCharacteristicChanged(BluetoothGatt.this, characteristic);
4399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
4400998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
4419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
4429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
4439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
4459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Descriptor has been read.
4469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
4479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
4489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onDescriptorRead(String address, int status, int srvcType,
4499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int srvcInstId, ParcelUuid srvcUuid,
4509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charInstId, ParcelUuid charUuid,
45125b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                             int descrInstId, ParcelUuid descrUuid,
45225b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                             byte[] value) {
45355d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach                if (VDBG) Log.d(TAG, "onDescriptorRead() - Device=" + address + " UUID=" + charUuid);
4549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
455ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
456ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
457ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
458cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
459cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                synchronized(mDeviceBusy) {
460cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                    mDeviceBusy = false;
461cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                }
462cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
463ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
4649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                          srvcInstId, srvcType);
4659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service == null) return;
4669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic characteristic = service.getCharacteristic(
4689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        charUuid.getUuid(), charInstId);
4699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (characteristic == null) return;
4709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
47225b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                        descrUuid.getUuid(), descrInstId);
4739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (descriptor == null) return;
4749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (status == 0) descriptor.setValue(value);
4769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if ((status == GATT_INSUFFICIENT_AUTHENTICATION
4789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  || status == GATT_INSUFFICIENT_ENCRYPTION)
4799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  && mAuthRetry == false) {
4809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    try {
4819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mAuthRetry = true;
4829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mService.readDescriptor(mClientIf, address,
4839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            srvcType, srvcInstId, srvcUuid, charInstId, charUuid,
48425b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                            descrInstId, descrUuid, AUTHENTICATION_MITM);
485d65e8f4b6b37b274fcd5b7701a73eaef7c4ba8b4Andre Eisenbach                        return;
4869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    } catch (RemoteException e) {
4879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        Log.e(TAG,"",e);
4889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    }
4899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
4909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                mAuthRetry = true;
4929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
49433ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onDescriptorRead(BluetoothGatt.this, descriptor, status);
4959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
4960998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
4979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
4989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
4999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
5019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Descriptor write operation complete.
5029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
5039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
5049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onDescriptorWrite(String address, int status, int srvcType,
5059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int srvcInstId, ParcelUuid srvcUuid,
5069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charInstId, ParcelUuid charUuid,
50725b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                             int descrInstId, ParcelUuid descrUuid) {
50855d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach                if (VDBG) Log.d(TAG, "onDescriptorWrite() - Device=" + address + " UUID=" + charUuid);
5099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
510ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
511ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
512ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
513cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
514cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                synchronized(mDeviceBusy) {
515cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                    mDeviceBusy = false;
516cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                }
517cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
518ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
5199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                          srvcInstId, srvcType);
5209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service == null) return;
5219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic characteristic = service.getCharacteristic(
5239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        charUuid.getUuid(), charInstId);
5249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (characteristic == null) return;
5259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
52725b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                        descrUuid.getUuid(), descrInstId);
5289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (descriptor == null) return;
5299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if ((status == GATT_INSUFFICIENT_AUTHENTICATION
5319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  || status == GATT_INSUFFICIENT_ENCRYPTION)
5329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  && mAuthRetry == false) {
5339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    try {
5349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mAuthRetry = true;
5359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mService.writeDescriptor(mClientIf, address,
5369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            srvcType, srvcInstId, srvcUuid, charInstId, charUuid,
53725b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                            descrInstId, descrUuid, characteristic.getWriteType(),
5389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            AUTHENTICATION_MITM, descriptor.getValue());
539d65e8f4b6b37b274fcd5b7701a73eaef7c4ba8b4Andre Eisenbach                        return;
5409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    } catch (RemoteException e) {
5419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        Log.e(TAG,"",e);
5429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    }
5439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
5449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                mAuthRetry = false;
5469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
54833ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onDescriptorWrite(BluetoothGatt.this, descriptor, status);
5499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
5500998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
5519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
5529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
5539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
5559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Prepared write transaction completed (or aborted)
5569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
5579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
5589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onExecuteWrite(String address, int status) {
55955d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach                if (VDBG) Log.d(TAG, "onExecuteWrite() - Device=" + address
5609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    + " status=" + status);
561ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
562ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
563ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
564cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
565cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                synchronized(mDeviceBusy) {
566cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                    mDeviceBusy = false;
567cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                }
568cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
5699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
57033ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onReliableWriteCompleted(BluetoothGatt.this, status);
5719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
5720998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
5739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
5749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
5759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
5779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Remote device RSSI has been read
5789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
5799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
5809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onReadRemoteRssi(String address, int rssi, int status) {
58155d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach                if (VDBG) Log.d(TAG, "onReadRemoteRssi() - Device=" + address +
5829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            " rssi=" + rssi + " status=" + status);
583ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
584ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
585ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
5869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
58733ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onReadRemoteRssi(BluetoothGatt.this, rssi, status);
5889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
5890998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
5909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
5919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
592f305589f22f3fa1d73f2e29009d382c9a4f5c293Wei Wang
593f305589f22f3fa1d73f2e29009d382c9a4f5c293Wei Wang            /**
594580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach             * Callback invoked when the MTU for a given connection changes
595580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach             * @hide
596580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach             */
597580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach            public void onConfigureMTU(String address, int mtu, int status) {
598580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                if (DBG) Log.d(TAG, "onConfigureMTU() - Device=" + address +
599580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                            " mtu=" + mtu + " status=" + status);
600580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                if (!address.equals(mDevice.getAddress())) {
601580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                    return;
602580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                }
603580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                try {
6044072da041da2911dd56635b530b276671ce0199dAndre Eisenbach                    mCallback.onMtuChanged(BluetoothGatt.this, mtu, status);
605580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                } catch (Exception ex) {
606580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                    Log.w(TAG, "Unhandled exception in callback", ex);
607580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                }
608f305589f22f3fa1d73f2e29009d382c9a4f5c293Wei Wang            }
6099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        };
6109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
611b88fa824ab6337684de9aa8437c4952df4f1a75eGanesh Ganapathi Batta    /*package*/ BluetoothGatt(Context context, IBluetoothGatt iGatt, BluetoothDevice device,
612b88fa824ab6337684de9aa8437c4952df4f1a75eGanesh Ganapathi Batta                                int transport) {
6139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        mContext = context;
614ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        mService = iGatt;
615ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        mDevice = device;
616b88fa824ab6337684de9aa8437c4952df4f1a75eGanesh Ganapathi Batta        mTransport = transport;
6179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        mServices = new ArrayList<BluetoothGattService>();
6189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
619ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        mConnState = CONN_STATE_IDLE;
6209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
6219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
62333ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * Close this Bluetooth GATT client.
624b30f91e38c19f6728d836293446d4b9c76705e7fMatthew Xie     *
625b30f91e38c19f6728d836293446d4b9c76705e7fMatthew Xie     * Application should call this method as early as possible after it is done with
626b30f91e38c19f6728d836293446d4b9c76705e7fMatthew Xie     * this GATT client.
6279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
62833ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    public void close() {
6299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "close()");
6309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        unregisterApp();
63233ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie        mConnState = CONN_STATE_CLOSED;
6339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
6349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
6369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Returns a service by UUID, instance and type.
6379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @hide
6389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
6399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /*package*/ BluetoothGattService getService(BluetoothDevice device, UUID uuid,
6409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                int instanceId, int type) {
6419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        for(BluetoothGattService svc : mServices) {
6429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            if (svc.getDevice().equals(device) &&
6439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                svc.getType() == type &&
6449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                svc.getInstanceId() == instanceId &&
6459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                svc.getUuid().equals(uuid)) {
6469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                return svc;
6479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
6489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
6499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return null;
6509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
6519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
654ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Register an application callback to start using GATT.
6559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
656ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * <p>This is an asynchronous call. The callback {@link BluetoothGattCallback#onAppRegistered}
657ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * is used to notify success or failure if the function returns true.
6589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
6599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
6609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
661ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @param callback GATT callback handler that will receive asynchronous callbacks.
662ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @return If true, the callback will be called to notify success or failure,
663ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     *         false on immediate error
6649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
665ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private boolean registerApp(BluetoothGattCallback callback) {
6669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "registerApp()");
6679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null) return false;
6689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        mCallback = callback;
6709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        UUID uuid = UUID.randomUUID();
6719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "registerApp() - UUID=" + uuid);
6729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
6749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.registerClient(new ParcelUuid(uuid), mBluetoothGattCallback);
6759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
6769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
6779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
6789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
6799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
6819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
6829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
6849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Unregister the current application and callbacks.
6859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
686ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private void unregisterApp() {
6879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "unregisterApp() - mClientIf=" + mClientIf);
6889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return;
6899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
6919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mCallback = null;
6929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.unregisterClient(mClientIf);
6939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mClientIf = 0;
6949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
6959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
6969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
6979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
6989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
700ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Initiate a connection to a Bluetooth GATT capable device.
7019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
7029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>The connection may not be established right away, but will be
7039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * completed when the remote device is available. A
7049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * {@link BluetoothGattCallback#onConnectionStateChange} callback will be
7059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * invoked when the connection state changes as a result of this function.
7069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
7076ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * <p>The autoConnect parameter determines whether to actively connect to
7089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * the remote device, or rather passively scan and finalize the connection
7099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * when the remote device is in range/available. Generally, the first ever
7109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * connection to a device should be direct (autoConnect set to false) and
7119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * subsequent connections to known devices should be invoked with the
712ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * autoConnect parameter set to true.
7139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
7149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
7159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
7169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param device Remote device to connect to
7179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param autoConnect Whether to directly connect to the remote device (false)
7189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *                    or to automatically connect as soon as the remote
7199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *                    device becomes available (true).
7209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the connection attempt was initiated successfully
7219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
722ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    /*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallback callback) {
723ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "connect() - device: " + mDevice.getAddress() + ", auto: " + autoConnect);
724ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        synchronized(mStateLock) {
725ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            if (mConnState != CONN_STATE_IDLE) {
726ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                throw new IllegalStateException("Not idle");
727ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            }
728ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mConnState = CONN_STATE_CONNECTING;
729ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        }
730ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (!registerApp(callback)) {
731ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            synchronized(mStateLock) {
732ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                mConnState = CONN_STATE_IDLE;
733ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            }
734ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            Log.e(TAG, "Failed to register callback");
7359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
7369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
7379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
738ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        // the connection will continue after successful callback registration
739ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        mAutoConnect = autoConnect;
7409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
7419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
7429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
7439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
7449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Disconnects an established connection, or cancels a connection attempt
7459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * currently in progress.
7469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
7479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
7489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
749ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public void disconnect() {
750ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "cancelOpen() - device: " + mDevice.getAddress());
7519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return;
7529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
7539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
754ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.clientDisconnect(mClientIf, mDevice.getAddress());
7559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
7569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
7579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
75833ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    }
75933ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie
76033ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    /**
76133ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * Connect back to remote device.
76233ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     *
76333ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * <p>This method is used to re-connect to a remote device after the
76433ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * connection has been dropped. If the device is not in range, the
76533ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * re-connection will be triggered once the device is back in range.
76633ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     *
76733ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * @return true, if the connection attempt was initiated successfully
76833ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     */
76933ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    public boolean connect() {
77033ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie        try {
77133ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie            mService.clientConnect(mClientIf, mDevice.getAddress(),
772b88fa824ab6337684de9aa8437c4952df4f1a75eGanesh Ganapathi Batta                                   false, mTransport); // autoConnect is inverse of "isDirect"
77333ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie            return true;
77433ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie        } catch (RemoteException e) {
77533ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie            Log.e(TAG,"",e);
77633ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie            return false;
77733ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie        }
77833ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    }
77933ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie
78033ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    /**
78133ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * Return the remote bluetooth device this GATT client targets to
78233ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     *
78333ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * @return remote bluetooth device
78433ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     */
78533ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    public BluetoothDevice getDevice() {
78633ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie        return mDevice;
7879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
7889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
7899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
7909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Discovers services offered by a remote device as well as their
7919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * characteristics and descriptors.
7929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
7939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>This is an asynchronous operation. Once service discovery is completed,
7949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * the {@link BluetoothGattCallback#onServicesDiscovered} callback is
7959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * triggered. If the discovery was successful, the remote services can be
7969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * retrieved using the {@link #getServices} function.
7979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
7989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
7999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the remote service discovery has been started
8019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
802ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public boolean discoverServices() {
803ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "discoverServices() - device: " + mDevice.getAddress());
8049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
8059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        mServices.clear();
8079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
809ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.discoverServices(mClientIf, mDevice.getAddress());
8109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
8119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
8129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
8139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
8149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
8169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
8179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
8199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Returns a list of GATT services offered by the remote device.
8209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>This function requires that service discovery has been completed
8229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * for the given device.
8239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
8259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return List of services on the remote device. Returns an empty list
8279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *         if service discovery has not yet been performed.
8289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
829ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public List<BluetoothGattService> getServices() {
8309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        List<BluetoothGattService> result =
8319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ArrayList<BluetoothGattService>();
8329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        for (BluetoothGattService service : mServices) {
834ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            if (service.getDevice().equals(mDevice)) {
8359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                result.add(service);
8369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
8379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
8389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return result;
8409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
8419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
8439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Returns a {@link BluetoothGattService}, if the requested UUID is
8449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * supported by the remote device.
8459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>This function requires that service discovery has been completed
8479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * for the given device.
8489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>If multiple instances of the same service (as identified by UUID)
8509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * exist, the first instance of the service is returned.
8519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
8539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param uuid UUID of the requested service
8559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return BluetoothGattService if supported, or null if the requested
8569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *         service is not offered by the remote device.
8579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
858ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public BluetoothGattService getService(UUID uuid) {
8599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        for (BluetoothGattService service : mServices) {
860ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            if (service.getDevice().equals(mDevice) &&
8619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                service.getUuid().equals(uuid)) {
8629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                return service;
8639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
8649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
8659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return null;
8679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
8689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
8709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Reads the requested characteristic from the associated remote device.
8719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>This is an asynchronous operation. The result of the read operation
8739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * is reported by the {@link BluetoothGattCallback#onCharacteristicRead}
8749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * callback.
8759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
8779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param characteristic Characteristic to read from the remote device
8799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the read operation was initiated successfully
8809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
8819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public boolean readCharacteristic(BluetoothGattCharacteristic characteristic) {
8829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if ((characteristic.getProperties() &
8839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic.PROPERTY_READ) == 0) return false;
8849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
88555d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach        if (VDBG) Log.d(TAG, "readCharacteristic() - uuid: " + characteristic.getUuid());
8869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
8879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattService service = characteristic.getService();
8899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (service == null) return false;
8909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothDevice device = service.getDevice();
8929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (device == null) return false;
8939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
894cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        synchronized(mDeviceBusy) {
895cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            if (mDeviceBusy) return false;
896cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = true;
897cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        }
898cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
8999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
9009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.readCharacteristic(mClientIf, device.getAddress(),
9019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                service.getType(), service.getInstanceId(),
9029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ParcelUuid(service.getUuid()), characteristic.getInstanceId(),
9039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ParcelUuid(characteristic.getUuid()), AUTHENTICATION_NONE);
9049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
9059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
906cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = false;
9079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
9089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
9099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
9119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
9129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
914ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Writes a given characteristic and its values to the associated remote device.
9159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Once the write operation has been completed, the
9179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * {@link BluetoothGattCallback#onCharacteristicWrite} callback is invoked,
9189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * reporting the result of the operation.
9199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
9219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param characteristic Characteristic to write on the remote device
9239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the write operation was initiated successfully
9249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
9259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public boolean writeCharacteristic(BluetoothGattCharacteristic characteristic) {
9269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE) == 0
9279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            && (characteristic.getProperties() &
9289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) == 0) return false;
9299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
93055d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach        if (VDBG) Log.d(TAG, "writeCharacteristic() - uuid: " + characteristic.getUuid());
931ff5e5db319785d23d672af95ac2dff3f37827cfdPrerepa Viswanadham        if (mService == null || mClientIf == 0 || characteristic.getValue() == null) return false;
9329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattService service = characteristic.getService();
9349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (service == null) return false;
9359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothDevice device = service.getDevice();
9379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (device == null) return false;
9389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
939cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        synchronized(mDeviceBusy) {
940cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            if (mDeviceBusy) return false;
941cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = true;
942cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        }
943cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
9449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
9459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.writeCharacteristic(mClientIf, device.getAddress(),
9469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                service.getType(), service.getInstanceId(),
9479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ParcelUuid(service.getUuid()), characteristic.getInstanceId(),
9489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ParcelUuid(characteristic.getUuid()),
9499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                characteristic.getWriteType(), AUTHENTICATION_NONE,
9509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                characteristic.getValue());
9519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
9529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
953cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = false;
9549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
9559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
9569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
9589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
9599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
9619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Reads the value for a given descriptor from the associated remote device.
9629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Once the read operation has been completed, the
9649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * {@link BluetoothGattCallback#onDescriptorRead} callback is
9659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * triggered, signaling the result of the operation.
9669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
9689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param descriptor Descriptor value to read from the remote device
9709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the read operation was initiated successfully
9719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
9729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public boolean readDescriptor(BluetoothGattDescriptor descriptor) {
97355d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach        if (VDBG) Log.d(TAG, "readDescriptor() - uuid: " + descriptor.getUuid());
9749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
9759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic();
9779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (characteristic == null) return false;
9789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattService service = characteristic.getService();
9809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (service == null) return false;
9819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothDevice device = service.getDevice();
9839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (device == null) return false;
9849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
985cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        synchronized(mDeviceBusy) {
986cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            if (mDeviceBusy) return false;
987cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = true;
988cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        }
989cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
9909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
99125b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach            mService.readDescriptor(mClientIf, device.getAddress(), service.getType(),
99225b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                service.getInstanceId(), new ParcelUuid(service.getUuid()),
99325b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                characteristic.getInstanceId(), new ParcelUuid(characteristic.getUuid()),
99425b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                descriptor.getInstanceId(), new ParcelUuid(descriptor.getUuid()),
99525b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                AUTHENTICATION_NONE);
9969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
9979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
998cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = false;
9999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
10009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
10019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
10039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
10049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
10069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Write the value of a given descriptor to the associated remote device.
10079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>A {@link BluetoothGattCallback#onDescriptorWrite} callback is
10099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * triggered to report the result of the write operation.
10109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
10129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param descriptor Descriptor to write to the associated remote device
10149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the write operation was initiated successfully
10159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
10169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public boolean writeDescriptor(BluetoothGattDescriptor descriptor) {
101755d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach        if (VDBG) Log.d(TAG, "writeDescriptor() - uuid: " + descriptor.getUuid());
1018ff5e5db319785d23d672af95ac2dff3f37827cfdPrerepa Viswanadham        if (mService == null || mClientIf == 0 || descriptor.getValue() == null) return false;
10199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic();
10219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (characteristic == null) return false;
10229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattService service = characteristic.getService();
10249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (service == null) return false;
10259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothDevice device = service.getDevice();
10279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (device == null) return false;
10289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1029cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        synchronized(mDeviceBusy) {
1030cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            if (mDeviceBusy) return false;
1031cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = true;
1032cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        }
1033cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
10349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
103525b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach            mService.writeDescriptor(mClientIf, device.getAddress(), service.getType(),
103625b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                service.getInstanceId(), new ParcelUuid(service.getUuid()),
103725b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                characteristic.getInstanceId(), new ParcelUuid(characteristic.getUuid()),
103825b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                descriptor.getInstanceId(), new ParcelUuid(descriptor.getUuid()),
10399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                characteristic.getWriteType(), AUTHENTICATION_NONE,
10409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                descriptor.getValue());
10419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
10429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
1043cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = false;
10449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
10459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
10469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
10489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
10499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
10519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Initiates a reliable write transaction for a given remote device.
10529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Once a reliable write transaction has been initiated, all calls
10549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * to {@link #writeCharacteristic} are sent to the remote device for
10559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * verification and queued up for atomic execution. The application will
10569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * receive an {@link BluetoothGattCallback#onCharacteristicWrite} callback
10579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * in response to every {@link #writeCharacteristic} call and is responsible
10589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * for verifying if the value has been transmitted accurately.
10599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>After all characteristics have been queued up and verified,
10619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * {@link #executeReliableWrite} will execute all writes. If a characteristic
10629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * was not written correctly, calling {@link #abortReliableWrite} will
10639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * cancel the current transaction without commiting any values on the
10649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * remote device.
10659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
10679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the reliable write transaction has been initiated
10699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1070ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public boolean beginReliableWrite() {
107155d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach        if (VDBG) Log.d(TAG, "beginReliableWrite() - device: " + mDevice.getAddress());
10729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
10739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
1075ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.beginReliableWrite(mClientIf, mDevice.getAddress());
10769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
10779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
10789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
10799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
10809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
10829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
10839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
10859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Executes a reliable write transaction for a given remote device.
10869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>This function will commit all queued up characteristic write
10889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * operations for a given remote device.
10899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>A {@link BluetoothGattCallback#onReliableWriteCompleted} callback is
10919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * invoked to indicate whether the transaction has been executed correctly.
10929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
10949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the request to execute the transaction has been sent
10969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1097ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public boolean executeReliableWrite() {
109855d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach        if (VDBG) Log.d(TAG, "executeReliableWrite() - device: " + mDevice.getAddress());
10999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
11009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1101cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        synchronized(mDeviceBusy) {
1102cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            if (mDeviceBusy) return false;
1103cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = true;
1104cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        }
1105cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
11069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
1107ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.endReliableWrite(mClientIf, mDevice.getAddress(), true);
11089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
11099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
1110cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = false;
11119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
11129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
11139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
11159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
11169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
11189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Cancels a reliable write transaction for a given device.
11199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Calling this function will discard all queued characteristic write
11219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * operations for a given remote device.
11229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
11249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
112548f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du    public void abortReliableWrite() {
112655d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach        if (VDBG) Log.d(TAG, "abortReliableWrite() - device: " + mDevice.getAddress());
11279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return;
11289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
1130ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.endReliableWrite(mClientIf, mDevice.getAddress(), false);
11319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
11329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
11339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
11349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
11359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1137b7b7d7a05c164a56dd4155de4e84fc25ba706728John Du     * @deprecated Use {@link #abortReliableWrite()}
113848f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du     */
113948f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du    public void abortReliableWrite(BluetoothDevice mDevice) {
114048f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du        abortReliableWrite();
114148f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du    }
114248f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du
114348f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du    /**
11449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Enable or disable notifications/indications for a given characteristic.
11459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Once notifications are enabled for a characteristic, a
11479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * {@link BluetoothGattCallback#onCharacteristicChanged} callback will be
11489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * triggered if the remote device indicates that the given characteristic
11499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * has changed.
11509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
11529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param characteristic The characteristic for which to enable notifications
11549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param enable Set to true to enable notifications/indications
11559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the requested notification status was set successfully
11569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
11579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public boolean setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
11589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                              boolean enable) {
11599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "setCharacteristicNotification() - uuid: " + characteristic.getUuid()
11609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                         + " enable: " + enable);
11619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
11629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattService service = characteristic.getService();
11649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (service == null) return false;
11659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothDevice device = service.getDevice();
11679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (device == null) return false;
11689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
11709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.registerForNotification(mClientIf, device.getAddress(),
11719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                service.getType(), service.getInstanceId(),
11729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ParcelUuid(service.getUuid()), characteristic.getInstanceId(),
11739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ParcelUuid(characteristic.getUuid()),
11749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                enable);
11759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
11769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
11779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
11789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
11799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
11819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
11829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
11849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Clears the internal cache and forces a refresh of the services from the
11859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * remote device.
11869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @hide
11879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1188ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public boolean refresh() {
1189ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "refresh() - device: " + mDevice.getAddress());
11909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
11919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
1193ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.refreshDevice(mClientIf, mDevice.getAddress());
11949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
11959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
11969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
11979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
11989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
12009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
12019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
12039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Read the RSSI for a connected remote device.
12049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
12059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>The {@link BluetoothGattCallback#onReadRemoteRssi} callback will be
12069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * invoked when the RSSI value has been read.
12079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
12089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
12099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
12109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the RSSI value has been requested successfully
12119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1212ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public boolean readRemoteRssi() {
1213ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "readRssi() - device: " + mDevice.getAddress());
12149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
12159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
1217ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.readRemoteRssi(mClientIf, mDevice.getAddress());
12189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
12199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
12209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
12219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
12229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
12249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
12259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
12274072da041da2911dd56635b530b276671ce0199dAndre Eisenbach     * Request an MTU size used for a given connection.
1228580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     *
1229580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     * <p>When performing a write request operation (write without response),
1230580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     * the data sent is truncated to the MTU size. This function may be used
12314072da041da2911dd56635b530b276671ce0199dAndre Eisenbach     * to request a larger MTU size to be able to send more data at once.
1232580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     *
12334072da041da2911dd56635b530b276671ce0199dAndre Eisenbach     * <p>A {@link BluetoothGattCallback#onMtuChanged} callback will indicate
1234580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     * whether this operation was successful.
1235580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     *
1236580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
1237580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     *
1238580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     * @return true, if the new MTU value has been requested successfully
1239580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     */
12404072da041da2911dd56635b530b276671ce0199dAndre Eisenbach    public boolean requestMtu(int mtu) {
1241580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach        if (DBG) Log.d(TAG, "configureMTU() - device: " + mDevice.getAddress()
1242580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                            + " mtu: " + mtu);
1243580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach        if (mService == null || mClientIf == 0) return false;
1244580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach
1245580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach        try {
1246580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach            mService.configureMTU(mClientIf, mDevice.getAddress(), mtu);
1247580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach        } catch (RemoteException e) {
1248580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach            Log.e(TAG,"",e);
1249580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach            return false;
1250580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach        }
1251580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach
1252580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach        return true;
1253580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach    }
1254580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach
1255580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach    /**
12566ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * Request a connection parameter update.
12576ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     *
12586ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * <p>This function will send a connection parameter update request to the
12596ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * remote device.
12606ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     *
12616ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * @param connectionPriority Request a specific connection priority. Must be one of
12624072da041da2911dd56635b530b276671ce0199dAndre Eisenbach     *          {@link BluetoothGatt#CONNECTION_PRIORITY_BALANCED},
12634072da041da2911dd56635b530b276671ce0199dAndre Eisenbach     *          {@link BluetoothGatt#CONNECTION_PRIORITY_HIGH}
12644072da041da2911dd56635b530b276671ce0199dAndre Eisenbach     *          or {@link BluetoothGatt#CONNECTION_PRIORITY_LOW_POWER}.
12656ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     * @throws IllegalArgumentException If the parameters are outside of their
12666ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     *                                  specified range.
12676ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach     */
12684072da041da2911dd56635b530b276671ce0199dAndre Eisenbach    public boolean requestConnectionPriority(int connectionPriority) {
12694072da041da2911dd56635b530b276671ce0199dAndre Eisenbach        if (connectionPriority < CONNECTION_PRIORITY_BALANCED ||
12704072da041da2911dd56635b530b276671ce0199dAndre Eisenbach            connectionPriority > CONNECTION_PRIORITY_LOW_POWER) {
12716ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach            throw new IllegalArgumentException("connectionPriority not within valid range");
12726ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach        }
12736ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach
12744072da041da2911dd56635b530b276671ce0199dAndre Eisenbach        if (DBG) Log.d(TAG, "requestConnectionPriority() - params: " + connectionPriority);
12756ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach        if (mService == null || mClientIf == 0) return false;
12766ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach
12776ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach        try {
12786ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach            mService.connectionParameterUpdate(mClientIf, mDevice.getAddress(), connectionPriority);
12796ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach        } catch (RemoteException e) {
12806ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach            Log.e(TAG,"",e);
12816ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach            return false;
12826ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach        }
12836ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach
12846ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach        return true;
12856ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach    }
12866ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach
12876ce4db0acf9dea297d96424e526092e799f6da84Andre Eisenbach    /**
1288ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
1289ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * with {@link BluetoothProfile#GATT} as argument
12909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
1291ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @throws UnsupportedOperationException
12929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
12939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    @Override
12949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public int getConnectionState(BluetoothDevice device) {
1295ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        throw new UnsupportedOperationException("Use BluetoothManager#getConnectionState instead.");
12969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
12979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1299ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
1300ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * with {@link BluetoothProfile#GATT} as argument
13019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
1302ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @throws UnsupportedOperationException
13039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
13049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    @Override
13059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public List<BluetoothDevice> getConnectedDevices() {
1306ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        throw new UnsupportedOperationException
1307ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            ("Use BluetoothManager#getConnectedDevices instead.");
13089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
13099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
13109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1311ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Not supported - please use
1312ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * {@link BluetoothManager#getDevicesMatchingConnectionStates(int, int[])}
1313ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * with {@link BluetoothProfile#GATT} as first argument
13149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
1315ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @throws UnsupportedOperationException
13169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
13179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    @Override
13189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
1319ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        throw new UnsupportedOperationException
1320ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            ("Use BluetoothManager#getDevicesMatchingConnectionStates instead.");
13219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
13229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta}
1323