BluetoothGatt.java revision b88fa824ab6337684de9aa8437c4952df4f1a75e
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;
42ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private static final boolean VDBG = true;
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
8890ca807f7b2037499112d1c49c4b0793cc780540Matthew Xie    /** A GATT operation failed, errors other than the above */
8990ca807f7b2037499112d1c49c4b0793cc780540Matthew Xie    public static final int GATT_FAILURE = 0x101;
9090ca807f7b2037499112d1c49c4b0793cc780540Matthew Xie
919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * No authentication required.
939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @hide
949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /*package*/ static final int AUTHENTICATION_NONE = 0;
969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Authentication requested; no man-in-the-middle protection required.
999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @hide
1009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /*package*/ static final int AUTHENTICATION_NO_MITM = 1;
1029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Authentication with man-in-the-middle protection requested.
1059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @hide
1069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /*package*/ static final int AUTHENTICATION_MITM = 2;
1089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Bluetooth GATT interface callbacks
1119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private final IBluetoothGattCallback mBluetoothGattCallback =
1139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        new IBluetoothGattCallback.Stub() {
1149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
1159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Application interface registered - app is ready to go
1169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
1179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
1189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onClientRegistered(int status, int clientIf) {
1199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onClientRegistered() - status=" + status
1209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    + " clientIf=" + clientIf);
121ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (VDBG) {
122ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    synchronized(mStateLock) {
123ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        if (mConnState != CONN_STATE_CONNECTING) {
124ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                            Log.e(TAG, "Bad connection state: " + mConnState);
125ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        }
126ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    }
127ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
1289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                mClientIf = clientIf;
129ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (status != GATT_SUCCESS) {
13033ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onConnectionStateChange(BluetoothGatt.this, GATT_FAILURE,
131ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                                                      BluetoothProfile.STATE_DISCONNECTED);
132ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    synchronized(mStateLock) {
133ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        mConnState = CONN_STATE_IDLE;
134ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    }
135ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
136ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
1379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
138ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    mService.clientConnect(mClientIf, mDevice.getAddress(),
139b88fa824ab6337684de9aa8437c4952df4f1a75eGanesh Ganapathi Batta                                           !mAutoConnect, mTransport); // autoConnect is inverse of "isDirect"
140ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                } catch (RemoteException e) {
141ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    Log.e(TAG,"",e);
1429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
1439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
1449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
1469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Client connection state changed
1479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
1489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
1499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onClientConnectionState(int status, int clientIf,
1509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                boolean connected, String address) {
1519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onClientConnectionState() - status=" + status
1529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                 + " clientIf=" + clientIf + " device=" + address);
153ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
154ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
155ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
156ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                int profileState = connected ? BluetoothProfile.STATE_CONNECTED :
157ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                                               BluetoothProfile.STATE_DISCONNECTED;
1589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
15933ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onConnectionStateChange(BluetoothGatt.this, status, profileState);
1609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
1610998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
1629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
163ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie
164ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                synchronized(mStateLock) {
165ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    if (connected) {
166ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        mConnState = CONN_STATE_CONNECTED;
167ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    } else {
168ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        mConnState = CONN_STATE_IDLE;
169ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    }
170ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
171cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
172cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                synchronized(mDeviceBusy) {
173cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                    mDeviceBusy = false;
174cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                }
1759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
1769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
1789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Callback reporting an LE scan result.
1799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
1809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
1819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onScanResult(String address, int rssi, byte[] advData) {
182ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                // no op
1839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
1849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
1869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * A new GATT service has been discovered.
1879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * The service is added to the internal list and the search
1889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * continues.
1899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
1909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
1919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onGetService(String address, int srvcType,
1929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                     int srvcInstId, ParcelUuid srvcUuid) {
1939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onGetService() - Device=" + address + " UUID=" + srvcUuid);
194ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
195ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
196ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
197ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                mServices.add(new BluetoothGattService(mDevice, srvcUuid.getUuid(),
1989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                       srvcInstId, srvcType));
1999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
2009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
2029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * An included service has been found durig GATT discovery.
2039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * The included service is added to the respective parent.
2049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
2059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
2069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onGetIncludedService(String address, int srvcType,
2079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                             int srvcInstId, ParcelUuid srvcUuid,
2089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                             int inclSrvcType, int inclSrvcInstId,
2099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                             ParcelUuid inclSrvcUuid) {
2109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onGetIncludedService() - Device=" + address
2119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    + " UUID=" + srvcUuid + " Included=" + inclSrvcUuid);
2129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
213ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
214ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
215ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
216ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice,
2179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        srvcUuid.getUuid(), srvcInstId, srvcType);
218ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService includedService = getService(mDevice,
2199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        inclSrvcUuid.getUuid(), inclSrvcInstId, inclSrvcType);
2209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service != null && includedService != null) {
2229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    service.addIncludedService(includedService);
2239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
2249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
2259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
2279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * A new GATT characteristic has been discovered.
2289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Add the new characteristic to the relevant service and continue
2299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * the remote device inspection.
2309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
2319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
2329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onGetCharacteristic(String address, int srvcType,
2339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int srvcInstId, ParcelUuid srvcUuid,
2349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charInstId, ParcelUuid charUuid,
2359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charProps) {
2369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onGetCharacteristic() - Device=" + address + " UUID=" +
2379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                               charUuid);
2389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
239ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
240ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
241ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
242ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
2439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                          srvcInstId, srvcType);
2449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service != null) {
2459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    service.addCharacteristic(new BluetoothGattCharacteristic(
2469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                           service, charUuid.getUuid(), charInstId, charProps, 0));
2479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
2489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
2499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
2519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * A new GATT descriptor has been discovered.
2529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Finally, add the descriptor to the related characteristic.
2539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * This should conclude the remote device update.
2549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
2559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
2569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onGetDescriptor(String address, int srvcType,
2579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int srvcInstId, ParcelUuid srvcUuid,
2589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charInstId, ParcelUuid charUuid,
25925b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                             int descrInstId, ParcelUuid descUuid) {
2609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onGetDescriptor() - Device=" + address + " UUID=" + descUuid);
2619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
262ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
263ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
264ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
265ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
2669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                          srvcInstId, srvcType);
2679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service == null) return;
2689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic characteristic = service.getCharacteristic(
2709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    charUuid.getUuid());
2719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (characteristic == null) return;
2729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                characteristic.addDescriptor(new BluetoothGattDescriptor(
27425b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                    characteristic, descUuid.getUuid(), descrInstId, 0));
2759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
2769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
2789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Remote search has been completed.
2799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * The internal object structure should now reflect the state
2809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * of the remote device database. Let the application know that
2819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * we are done at this point.
2829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
2839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
2849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onSearchComplete(String address, int status) {
2859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onSearchComplete() = Device=" + address + " Status=" + status);
286ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
287ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
288ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
2899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
29033ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onServicesDiscovered(BluetoothGatt.this, status);
2919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
2920998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
2939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
2949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
2959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
2979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Remote characteristic has been read.
2989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Updates the internal value.
2999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
3009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
3019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onCharacteristicRead(String address, int status, int srvcType,
3029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int srvcInstId, ParcelUuid srvcUuid,
3039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charInstId, ParcelUuid charUuid, byte[] value) {
3049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onCharacteristicRead() - Device=" + address
3059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            + " UUID=" + charUuid + " Status=" + status);
3069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
307ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
308ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
309ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
310cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
311cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                synchronized(mDeviceBusy) {
312cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                    mDeviceBusy = false;
313cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                }
314cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
3159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if ((status == GATT_INSUFFICIENT_AUTHENTICATION
3169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  || status == GATT_INSUFFICIENT_ENCRYPTION)
3179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  && mAuthRetry == false) {
3189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    try {
3199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mAuthRetry = true;
3209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mService.readCharacteristic(mClientIf, address,
3219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            srvcType, srvcInstId, srvcUuid,
3229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            charInstId, charUuid, AUTHENTICATION_MITM);
3239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        return;
3249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    } catch (RemoteException e) {
3259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        Log.e(TAG,"",e);
3269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    }
3279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
3289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                mAuthRetry = false;
3309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
331ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
3329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                          srvcInstId, srvcType);
3339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service == null) return;
3349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic characteristic = service.getCharacteristic(
3369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        charUuid.getUuid(), charInstId);
3379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (characteristic == null) return;
3389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (status == 0) characteristic.setValue(value);
3409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
34233ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onCharacteristicRead(BluetoothGatt.this, characteristic, status);
3439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
3440998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
3459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
3469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
3479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
3499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Characteristic has been written to the remote device.
3509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Let the app know how we did...
3519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
3529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
3539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onCharacteristicWrite(String address, int status, int srvcType,
3549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int srvcInstId, ParcelUuid srvcUuid,
3559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charInstId, ParcelUuid charUuid) {
3569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onCharacteristicWrite() - Device=" + address
3579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            + " UUID=" + charUuid + " Status=" + status);
3589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
359ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
360ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
361ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
362cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
363cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                synchronized(mDeviceBusy) {
364cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                    mDeviceBusy = false;
365cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                }
366cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
367ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
3689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                          srvcInstId, srvcType);
3699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service == null) return;
3709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic characteristic = service.getCharacteristic(
3729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        charUuid.getUuid(), charInstId);
3739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (characteristic == null) return;
3749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if ((status == GATT_INSUFFICIENT_AUTHENTICATION
3769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  || status == GATT_INSUFFICIENT_ENCRYPTION)
3779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  && mAuthRetry == false) {
3789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    try {
3799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mAuthRetry = true;
3809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mService.writeCharacteristic(mClientIf, address,
3819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            srvcType, srvcInstId, srvcUuid, charInstId, charUuid,
3829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            characteristic.getWriteType(), AUTHENTICATION_MITM,
3839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            characteristic.getValue());
3849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        return;
3859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    } catch (RemoteException e) {
3869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        Log.e(TAG,"",e);
3879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    }
3889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
3899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                mAuthRetry = false;
3919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
39333ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onCharacteristicWrite(BluetoothGatt.this, characteristic, status);
3949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
3950998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
3969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
3979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
3989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
4009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Remote characteristic has been updated.
4019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Updates the internal value.
4029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
4039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
4049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onNotify(String address, int srvcType,
4059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int srvcInstId, ParcelUuid srvcUuid,
4069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charInstId, ParcelUuid charUuid,
4079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             byte[] value) {
4089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onNotify() - Device=" + address + " UUID=" + charUuid);
4099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
410ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
411ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
412ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
413ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
4149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                          srvcInstId, srvcType);
4159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service == null) return;
4169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic characteristic = service.getCharacteristic(
4189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        charUuid.getUuid(), charInstId);
4199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (characteristic == null) return;
4209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                characteristic.setValue(value);
4229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
42433ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onCharacteristicChanged(BluetoothGatt.this, characteristic);
4259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
4260998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
4279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
4289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
4299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
4319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Descriptor has been read.
4329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
4339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
4349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onDescriptorRead(String address, int status, int srvcType,
4359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int srvcInstId, ParcelUuid srvcUuid,
4369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charInstId, ParcelUuid charUuid,
43725b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                             int descrInstId, ParcelUuid descrUuid,
43825b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                             byte[] value) {
4399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onDescriptorRead() - Device=" + address + " UUID=" + charUuid);
4409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
441ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
442ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
443ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
444cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
445cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                synchronized(mDeviceBusy) {
446cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                    mDeviceBusy = false;
447cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                }
448cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
449ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
4509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                          srvcInstId, srvcType);
4519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service == null) return;
4529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic characteristic = service.getCharacteristic(
4549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        charUuid.getUuid(), charInstId);
4559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (characteristic == null) return;
4569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
45825b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                        descrUuid.getUuid(), descrInstId);
4599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (descriptor == null) return;
4609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (status == 0) descriptor.setValue(value);
4629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if ((status == GATT_INSUFFICIENT_AUTHENTICATION
4649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  || status == GATT_INSUFFICIENT_ENCRYPTION)
4659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  && mAuthRetry == false) {
4669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    try {
4679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mAuthRetry = true;
4689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mService.readDescriptor(mClientIf, address,
4699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            srvcType, srvcInstId, srvcUuid, charInstId, charUuid,
47025b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                            descrInstId, descrUuid, AUTHENTICATION_MITM);
4719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    } catch (RemoteException e) {
4729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        Log.e(TAG,"",e);
4739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    }
4749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
4759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                mAuthRetry = true;
4779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
47933ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onDescriptorRead(BluetoothGatt.this, descriptor, status);
4809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
4810998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
4829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
4839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
4849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
4869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Descriptor write operation complete.
4879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
4889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
4899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onDescriptorWrite(String address, int status, int srvcType,
4909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int srvcInstId, ParcelUuid srvcUuid,
4919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charInstId, ParcelUuid charUuid,
49225b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                             int descrInstId, ParcelUuid descrUuid) {
4939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onDescriptorWrite() - Device=" + address + " UUID=" + charUuid);
4949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
495ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
496ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
497ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
498cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
499cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                synchronized(mDeviceBusy) {
500cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                    mDeviceBusy = false;
501cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                }
502cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
503ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
5049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                          srvcInstId, srvcType);
5059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service == null) return;
5069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic characteristic = service.getCharacteristic(
5089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        charUuid.getUuid(), charInstId);
5099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (characteristic == null) return;
5109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
51225b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                        descrUuid.getUuid(), descrInstId);
5139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (descriptor == null) return;
5149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if ((status == GATT_INSUFFICIENT_AUTHENTICATION
5169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  || status == GATT_INSUFFICIENT_ENCRYPTION)
5179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  && mAuthRetry == false) {
5189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    try {
5199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mAuthRetry = true;
5209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mService.writeDescriptor(mClientIf, address,
5219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            srvcType, srvcInstId, srvcUuid, charInstId, charUuid,
52225b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                            descrInstId, descrUuid, characteristic.getWriteType(),
5239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            AUTHENTICATION_MITM, descriptor.getValue());
5249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    } catch (RemoteException e) {
5259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        Log.e(TAG,"",e);
5269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    }
5279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
5289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                mAuthRetry = false;
5309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
53233ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onDescriptorWrite(BluetoothGatt.this, descriptor, status);
5339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
5340998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
5359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
5369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
5379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
5399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Prepared write transaction completed (or aborted)
5409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
5419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
5429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onExecuteWrite(String address, int status) {
5439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onExecuteWrite() - Device=" + address
5449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    + " status=" + status);
545ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
546ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
547ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
548cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
549cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                synchronized(mDeviceBusy) {
550cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                    mDeviceBusy = false;
551cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                }
552cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
5539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
55433ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onReliableWriteCompleted(BluetoothGatt.this, status);
5559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
5560998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
5579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
5589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
5599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
5619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Remote device RSSI has been read
5629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
5639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
5649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onReadRemoteRssi(String address, int rssi, int status) {
5659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onReadRemoteRssi() - Device=" + address +
5669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            " rssi=" + rssi + " status=" + status);
567ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
568ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
569ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
5709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
57133ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onReadRemoteRssi(BluetoothGatt.this, rssi, status);
5729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
5730998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
5749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
5759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
576f305589f22f3fa1d73f2e29009d382c9a4f5c293Wei Wang
577f305589f22f3fa1d73f2e29009d382c9a4f5c293Wei Wang            /**
578f305589f22f3fa1d73f2e29009d382c9a4f5c293Wei Wang             * Advertise state change callback
579f305589f22f3fa1d73f2e29009d382c9a4f5c293Wei Wang             * @hide
580f305589f22f3fa1d73f2e29009d382c9a4f5c293Wei Wang             */
581f305589f22f3fa1d73f2e29009d382c9a4f5c293Wei Wang            public void onAdvertiseStateChange(int state, int status) {
582f305589f22f3fa1d73f2e29009d382c9a4f5c293Wei Wang                if (DBG) Log.d(TAG, "onAdvertiseStateChange() - state = "
583f305589f22f3fa1d73f2e29009d382c9a4f5c293Wei Wang                        + state + " status=" + status);
584580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach	    }
585580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach
586580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach            /**
587580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach             * Callback invoked when the MTU for a given connection changes
588580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach             * @hide
589580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach             */
590580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach            public void onConfigureMTU(String address, int mtu, int status) {
591580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                if (DBG) Log.d(TAG, "onConfigureMTU() - Device=" + address +
592580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                            " mtu=" + mtu + " status=" + status);
593580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                if (!address.equals(mDevice.getAddress())) {
594580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                    return;
595580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                }
596580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                try {
597580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                    mCallback.onConfigureMTU(BluetoothGatt.this, mtu, status);
598580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                } catch (Exception ex) {
599580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                    Log.w(TAG, "Unhandled exception in callback", ex);
600580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                }
601f305589f22f3fa1d73f2e29009d382c9a4f5c293Wei Wang            }
6029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        };
6039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
604b88fa824ab6337684de9aa8437c4952df4f1a75eGanesh Ganapathi Batta    /*package*/ BluetoothGatt(Context context, IBluetoothGatt iGatt, BluetoothDevice device,
605b88fa824ab6337684de9aa8437c4952df4f1a75eGanesh Ganapathi Batta                                int transport) {
6069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        mContext = context;
607ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        mService = iGatt;
608ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        mDevice = device;
609b88fa824ab6337684de9aa8437c4952df4f1a75eGanesh Ganapathi Batta        mTransport = transport;
6109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        mServices = new ArrayList<BluetoothGattService>();
6119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
612ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        mConnState = CONN_STATE_IDLE;
6139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
6149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
61633ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * Close this Bluetooth GATT client.
617b30f91e38c19f6728d836293446d4b9c76705e7fMatthew Xie     *
618b30f91e38c19f6728d836293446d4b9c76705e7fMatthew Xie     * Application should call this method as early as possible after it is done with
619b30f91e38c19f6728d836293446d4b9c76705e7fMatthew Xie     * this GATT client.
6209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
62133ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    public void close() {
6229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "close()");
6239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        unregisterApp();
62533ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie        mConnState = CONN_STATE_CLOSED;
6269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
6279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
6299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Returns a service by UUID, instance and type.
6309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @hide
6319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
6329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /*package*/ BluetoothGattService getService(BluetoothDevice device, UUID uuid,
6339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                int instanceId, int type) {
6349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        for(BluetoothGattService svc : mServices) {
6359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            if (svc.getDevice().equals(device) &&
6369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                svc.getType() == type &&
6379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                svc.getInstanceId() == instanceId &&
6389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                svc.getUuid().equals(uuid)) {
6399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                return svc;
6409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
6419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
6429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return null;
6439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
6449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
647ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Register an application callback to start using GATT.
6489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
649ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * <p>This is an asynchronous call. The callback {@link BluetoothGattCallback#onAppRegistered}
650ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * is used to notify success or failure if the function returns true.
6519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
6529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
6539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
654ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @param callback GATT callback handler that will receive asynchronous callbacks.
655ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @return If true, the callback will be called to notify success or failure,
656ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     *         false on immediate error
6579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
658ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private boolean registerApp(BluetoothGattCallback callback) {
6599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "registerApp()");
6609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null) return false;
6619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        mCallback = callback;
6639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        UUID uuid = UUID.randomUUID();
6649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "registerApp() - UUID=" + uuid);
6659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
6679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.registerClient(new ParcelUuid(uuid), mBluetoothGattCallback);
6689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
6699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
6709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
6719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
6729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
6749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
6759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
6779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Unregister the current application and callbacks.
6789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
679ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private void unregisterApp() {
6809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "unregisterApp() - mClientIf=" + mClientIf);
6819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return;
6829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
6849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mCallback = null;
6859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.unregisterClient(mClientIf);
6869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mClientIf = 0;
6879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
6889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
6899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
6909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
6919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
693ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Initiate a connection to a Bluetooth GATT capable device.
6949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
6959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>The connection may not be established right away, but will be
6969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * completed when the remote device is available. A
6979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * {@link BluetoothGattCallback#onConnectionStateChange} callback will be
6989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * invoked when the connection state changes as a result of this function.
6999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
7009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>The autoConnect paramter determines whether to actively connect to
7019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * the remote device, or rather passively scan and finalize the connection
7029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * when the remote device is in range/available. Generally, the first ever
7039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * connection to a device should be direct (autoConnect set to false) and
7049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * subsequent connections to known devices should be invoked with the
705ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * autoConnect parameter set to true.
7069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
7079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
7089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
7099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param device Remote device to connect to
7109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param autoConnect Whether to directly connect to the remote device (false)
7119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *                    or to automatically connect as soon as the remote
7129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *                    device becomes available (true).
7139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the connection attempt was initiated successfully
7149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
715ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    /*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallback callback) {
716ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "connect() - device: " + mDevice.getAddress() + ", auto: " + autoConnect);
717ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        synchronized(mStateLock) {
718ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            if (mConnState != CONN_STATE_IDLE) {
719ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                throw new IllegalStateException("Not idle");
720ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            }
721ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mConnState = CONN_STATE_CONNECTING;
722ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        }
723ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (!registerApp(callback)) {
724ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            synchronized(mStateLock) {
725ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                mConnState = CONN_STATE_IDLE;
726ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            }
727ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            Log.e(TAG, "Failed to register callback");
7289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
7299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
7309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
731ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        // the connection will continue after successful callback registration
732ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        mAutoConnect = autoConnect;
7339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
7349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
7359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
7369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
7379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Disconnects an established connection, or cancels a connection attempt
7389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * currently in progress.
7399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
7409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
7419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
742ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public void disconnect() {
743ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "cancelOpen() - device: " + mDevice.getAddress());
7449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return;
7459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
7469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
747ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.clientDisconnect(mClientIf, mDevice.getAddress());
7489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
7499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
7509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
75133ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    }
75233ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie
75333ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    /**
75433ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * Connect back to remote device.
75533ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     *
75633ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * <p>This method is used to re-connect to a remote device after the
75733ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * connection has been dropped. If the device is not in range, the
75833ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * re-connection will be triggered once the device is back in range.
75933ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     *
76033ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * @return true, if the connection attempt was initiated successfully
76133ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     */
76233ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    public boolean connect() {
76333ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie        try {
76433ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie            mService.clientConnect(mClientIf, mDevice.getAddress(),
765b88fa824ab6337684de9aa8437c4952df4f1a75eGanesh Ganapathi Batta                                   false, mTransport); // autoConnect is inverse of "isDirect"
76633ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie            return true;
76733ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie        } catch (RemoteException e) {
76833ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie            Log.e(TAG,"",e);
76933ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie            return false;
77033ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie        }
77133ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    }
77233ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie
77333ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    /**
77433ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * Return the remote bluetooth device this GATT client targets to
77533ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     *
77633ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * @return remote bluetooth device
77733ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     */
77833ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    public BluetoothDevice getDevice() {
77933ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie        return mDevice;
7809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
7819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
7829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
7839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Discovers services offered by a remote device as well as their
7849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * characteristics and descriptors.
7859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
7869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>This is an asynchronous operation. Once service discovery is completed,
7879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * the {@link BluetoothGattCallback#onServicesDiscovered} callback is
7889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * triggered. If the discovery was successful, the remote services can be
7899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * retrieved using the {@link #getServices} function.
7909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
7919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
7929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
7939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the remote service discovery has been started
7949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
795ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public boolean discoverServices() {
796ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "discoverServices() - device: " + mDevice.getAddress());
7979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
7989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
7999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        mServices.clear();
8009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
802ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.discoverServices(mClientIf, mDevice.getAddress());
8039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
8049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
8059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
8069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
8079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
8099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
8109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
8129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Returns a list of GATT services offered by the remote device.
8139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>This function requires that service discovery has been completed
8159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * for the given device.
8169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
8189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return List of services on the remote device. Returns an empty list
8209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *         if service discovery has not yet been performed.
8219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
822ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public List<BluetoothGattService> getServices() {
8239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        List<BluetoothGattService> result =
8249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ArrayList<BluetoothGattService>();
8259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        for (BluetoothGattService service : mServices) {
827ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            if (service.getDevice().equals(mDevice)) {
8289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                result.add(service);
8299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
8309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
8319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return result;
8339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
8349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
8369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Returns a {@link BluetoothGattService}, if the requested UUID is
8379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * supported by the remote device.
8389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>This function requires that service discovery has been completed
8409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * for the given device.
8419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>If multiple instances of the same service (as identified by UUID)
8439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * exist, the first instance of the service is returned.
8449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
8469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param uuid UUID of the requested service
8489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return BluetoothGattService if supported, or null if the requested
8499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *         service is not offered by the remote device.
8509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
851ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public BluetoothGattService getService(UUID uuid) {
8529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        for (BluetoothGattService service : mServices) {
853ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            if (service.getDevice().equals(mDevice) &&
8549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                service.getUuid().equals(uuid)) {
8559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                return service;
8569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
8579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
8589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return null;
8609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
8619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
8639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Reads the requested characteristic from the associated remote device.
8649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>This is an asynchronous operation. The result of the read operation
8669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * is reported by the {@link BluetoothGattCallback#onCharacteristicRead}
8679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * callback.
8689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
8709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param characteristic Characteristic to read from the remote device
8729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the read operation was initiated successfully
8739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
8749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public boolean readCharacteristic(BluetoothGattCharacteristic characteristic) {
8759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if ((characteristic.getProperties() &
8769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic.PROPERTY_READ) == 0) return false;
8779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "readCharacteristic() - uuid: " + characteristic.getUuid());
8799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
8809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattService service = characteristic.getService();
8829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (service == null) return false;
8839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothDevice device = service.getDevice();
8859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (device == null) return false;
8869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
887cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        synchronized(mDeviceBusy) {
888cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            if (mDeviceBusy) return false;
889cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = true;
890cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        }
891cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
8929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
8939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.readCharacteristic(mClientIf, device.getAddress(),
8949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                service.getType(), service.getInstanceId(),
8959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ParcelUuid(service.getUuid()), characteristic.getInstanceId(),
8969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ParcelUuid(characteristic.getUuid()), AUTHENTICATION_NONE);
8979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
8989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
899cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = false;
9009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
9019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
9029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
9049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
9059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
907ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Writes a given characteristic and its values to the associated remote device.
9089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Once the write operation has been completed, the
9109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * {@link BluetoothGattCallback#onCharacteristicWrite} callback is invoked,
9119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * reporting the result of the operation.
9129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
9149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param characteristic Characteristic to write on the remote device
9169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the write operation was initiated successfully
9179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
9189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public boolean writeCharacteristic(BluetoothGattCharacteristic characteristic) {
9199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE) == 0
9209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            && (characteristic.getProperties() &
9219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) == 0) return false;
9229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "writeCharacteristic() - uuid: " + characteristic.getUuid());
9249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
9259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattService service = characteristic.getService();
9279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (service == null) return false;
9289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothDevice device = service.getDevice();
9309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (device == null) return false;
9319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
932cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        synchronized(mDeviceBusy) {
933cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            if (mDeviceBusy) return false;
934cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = true;
935cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        }
936cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
9379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
9389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.writeCharacteristic(mClientIf, device.getAddress(),
9399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                service.getType(), service.getInstanceId(),
9409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ParcelUuid(service.getUuid()), characteristic.getInstanceId(),
9419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ParcelUuid(characteristic.getUuid()),
9429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                characteristic.getWriteType(), AUTHENTICATION_NONE,
9439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                characteristic.getValue());
9449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
9459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
946cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = false;
9479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
9489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
9499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
9519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
9529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
9549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Reads the value for a given descriptor from the associated remote device.
9559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Once the read operation has been completed, the
9579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * {@link BluetoothGattCallback#onDescriptorRead} callback is
9589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * triggered, signaling the result of the operation.
9599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
9619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param descriptor Descriptor value to read from the remote device
9639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the read operation was initiated successfully
9649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
9659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public boolean readDescriptor(BluetoothGattDescriptor descriptor) {
9669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "readDescriptor() - uuid: " + descriptor.getUuid());
9679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
9689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic();
9709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (characteristic == null) return false;
9719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattService service = characteristic.getService();
9739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (service == null) return false;
9749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothDevice device = service.getDevice();
9769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (device == null) return false;
9779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
978cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        synchronized(mDeviceBusy) {
979cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            if (mDeviceBusy) return false;
980cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = true;
981cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        }
982cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
9839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
98425b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach            mService.readDescriptor(mClientIf, device.getAddress(), service.getType(),
98525b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                service.getInstanceId(), new ParcelUuid(service.getUuid()),
98625b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                characteristic.getInstanceId(), new ParcelUuid(characteristic.getUuid()),
98725b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                descriptor.getInstanceId(), new ParcelUuid(descriptor.getUuid()),
98825b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                AUTHENTICATION_NONE);
9899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
9909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
991cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = false;
9929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
9939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
9949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
9969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
9979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
9999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Write the value of a given descriptor to the associated remote device.
10009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>A {@link BluetoothGattCallback#onDescriptorWrite} callback is
10029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * triggered to report the result of the write operation.
10039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
10059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param descriptor Descriptor to write to the associated remote device
10079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the write operation was initiated successfully
10089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
10099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public boolean writeDescriptor(BluetoothGattDescriptor descriptor) {
10109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "writeDescriptor() - uuid: " + descriptor.getUuid());
10119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
10129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic();
10149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (characteristic == null) return false;
10159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattService service = characteristic.getService();
10179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (service == null) return false;
10189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothDevice device = service.getDevice();
10209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (device == null) return false;
10219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1022cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        synchronized(mDeviceBusy) {
1023cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            if (mDeviceBusy) return false;
1024cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = true;
1025cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        }
1026cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
10279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
102825b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach            mService.writeDescriptor(mClientIf, device.getAddress(), service.getType(),
102925b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                service.getInstanceId(), new ParcelUuid(service.getUuid()),
103025b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                characteristic.getInstanceId(), new ParcelUuid(characteristic.getUuid()),
103125b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                descriptor.getInstanceId(), new ParcelUuid(descriptor.getUuid()),
10329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                characteristic.getWriteType(), AUTHENTICATION_NONE,
10339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                descriptor.getValue());
10349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
10359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
1036cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = false;
10379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
10389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
10399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
10419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
10429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
10449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Initiates a reliable write transaction for a given remote device.
10459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Once a reliable write transaction has been initiated, all calls
10479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * to {@link #writeCharacteristic} are sent to the remote device for
10489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * verification and queued up for atomic execution. The application will
10499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * receive an {@link BluetoothGattCallback#onCharacteristicWrite} callback
10509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * in response to every {@link #writeCharacteristic} call and is responsible
10519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * for verifying if the value has been transmitted accurately.
10529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>After all characteristics have been queued up and verified,
10549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * {@link #executeReliableWrite} will execute all writes. If a characteristic
10559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * was not written correctly, calling {@link #abortReliableWrite} will
10569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * cancel the current transaction without commiting any values on the
10579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * remote device.
10589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
10609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the reliable write transaction has been initiated
10629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1063ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public boolean beginReliableWrite() {
1064ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "beginReliableWrite() - device: " + mDevice.getAddress());
10659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
10669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
1068ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.beginReliableWrite(mClientIf, mDevice.getAddress());
10699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
10709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
10719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
10729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
10739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
10759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
10769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
10789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Executes a reliable write transaction for a given remote device.
10799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>This function will commit all queued up characteristic write
10819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * operations for a given remote device.
10829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>A {@link BluetoothGattCallback#onReliableWriteCompleted} callback is
10849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * invoked to indicate whether the transaction has been executed correctly.
10859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
10879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the request to execute the transaction has been sent
10899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1090ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public boolean executeReliableWrite() {
1091ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "executeReliableWrite() - device: " + mDevice.getAddress());
10929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
10939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1094cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        synchronized(mDeviceBusy) {
1095cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            if (mDeviceBusy) return false;
1096cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = true;
1097cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        }
1098cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
10999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
1100ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.endReliableWrite(mClientIf, mDevice.getAddress(), true);
11019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
11029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
1103cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = false;
11049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
11059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
11069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
11089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
11099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
11119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Cancels a reliable write transaction for a given device.
11129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Calling this function will discard all queued characteristic write
11149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * operations for a given remote device.
11159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
11179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
111848f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du    public void abortReliableWrite() {
1119ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "abortReliableWrite() - device: " + mDevice.getAddress());
11209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return;
11219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
1123ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.endReliableWrite(mClientIf, mDevice.getAddress(), false);
11249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
11259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
11269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
11279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
11289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1130b7b7d7a05c164a56dd4155de4e84fc25ba706728John Du     * @deprecated Use {@link #abortReliableWrite()}
113148f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du     */
113248f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du    public void abortReliableWrite(BluetoothDevice mDevice) {
113348f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du        abortReliableWrite();
113448f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du    }
113548f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du
113648f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du    /**
11379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Enable or disable notifications/indications for a given characteristic.
11389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Once notifications are enabled for a characteristic, a
11409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * {@link BluetoothGattCallback#onCharacteristicChanged} callback will be
11419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * triggered if the remote device indicates that the given characteristic
11429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * has changed.
11439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
11459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param characteristic The characteristic for which to enable notifications
11479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param enable Set to true to enable notifications/indications
11489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the requested notification status was set successfully
11499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
11509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public boolean setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
11519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                              boolean enable) {
11529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "setCharacteristicNotification() - uuid: " + characteristic.getUuid()
11539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                         + " enable: " + enable);
11549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
11559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattService service = characteristic.getService();
11579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (service == null) return false;
11589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothDevice device = service.getDevice();
11609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (device == null) return false;
11619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
11639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.registerForNotification(mClientIf, device.getAddress(),
11649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                service.getType(), service.getInstanceId(),
11659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ParcelUuid(service.getUuid()), characteristic.getInstanceId(),
11669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ParcelUuid(characteristic.getUuid()),
11679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                enable);
11689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
11699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
11709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
11719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
11729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
11749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
11759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
11779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Clears the internal cache and forces a refresh of the services from the
11789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * remote device.
11799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @hide
11809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1181ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public boolean refresh() {
1182ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "refresh() - device: " + mDevice.getAddress());
11839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
11849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
1186ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.refreshDevice(mClientIf, mDevice.getAddress());
11879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
11889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
11899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
11909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
11919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
11939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
11949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
11969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Read the RSSI for a connected remote device.
11979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>The {@link BluetoothGattCallback#onReadRemoteRssi} callback will be
11999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * invoked when the RSSI value has been read.
12009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
12019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
12029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
12039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the RSSI value has been requested successfully
12049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1205ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public boolean readRemoteRssi() {
1206ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "readRssi() - device: " + mDevice.getAddress());
12079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
12089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
1210ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.readRemoteRssi(mClientIf, mDevice.getAddress());
12119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
12129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
12139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
12149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
12159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
12179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
12189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1220580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     * Configure the MTU used for a given connection.
1221580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     *
1222580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     * <p>When performing a write request operation (write without response),
1223580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     * the data sent is truncated to the MTU size. This function may be used
1224580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     * to request a larget MTU size to be able to send more data at once.
1225580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     *
1226580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     * <p>A {@link BluetoothGattCallback#onConfigureMTU} callback will indicate
1227580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     * whether this operation was successful.
1228580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     *
1229580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
1230580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     *
1231580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     * @return true, if the new MTU value has been requested successfully
1232580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     * @hide
1233580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     */
1234580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach    public boolean configureMTU(int mtu) {
1235580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach        if (DBG) Log.d(TAG, "configureMTU() - device: " + mDevice.getAddress()
1236580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                            + " mtu: " + mtu);
1237580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach        if (mService == null || mClientIf == 0) return false;
1238580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach
1239580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach        try {
1240580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach            mService.configureMTU(mClientIf, mDevice.getAddress(), mtu);
1241580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach        } catch (RemoteException e) {
1242580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach            Log.e(TAG,"",e);
1243580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach            return false;
1244580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach        }
1245580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach
1246580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach        return true;
1247580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach    }
1248580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach
1249580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach    /**
1250ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
1251ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * with {@link BluetoothProfile#GATT} as argument
12529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
1253ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @throws UnsupportedOperationException
12549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
12559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    @Override
12569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public int getConnectionState(BluetoothDevice device) {
1257ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        throw new UnsupportedOperationException("Use BluetoothManager#getConnectionState instead.");
12589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
12599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1261ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
1262ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * with {@link BluetoothProfile#GATT} as argument
12639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
1264ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @throws UnsupportedOperationException
12659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
12669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    @Override
12679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public List<BluetoothDevice> getConnectedDevices() {
1268ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        throw new UnsupportedOperationException
1269ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            ("Use BluetoothManager#getConnectedDevices instead.");
12709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
12719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1273ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Not supported - please use
1274ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * {@link BluetoothManager#getDevicesMatchingConnectionStates(int, int[])}
1275ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * with {@link BluetoothProfile#GATT} as first argument
12769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
1277ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @throws UnsupportedOperationException
12789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
12799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    @Override
12809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
1281ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        throw new UnsupportedOperationException
1282ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            ("Use BluetoothManager#getDevicesMatchingConnectionStates instead.");
12839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
12849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta}
1285