BluetoothGatt.java revision 9fb1791e1a6859bfb14006a6d101cdecc88f3f95
19908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta/*
29908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Copyright (C) 2013 The Android Open Source Project
39908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta *
49908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Licensed under the Apache License, Version 2.0 (the "License");
59908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * you may not use this file except in compliance with the License.
69908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * You may obtain a copy of the License at
79908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta *
89908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta *      http://www.apache.org/licenses/LICENSE-2.0
99908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta *
109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Unless required by applicable law or agreed to in writing, software
119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * distributed under the License is distributed on an "AS IS" BASIS,
129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * See the License for the specific language governing permissions and
149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * limitations under the License.
159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */
169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battapackage android.bluetooth;
189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
199fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wangimport android.bluetooth.le.ScanResult;
209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.content.Context;
219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.os.ParcelUuid;
229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.os.RemoteException;
239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.util.Log;
249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport java.util.ArrayList;
269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport java.util.List;
279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport java.util.UUID;
289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta/**
30ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * Public API for the Bluetooth GATT Profile.
319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta *
32ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * <p>This class provides Bluetooth GATT functionality to enable communication
339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * with Bluetooth Smart or Smart Ready devices.
349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta *
359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>To connect to a remote peripheral device, create a {@link BluetoothGattCallback}
3633ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie * and call {@link BluetoothDevice#connectGatt} to get a instance of this class.
37ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * GATT capable devices can be discovered using the Bluetooth device discovery or BLE
38ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * scan process.
399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */
409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battapublic final class BluetoothGatt implements BluetoothProfile {
419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private static final String TAG = "BluetoothGatt";
429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private static final boolean DBG = true;
43ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private static final boolean VDBG = true;
449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
45ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private final Context mContext;
469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private IBluetoothGatt mService;
479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private BluetoothGattCallback mCallback;
489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private int mClientIf;
499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private boolean mAuthRetry = false;
50ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private BluetoothDevice mDevice;
51ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private boolean mAutoConnect;
52ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private int mConnState;
53ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private final Object mStateLock = new Object();
54cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach    private Boolean mDeviceBusy = false;
55b88fa824ab6337684de9aa8437c4952df4f1a75eGanesh Ganapathi Batta    private int mTransport;
56ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie
57ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private static final int CONN_STATE_IDLE = 0;
58ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private static final int CONN_STATE_CONNECTING = 1;
59ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private static final int CONN_STATE_CONNECTED = 2;
60ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private static final int CONN_STATE_DISCONNECTING = 3;
6133ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    private static final int CONN_STATE_CLOSED = 4;
629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private List<BluetoothGattService> mServices;
649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
65ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    /** A GATT operation completed successfully */
669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_SUCCESS = 0;
679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
68ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    /** GATT read operation is not permitted */
699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_READ_NOT_PERMITTED = 0x2;
709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
71ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    /** GATT write operation is not permitted */
729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_WRITE_NOT_PERMITTED = 0x3;
739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /** Insufficient authentication for a given operation */
759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_INSUFFICIENT_AUTHENTICATION = 0x5;
769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /** The given request is not supported */
789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_REQUEST_NOT_SUPPORTED = 0x6;
799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /** Insufficient encryption for a given operation */
819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_INSUFFICIENT_ENCRYPTION = 0xf;
829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /** A read or write operation was requested with an invalid offset */
849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_INVALID_OFFSET = 0x7;
859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /** A write operation exceeds the maximum length of the attribute */
879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_INVALID_ATTRIBUTE_LENGTH = 0xd;
889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
89fad672672429e27de3c487a428264c2a2d48dd0fAndre Eisenbach    /** A remote device connection is congested.
90fad672672429e27de3c487a428264c2a2d48dd0fAndre Eisenbach     * @hide
91fad672672429e27de3c487a428264c2a2d48dd0fAndre Eisenbach     */
92dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach    public static final int GATT_CONNECTION_CONGESTED = 0x8f;
93dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach
9490ca807f7b2037499112d1c49c4b0793cc780540Matthew Xie    /** A GATT operation failed, errors other than the above */
9590ca807f7b2037499112d1c49c4b0793cc780540Matthew Xie    public static final int GATT_FAILURE = 0x101;
9690ca807f7b2037499112d1c49c4b0793cc780540Matthew Xie
979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * No authentication required.
999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @hide
1009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /*package*/ static final int AUTHENTICATION_NONE = 0;
1029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Authentication requested; no man-in-the-middle protection required.
1059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @hide
1069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /*package*/ static final int AUTHENTICATION_NO_MITM = 1;
1089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Authentication with man-in-the-middle protection requested.
1119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @hide
1129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /*package*/ static final int AUTHENTICATION_MITM = 2;
1149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Bluetooth GATT interface callbacks
1179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private final IBluetoothGattCallback mBluetoothGattCallback =
1199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        new IBluetoothGattCallback.Stub() {
1209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
1219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Application interface registered - app is ready to go
1229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
1239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
1249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onClientRegistered(int status, int clientIf) {
1259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onClientRegistered() - status=" + status
1269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    + " clientIf=" + clientIf);
127ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (VDBG) {
128ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    synchronized(mStateLock) {
129ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        if (mConnState != CONN_STATE_CONNECTING) {
130ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                            Log.e(TAG, "Bad connection state: " + mConnState);
131ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        }
132ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    }
133ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
1349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                mClientIf = clientIf;
135ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (status != GATT_SUCCESS) {
13633ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onConnectionStateChange(BluetoothGatt.this, GATT_FAILURE,
137ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                                                      BluetoothProfile.STATE_DISCONNECTED);
138ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    synchronized(mStateLock) {
139ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        mConnState = CONN_STATE_IDLE;
140ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    }
141ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
142ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
1439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
144ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    mService.clientConnect(mClientIf, mDevice.getAddress(),
145b88fa824ab6337684de9aa8437c4952df4f1a75eGanesh Ganapathi Batta                                           !mAutoConnect, mTransport); // autoConnect is inverse of "isDirect"
146ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                } catch (RemoteException e) {
147ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    Log.e(TAG,"",e);
1489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
1499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
1509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
1529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Client connection state changed
1539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
1549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
1559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onClientConnectionState(int status, int clientIf,
1569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                boolean connected, String address) {
1579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onClientConnectionState() - status=" + status
1589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                 + " clientIf=" + clientIf + " device=" + address);
159ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
160ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
161ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
162ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                int profileState = connected ? BluetoothProfile.STATE_CONNECTED :
163ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                                               BluetoothProfile.STATE_DISCONNECTED;
1649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
16533ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onConnectionStateChange(BluetoothGatt.this, status, profileState);
1669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
1670998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
1689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
169ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie
170ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                synchronized(mStateLock) {
171ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    if (connected) {
172ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        mConnState = CONN_STATE_CONNECTED;
173ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    } else {
174ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        mConnState = CONN_STATE_IDLE;
175ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    }
176ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
177cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
178cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                synchronized(mDeviceBusy) {
179cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                    mDeviceBusy = false;
180cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                }
1819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
1829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
1849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Callback reporting an LE scan result.
1859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
1869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
1879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onScanResult(String address, int rssi, byte[] advData) {
188ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                // no op
1899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
1909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
1929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * A new GATT service has been discovered.
1939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * The service is added to the internal list and the search
1949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * continues.
1959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
1969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
1979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onGetService(String address, int srvcType,
1989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                     int srvcInstId, ParcelUuid srvcUuid) {
1999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onGetService() - Device=" + address + " UUID=" + srvcUuid);
200ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
201ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
202ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
203ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                mServices.add(new BluetoothGattService(mDevice, srvcUuid.getUuid(),
2049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                       srvcInstId, srvcType));
2059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
2069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
2089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * An included service has been found durig GATT discovery.
2099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * The included service is added to the respective parent.
2109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
2119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
2129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onGetIncludedService(String address, int srvcType,
2139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                             int srvcInstId, ParcelUuid srvcUuid,
2149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                             int inclSrvcType, int inclSrvcInstId,
2159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                             ParcelUuid inclSrvcUuid) {
2169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onGetIncludedService() - Device=" + address
2179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    + " UUID=" + srvcUuid + " Included=" + inclSrvcUuid);
2189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
219ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
220ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
221ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
222ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice,
2239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        srvcUuid.getUuid(), srvcInstId, srvcType);
224ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService includedService = getService(mDevice,
2259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        inclSrvcUuid.getUuid(), inclSrvcInstId, inclSrvcType);
2269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service != null && includedService != null) {
2289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    service.addIncludedService(includedService);
2299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
2309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
2319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
2339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * A new GATT characteristic has been discovered.
2349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Add the new characteristic to the relevant service and continue
2359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * the remote device inspection.
2369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
2379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
2389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onGetCharacteristic(String address, int srvcType,
2399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int srvcInstId, ParcelUuid srvcUuid,
2409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charInstId, ParcelUuid charUuid,
2419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charProps) {
2429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onGetCharacteristic() - Device=" + address + " UUID=" +
2439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                               charUuid);
2449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
245ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
246ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
247ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
248ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
2499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                          srvcInstId, srvcType);
2509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service != null) {
2519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    service.addCharacteristic(new BluetoothGattCharacteristic(
2529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                           service, charUuid.getUuid(), charInstId, charProps, 0));
2539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
2549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
2559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
2579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * A new GATT descriptor has been discovered.
2589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Finally, add the descriptor to the related characteristic.
2599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * This should conclude the remote device update.
2609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
2619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
2629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onGetDescriptor(String address, int srvcType,
2639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int srvcInstId, ParcelUuid srvcUuid,
2649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charInstId, ParcelUuid charUuid,
26525b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                             int descrInstId, ParcelUuid descUuid) {
2669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onGetDescriptor() - Device=" + address + " UUID=" + descUuid);
2679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
268ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
269ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
270ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
271ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
2729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                          srvcInstId, srvcType);
2739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service == null) return;
2749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic characteristic = service.getCharacteristic(
2762975c683bc43582a7dcf4e25501649ad3e566707Mike J. Chen                    charUuid.getUuid(), charInstId);
2779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (characteristic == null) return;
2789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                characteristic.addDescriptor(new BluetoothGattDescriptor(
28025b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                    characteristic, descUuid.getUuid(), descrInstId, 0));
2819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
2829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
2849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Remote search has been completed.
2859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * The internal object structure should now reflect the state
2869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * of the remote device database. Let the application know that
2879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * we are done at this point.
2889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
2899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
2909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onSearchComplete(String address, int status) {
2919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onSearchComplete() = Device=" + address + " Status=" + status);
292ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
293ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
294ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
2959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
29633ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onServicesDiscovered(BluetoothGatt.this, status);
2979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
2980998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
2999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
3009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
3019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
3039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Remote characteristic has been read.
3049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Updates the internal value.
3059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
3069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
3079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onCharacteristicRead(String address, int status, int srvcType,
3089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int srvcInstId, ParcelUuid srvcUuid,
3099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charInstId, ParcelUuid charUuid, byte[] value) {
3109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onCharacteristicRead() - Device=" + address
3119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            + " UUID=" + charUuid + " Status=" + status);
3129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
313ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
314ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
315ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
316cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
317cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                synchronized(mDeviceBusy) {
318cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                    mDeviceBusy = false;
319cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                }
320cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
3219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if ((status == GATT_INSUFFICIENT_AUTHENTICATION
3229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  || status == GATT_INSUFFICIENT_ENCRYPTION)
3239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  && mAuthRetry == false) {
3249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    try {
3259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mAuthRetry = true;
3269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mService.readCharacteristic(mClientIf, address,
3279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            srvcType, srvcInstId, srvcUuid,
3289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            charInstId, charUuid, AUTHENTICATION_MITM);
3299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        return;
3309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    } catch (RemoteException e) {
3319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        Log.e(TAG,"",e);
3329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    }
3339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
3349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                mAuthRetry = false;
3369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
337ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
3389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                          srvcInstId, srvcType);
3399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service == null) return;
3409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic characteristic = service.getCharacteristic(
3429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        charUuid.getUuid(), charInstId);
3439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (characteristic == null) return;
3449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (status == 0) characteristic.setValue(value);
3469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
34833ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onCharacteristicRead(BluetoothGatt.this, characteristic, status);
3499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
3500998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
3519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
3529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
3539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
3559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Characteristic has been written to the remote device.
3569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Let the app know how we did...
3579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
3589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
3599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onCharacteristicWrite(String address, int status, int srvcType,
3609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int srvcInstId, ParcelUuid srvcUuid,
3619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charInstId, ParcelUuid charUuid) {
3629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onCharacteristicWrite() - Device=" + address
3639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            + " UUID=" + charUuid + " Status=" + status);
3649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
365ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
366ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
367ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
368cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
369cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                synchronized(mDeviceBusy) {
370cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                    mDeviceBusy = false;
371cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                }
372cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
373ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
3749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                          srvcInstId, srvcType);
3759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service == null) return;
3769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic characteristic = service.getCharacteristic(
3789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        charUuid.getUuid(), charInstId);
3799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (characteristic == null) return;
3809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if ((status == GATT_INSUFFICIENT_AUTHENTICATION
3829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  || status == GATT_INSUFFICIENT_ENCRYPTION)
3839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  && mAuthRetry == false) {
3849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    try {
3859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mAuthRetry = true;
3869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mService.writeCharacteristic(mClientIf, address,
3879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            srvcType, srvcInstId, srvcUuid, charInstId, charUuid,
3889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            characteristic.getWriteType(), AUTHENTICATION_MITM,
3899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            characteristic.getValue());
3909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        return;
3919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    } catch (RemoteException e) {
3929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        Log.e(TAG,"",e);
3939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    }
3949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
3959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                mAuthRetry = false;
3979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
39933ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onCharacteristicWrite(BluetoothGatt.this, characteristic, status);
4009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
4010998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
4029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
4039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
4049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
4069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Remote characteristic has been updated.
4079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Updates the internal value.
4089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
4099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
4109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onNotify(String address, int srvcType,
4119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int srvcInstId, ParcelUuid srvcUuid,
4129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charInstId, ParcelUuid charUuid,
4139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             byte[] value) {
4149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onNotify() - Device=" + address + " UUID=" + charUuid);
4159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
416ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
417ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
418ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
419ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
4209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                          srvcInstId, srvcType);
4219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service == null) return;
4229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic characteristic = service.getCharacteristic(
4249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        charUuid.getUuid(), charInstId);
4259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (characteristic == null) return;
4269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                characteristic.setValue(value);
4289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
43033ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onCharacteristicChanged(BluetoothGatt.this, characteristic);
4319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
4320998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
4339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
4349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
4359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
4379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Descriptor has been read.
4389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
4399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
4409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onDescriptorRead(String address, int status, int srvcType,
4419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int srvcInstId, ParcelUuid srvcUuid,
4429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charInstId, ParcelUuid charUuid,
44325b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                             int descrInstId, ParcelUuid descrUuid,
44425b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                             byte[] value) {
4459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onDescriptorRead() - Device=" + address + " UUID=" + charUuid);
4469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
447ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
448ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
449ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
450cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
451cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                synchronized(mDeviceBusy) {
452cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                    mDeviceBusy = false;
453cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                }
454cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
455ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
4569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                          srvcInstId, srvcType);
4579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service == null) return;
4589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic characteristic = service.getCharacteristic(
4609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        charUuid.getUuid(), charInstId);
4619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (characteristic == null) return;
4629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
46425b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                        descrUuid.getUuid(), descrInstId);
4659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (descriptor == null) return;
4669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (status == 0) descriptor.setValue(value);
4689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if ((status == GATT_INSUFFICIENT_AUTHENTICATION
4709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  || status == GATT_INSUFFICIENT_ENCRYPTION)
4719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  && mAuthRetry == false) {
4729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    try {
4739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mAuthRetry = true;
4749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mService.readDescriptor(mClientIf, address,
4759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            srvcType, srvcInstId, srvcUuid, charInstId, charUuid,
47625b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                            descrInstId, descrUuid, AUTHENTICATION_MITM);
4779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    } catch (RemoteException e) {
4789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        Log.e(TAG,"",e);
4799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    }
4809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
4819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                mAuthRetry = true;
4839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
48533ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onDescriptorRead(BluetoothGatt.this, descriptor, status);
4869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
4870998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
4889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
4899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
4909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
4929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Descriptor write operation complete.
4939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
4949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
4959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onDescriptorWrite(String address, int status, int srvcType,
4969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int srvcInstId, ParcelUuid srvcUuid,
4979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charInstId, ParcelUuid charUuid,
49825b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                             int descrInstId, ParcelUuid descrUuid) {
4999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onDescriptorWrite() - Device=" + address + " UUID=" + charUuid);
5009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
501ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
502ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
503ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
504cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
505cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                synchronized(mDeviceBusy) {
506cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                    mDeviceBusy = false;
507cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                }
508cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
509ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
5109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                          srvcInstId, srvcType);
5119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service == null) return;
5129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic characteristic = service.getCharacteristic(
5149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        charUuid.getUuid(), charInstId);
5159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (characteristic == null) return;
5169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
51825b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                        descrUuid.getUuid(), descrInstId);
5199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (descriptor == null) return;
5209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if ((status == GATT_INSUFFICIENT_AUTHENTICATION
5229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  || status == GATT_INSUFFICIENT_ENCRYPTION)
5239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  && mAuthRetry == false) {
5249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    try {
5259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mAuthRetry = true;
5269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mService.writeDescriptor(mClientIf, address,
5279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            srvcType, srvcInstId, srvcUuid, charInstId, charUuid,
52825b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                            descrInstId, descrUuid, characteristic.getWriteType(),
5299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            AUTHENTICATION_MITM, descriptor.getValue());
5309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    } catch (RemoteException e) {
5319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        Log.e(TAG,"",e);
5329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    }
5339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
5349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                mAuthRetry = false;
5369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
53833ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onDescriptorWrite(BluetoothGatt.this, descriptor, status);
5399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
5400998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
5419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
5429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
5439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
5459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Prepared write transaction completed (or aborted)
5469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
5479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
5489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onExecuteWrite(String address, int status) {
5499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onExecuteWrite() - Device=" + address
5509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    + " status=" + status);
551ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
552ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
553ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
554cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
555cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                synchronized(mDeviceBusy) {
556cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                    mDeviceBusy = false;
557cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach                }
558cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
5599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
56033ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onReliableWriteCompleted(BluetoothGatt.this, status);
5619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
5620998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
5639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
5649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
5659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
5679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Remote device RSSI has been read
5689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
5699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
5709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onReadRemoteRssi(String address, int rssi, int status) {
5719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onReadRemoteRssi() - Device=" + address +
5729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            " rssi=" + rssi + " status=" + status);
573ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
574ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
575ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
5769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
57733ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onReadRemoteRssi(BluetoothGatt.this, rssi, status);
5789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
5790998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
5809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
5819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
582f305589f22f3fa1d73f2e29009d382c9a4f5c293Wei Wang
583f305589f22f3fa1d73f2e29009d382c9a4f5c293Wei Wang            /**
584f305589f22f3fa1d73f2e29009d382c9a4f5c293Wei Wang             * Advertise state change callback
585f305589f22f3fa1d73f2e29009d382c9a4f5c293Wei Wang             * @hide
586f305589f22f3fa1d73f2e29009d382c9a4f5c293Wei Wang             */
587f305589f22f3fa1d73f2e29009d382c9a4f5c293Wei Wang            public void onAdvertiseStateChange(int state, int status) {
588f305589f22f3fa1d73f2e29009d382c9a4f5c293Wei Wang                if (DBG) Log.d(TAG, "onAdvertiseStateChange() - state = "
589f305589f22f3fa1d73f2e29009d382c9a4f5c293Wei Wang                        + state + " status=" + status);
590adf6aff5b03b1e3ca4636f9887225a7f906d1238Wei Wang            }
591adf6aff5b03b1e3ca4636f9887225a7f906d1238Wei Wang
592adf6aff5b03b1e3ca4636f9887225a7f906d1238Wei Wang            /**
593adf6aff5b03b1e3ca4636f9887225a7f906d1238Wei Wang             * @hide
594adf6aff5b03b1e3ca4636f9887225a7f906d1238Wei Wang             */
595adf6aff5b03b1e3ca4636f9887225a7f906d1238Wei Wang            @Override
596adf6aff5b03b1e3ca4636f9887225a7f906d1238Wei Wang            public void onMultiAdvertiseCallback(int status) {
597adf6aff5b03b1e3ca4636f9887225a7f906d1238Wei Wang                // no op.
598adf6aff5b03b1e3ca4636f9887225a7f906d1238Wei Wang            }
599580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach
600580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach            /**
601580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach             * Callback invoked when the MTU for a given connection changes
602580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach             * @hide
603580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach             */
604580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach            public void onConfigureMTU(String address, int mtu, int status) {
605580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                if (DBG) Log.d(TAG, "onConfigureMTU() - Device=" + address +
606580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                            " mtu=" + mtu + " status=" + status);
607580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                if (!address.equals(mDevice.getAddress())) {
608580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                    return;
609580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                }
610580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                try {
611580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                    mCallback.onConfigureMTU(BluetoothGatt.this, mtu, status);
612580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                } catch (Exception ex) {
613580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                    Log.w(TAG, "Unhandled exception in callback", ex);
614580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                }
615f305589f22f3fa1d73f2e29009d382c9a4f5c293Wei Wang            }
616dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach
617dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach            /**
618dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach             * Callback indicating the remote device connection is congested.
619dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach             * @hide
620dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach             */
621dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach            public void onConnectionCongested(String address, boolean congested) {
622dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach                if (DBG) Log.d(TAG, "onConnectionCongested() - Device=" + address
623dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach                        + " congested=" + congested);
624dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach                if (!address.equals(mDevice.getAddress())) return;
625dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach                try {
626dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach                    mCallback.onConnectionCongested(BluetoothGatt.this, congested);
627dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach                } catch (Exception ex) {
628dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach                    Log.w(TAG, "Unhandled exception in callback", ex);
629dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach                }
630dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach            }
6319fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang
6329fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang            @Override
6339fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang            public void onBatchScanResults(List<ScanResult> results) {
6349fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang                // no op
6359fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang            }
6369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        };
6379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
638b88fa824ab6337684de9aa8437c4952df4f1a75eGanesh Ganapathi Batta    /*package*/ BluetoothGatt(Context context, IBluetoothGatt iGatt, BluetoothDevice device,
639b88fa824ab6337684de9aa8437c4952df4f1a75eGanesh Ganapathi Batta                                int transport) {
6409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        mContext = context;
641ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        mService = iGatt;
642ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        mDevice = device;
643b88fa824ab6337684de9aa8437c4952df4f1a75eGanesh Ganapathi Batta        mTransport = transport;
6449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        mServices = new ArrayList<BluetoothGattService>();
6459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
646ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        mConnState = CONN_STATE_IDLE;
6479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
6489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
65033ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * Close this Bluetooth GATT client.
651b30f91e38c19f6728d836293446d4b9c76705e7fMatthew Xie     *
652b30f91e38c19f6728d836293446d4b9c76705e7fMatthew Xie     * Application should call this method as early as possible after it is done with
653b30f91e38c19f6728d836293446d4b9c76705e7fMatthew Xie     * this GATT client.
6549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
65533ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    public void close() {
6569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "close()");
6579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        unregisterApp();
65933ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie        mConnState = CONN_STATE_CLOSED;
6609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
6619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
6639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Returns a service by UUID, instance and type.
6649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @hide
6659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
6669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /*package*/ BluetoothGattService getService(BluetoothDevice device, UUID uuid,
6679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                int instanceId, int type) {
6689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        for(BluetoothGattService svc : mServices) {
6699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            if (svc.getDevice().equals(device) &&
6709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                svc.getType() == type &&
6719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                svc.getInstanceId() == instanceId &&
6729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                svc.getUuid().equals(uuid)) {
6739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                return svc;
6749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
6759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
6769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return null;
6779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
6789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
681ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Register an application callback to start using GATT.
6829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
683ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * <p>This is an asynchronous call. The callback {@link BluetoothGattCallback#onAppRegistered}
684ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * is used to notify success or failure if the function returns true.
6859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
6869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
6879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
688ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @param callback GATT callback handler that will receive asynchronous callbacks.
689ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @return If true, the callback will be called to notify success or failure,
690ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     *         false on immediate error
6919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
692ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private boolean registerApp(BluetoothGattCallback callback) {
6939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "registerApp()");
6949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null) return false;
6959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        mCallback = callback;
6979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        UUID uuid = UUID.randomUUID();
6989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "registerApp() - UUID=" + uuid);
6999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
7009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
7019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.registerClient(new ParcelUuid(uuid), mBluetoothGattCallback);
7029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
7039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
7049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
7059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
7069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
7079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
7089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
7099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
7109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
7119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Unregister the current application and callbacks.
7129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
713ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private void unregisterApp() {
7149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "unregisterApp() - mClientIf=" + mClientIf);
7159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return;
7169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
7179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
7189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mCallback = null;
7199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.unregisterClient(mClientIf);
7209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mClientIf = 0;
7219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
7229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
7239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
7249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
7259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
7269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
727ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Initiate a connection to a Bluetooth GATT capable device.
7289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
7299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>The connection may not be established right away, but will be
7309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * completed when the remote device is available. A
7319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * {@link BluetoothGattCallback#onConnectionStateChange} callback will be
7329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * invoked when the connection state changes as a result of this function.
7339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
7349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>The autoConnect paramter determines whether to actively connect to
7359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * the remote device, or rather passively scan and finalize the connection
7369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * when the remote device is in range/available. Generally, the first ever
7379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * connection to a device should be direct (autoConnect set to false) and
7389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * subsequent connections to known devices should be invoked with the
739ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * autoConnect parameter set to true.
7409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
7419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
7429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
7439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param device Remote device to connect to
7449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param autoConnect Whether to directly connect to the remote device (false)
7459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *                    or to automatically connect as soon as the remote
7469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *                    device becomes available (true).
7479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the connection attempt was initiated successfully
7489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
749ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    /*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallback callback) {
750ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "connect() - device: " + mDevice.getAddress() + ", auto: " + autoConnect);
751ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        synchronized(mStateLock) {
752ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            if (mConnState != CONN_STATE_IDLE) {
753ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                throw new IllegalStateException("Not idle");
754ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            }
755ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mConnState = CONN_STATE_CONNECTING;
756ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        }
757ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (!registerApp(callback)) {
758ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            synchronized(mStateLock) {
759ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                mConnState = CONN_STATE_IDLE;
760ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            }
761ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            Log.e(TAG, "Failed to register callback");
7629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
7639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
7649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
765ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        // the connection will continue after successful callback registration
766ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        mAutoConnect = autoConnect;
7679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
7689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
7699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
7709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
7719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Disconnects an established connection, or cancels a connection attempt
7729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * currently in progress.
7739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
7749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
7759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
776ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public void disconnect() {
777ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "cancelOpen() - device: " + mDevice.getAddress());
7789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return;
7799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
7809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
781ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.clientDisconnect(mClientIf, mDevice.getAddress());
7829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
7839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
7849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
78533ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    }
78633ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie
78733ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    /**
78833ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * Connect back to remote device.
78933ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     *
79033ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * <p>This method is used to re-connect to a remote device after the
79133ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * connection has been dropped. If the device is not in range, the
79233ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * re-connection will be triggered once the device is back in range.
79333ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     *
79433ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * @return true, if the connection attempt was initiated successfully
79533ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     */
79633ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    public boolean connect() {
79733ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie        try {
79833ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie            mService.clientConnect(mClientIf, mDevice.getAddress(),
799b88fa824ab6337684de9aa8437c4952df4f1a75eGanesh Ganapathi Batta                                   false, mTransport); // autoConnect is inverse of "isDirect"
80033ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie            return true;
80133ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie        } catch (RemoteException e) {
80233ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie            Log.e(TAG,"",e);
80333ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie            return false;
80433ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie        }
80533ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    }
80633ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie
80733ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    /**
80833ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * Return the remote bluetooth device this GATT client targets to
80933ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     *
81033ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * @return remote bluetooth device
81133ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     */
81233ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    public BluetoothDevice getDevice() {
81333ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie        return mDevice;
8149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
8159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
8179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Discovers services offered by a remote device as well as their
8189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * characteristics and descriptors.
8199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>This is an asynchronous operation. Once service discovery is completed,
8219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * the {@link BluetoothGattCallback#onServicesDiscovered} callback is
8229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * triggered. If the discovery was successful, the remote services can be
8239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * retrieved using the {@link #getServices} function.
8249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
8269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the remote service discovery has been started
8289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
829ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public boolean discoverServices() {
830ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "discoverServices() - device: " + mDevice.getAddress());
8319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
8329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        mServices.clear();
8349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
836ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.discoverServices(mClientIf, mDevice.getAddress());
8379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
8389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
8399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
8409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
8419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
8439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
8449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
8469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Returns a list of GATT services offered by the remote device.
8479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>This function requires that service discovery has been completed
8499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * for the given device.
8509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
8529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return List of services on the remote device. Returns an empty list
8549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *         if service discovery has not yet been performed.
8559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
856ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public List<BluetoothGattService> getServices() {
8579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        List<BluetoothGattService> result =
8589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ArrayList<BluetoothGattService>();
8599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        for (BluetoothGattService service : mServices) {
861ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            if (service.getDevice().equals(mDevice)) {
8629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                result.add(service);
8639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
8649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
8659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return result;
8679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
8689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
8709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Returns a {@link BluetoothGattService}, if the requested UUID is
8719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * supported by the remote device.
8729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>This function requires that service discovery has been completed
8749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * for the given device.
8759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>If multiple instances of the same service (as identified by UUID)
8779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * exist, the first instance of the service is returned.
8789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
8809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param uuid UUID of the requested service
8829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return BluetoothGattService if supported, or null if the requested
8839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *         service is not offered by the remote device.
8849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
885ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public BluetoothGattService getService(UUID uuid) {
8869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        for (BluetoothGattService service : mServices) {
887ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            if (service.getDevice().equals(mDevice) &&
8889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                service.getUuid().equals(uuid)) {
8899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                return service;
8909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
8919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
8929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return null;
8949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
8959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
8979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Reads the requested characteristic from the associated remote device.
8989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>This is an asynchronous operation. The result of the read operation
9009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * is reported by the {@link BluetoothGattCallback#onCharacteristicRead}
9019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * callback.
9029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
9049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param characteristic Characteristic to read from the remote device
9069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the read operation was initiated successfully
9079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
9089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public boolean readCharacteristic(BluetoothGattCharacteristic characteristic) {
9099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if ((characteristic.getProperties() &
9109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic.PROPERTY_READ) == 0) return false;
9119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "readCharacteristic() - uuid: " + characteristic.getUuid());
9139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
9149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattService service = characteristic.getService();
9169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (service == null) return false;
9179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothDevice device = service.getDevice();
9199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (device == null) return false;
9209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
921cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        synchronized(mDeviceBusy) {
922cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            if (mDeviceBusy) return false;
923cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = true;
924cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        }
925cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
9269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
9279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.readCharacteristic(mClientIf, device.getAddress(),
9289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                service.getType(), service.getInstanceId(),
9299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ParcelUuid(service.getUuid()), characteristic.getInstanceId(),
9309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ParcelUuid(characteristic.getUuid()), AUTHENTICATION_NONE);
9319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
9329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
933cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = false;
9349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
9359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
9369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
9389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
9399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
941ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Writes a given characteristic and its values to the associated remote device.
9429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Once the write operation has been completed, the
9449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * {@link BluetoothGattCallback#onCharacteristicWrite} callback is invoked,
9459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * reporting the result of the operation.
9469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
9489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param characteristic Characteristic to write on the remote device
9509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the write operation was initiated successfully
9519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
9529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public boolean writeCharacteristic(BluetoothGattCharacteristic characteristic) {
9539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE) == 0
9549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            && (characteristic.getProperties() &
9559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) == 0) return false;
9569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "writeCharacteristic() - uuid: " + characteristic.getUuid());
9589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
9599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattService service = characteristic.getService();
9619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (service == null) return false;
9629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothDevice device = service.getDevice();
9649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (device == null) return false;
9659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
966cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        synchronized(mDeviceBusy) {
967cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            if (mDeviceBusy) return false;
968cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = true;
969cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        }
970cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
9719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
9729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.writeCharacteristic(mClientIf, device.getAddress(),
9739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                service.getType(), service.getInstanceId(),
9749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ParcelUuid(service.getUuid()), characteristic.getInstanceId(),
9759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ParcelUuid(characteristic.getUuid()),
9769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                characteristic.getWriteType(), AUTHENTICATION_NONE,
9779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                characteristic.getValue());
9789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
9799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
980cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = false;
9819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
9829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
9839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
9859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
9869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
9889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Reads the value for a given descriptor from the associated remote device.
9899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Once the read operation has been completed, the
9919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * {@link BluetoothGattCallback#onDescriptorRead} callback is
9929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * triggered, signaling the result of the operation.
9939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
9959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param descriptor Descriptor value to read from the remote device
9979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the read operation was initiated successfully
9989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
9999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public boolean readDescriptor(BluetoothGattDescriptor descriptor) {
10009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "readDescriptor() - uuid: " + descriptor.getUuid());
10019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
10029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic();
10049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (characteristic == null) return false;
10059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattService service = characteristic.getService();
10079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (service == null) return false;
10089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothDevice device = service.getDevice();
10109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (device == null) return false;
10119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1012cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        synchronized(mDeviceBusy) {
1013cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            if (mDeviceBusy) return false;
1014cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = true;
1015cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        }
1016cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
10179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
101825b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach            mService.readDescriptor(mClientIf, device.getAddress(), service.getType(),
101925b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                service.getInstanceId(), new ParcelUuid(service.getUuid()),
102025b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                characteristic.getInstanceId(), new ParcelUuid(characteristic.getUuid()),
102125b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                descriptor.getInstanceId(), new ParcelUuid(descriptor.getUuid()),
102225b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                AUTHENTICATION_NONE);
10239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
10249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
1025cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = false;
10269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
10279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
10289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
10309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
10319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
10339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Write the value of a given descriptor to the associated remote device.
10349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>A {@link BluetoothGattCallback#onDescriptorWrite} callback is
10369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * triggered to report the result of the write operation.
10379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
10399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param descriptor Descriptor to write to the associated remote device
10419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the write operation was initiated successfully
10429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
10439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public boolean writeDescriptor(BluetoothGattDescriptor descriptor) {
10449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "writeDescriptor() - uuid: " + descriptor.getUuid());
10459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
10469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic();
10489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (characteristic == null) return false;
10499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattService service = characteristic.getService();
10519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (service == null) return false;
10529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothDevice device = service.getDevice();
10549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (device == null) return false;
10559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1056cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        synchronized(mDeviceBusy) {
1057cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            if (mDeviceBusy) return false;
1058cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = true;
1059cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        }
1060cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
10619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
106225b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach            mService.writeDescriptor(mClientIf, device.getAddress(), service.getType(),
106325b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                service.getInstanceId(), new ParcelUuid(service.getUuid()),
106425b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                characteristic.getInstanceId(), new ParcelUuid(characteristic.getUuid()),
106525b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                descriptor.getInstanceId(), new ParcelUuid(descriptor.getUuid()),
10669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                characteristic.getWriteType(), AUTHENTICATION_NONE,
10679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                descriptor.getValue());
10689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
10699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
1070cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = false;
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     * Initiates a reliable write transaction for a given remote device.
10799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Once a reliable write transaction has been initiated, all calls
10819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * to {@link #writeCharacteristic} are sent to the remote device for
10829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * verification and queued up for atomic execution. The application will
10839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * receive an {@link BluetoothGattCallback#onCharacteristicWrite} callback
10849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * in response to every {@link #writeCharacteristic} call and is responsible
10859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * for verifying if the value has been transmitted accurately.
10869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>After all characteristics have been queued up and verified,
10889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * {@link #executeReliableWrite} will execute all writes. If a characteristic
10899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * was not written correctly, calling {@link #abortReliableWrite} will
10909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * cancel the current transaction without commiting any values on the
10919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * remote device.
10929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
10949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the reliable write transaction has been initiated
10969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1097ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public boolean beginReliableWrite() {
1098ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "beginReliableWrite() - device: " + mDevice.getAddress());
10999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
11009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
1102ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.beginReliableWrite(mClientIf, mDevice.getAddress());
11039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
11049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
11059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
11069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
11079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
11099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
11109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
11129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Executes a reliable write transaction for a given remote device.
11139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>This function will commit all queued up characteristic write
11159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * operations for a given remote device.
11169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>A {@link BluetoothGattCallback#onReliableWriteCompleted} callback is
11189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * invoked to indicate whether the transaction has been executed correctly.
11199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
11219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the request to execute the transaction has been sent
11239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1124ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public boolean executeReliableWrite() {
1125ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "executeReliableWrite() - device: " + mDevice.getAddress());
11269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
11279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1128cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        synchronized(mDeviceBusy) {
1129cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            if (mDeviceBusy) return false;
1130cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = true;
1131cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach        }
1132cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach
11339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
1134ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.endReliableWrite(mClientIf, mDevice.getAddress(), true);
11359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
11369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
1137cc68cc962d1c90aaa0cdf2fffa68810998717517Andre Eisenbach            mDeviceBusy = false;
11389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
11399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
11409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
11429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
11439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
11459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Cancels a reliable write transaction for a given device.
11469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Calling this function will discard all queued characteristic write
11489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * operations for a given remote device.
11499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
11519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
115248f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du    public void abortReliableWrite() {
1153ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "abortReliableWrite() - device: " + mDevice.getAddress());
11549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return;
11559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
1157ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.endReliableWrite(mClientIf, mDevice.getAddress(), false);
11589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
11599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
11609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
11619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
11629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1164b7b7d7a05c164a56dd4155de4e84fc25ba706728John Du     * @deprecated Use {@link #abortReliableWrite()}
116548f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du     */
116648f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du    public void abortReliableWrite(BluetoothDevice mDevice) {
116748f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du        abortReliableWrite();
116848f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du    }
116948f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du
117048f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du    /**
11719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Enable or disable notifications/indications for a given characteristic.
11729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Once notifications are enabled for a characteristic, a
11749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * {@link BluetoothGattCallback#onCharacteristicChanged} callback will be
11759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * triggered if the remote device indicates that the given characteristic
11769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * has changed.
11779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
11799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param characteristic The characteristic for which to enable notifications
11819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param enable Set to true to enable notifications/indications
11829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the requested notification status was set successfully
11839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
11849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public boolean setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
11859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                              boolean enable) {
11869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "setCharacteristicNotification() - uuid: " + characteristic.getUuid()
11879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                         + " enable: " + enable);
11889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
11899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattService service = characteristic.getService();
11919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (service == null) return false;
11929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothDevice device = service.getDevice();
11949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (device == null) return false;
11959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
11979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.registerForNotification(mClientIf, device.getAddress(),
11989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                service.getType(), service.getInstanceId(),
11999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ParcelUuid(service.getUuid()), characteristic.getInstanceId(),
12009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ParcelUuid(characteristic.getUuid()),
12019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                enable);
12029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
12039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
12049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
12059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
12069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
12089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
12099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
12119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Clears the internal cache and forces a refresh of the services from the
12129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * remote device.
12139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @hide
12149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1215ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public boolean refresh() {
1216ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "refresh() - device: " + mDevice.getAddress());
12179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
12189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
1220ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.refreshDevice(mClientIf, mDevice.getAddress());
12219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
12229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
12239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
12249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
12259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
12279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
12289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
12309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Read the RSSI for a connected remote device.
12319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
12329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>The {@link BluetoothGattCallback#onReadRemoteRssi} callback will be
12339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * invoked when the RSSI value has been read.
12349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
12359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
12369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
12379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the RSSI value has been requested successfully
12389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1239ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public boolean readRemoteRssi() {
1240ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "readRssi() - device: " + mDevice.getAddress());
12419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
12429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
1244ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.readRemoteRssi(mClientIf, mDevice.getAddress());
12459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
12469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
12479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
12489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
12499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
12519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
12529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1254580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     * Configure the MTU used for a given connection.
1255580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     *
1256580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     * <p>When performing a write request operation (write without response),
1257580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     * the data sent is truncated to the MTU size. This function may be used
1258580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     * to request a larget MTU size to be able to send more data at once.
1259580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     *
1260580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     * <p>A {@link BluetoothGattCallback#onConfigureMTU} callback will indicate
1261580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     * whether this operation was successful.
1262580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     *
1263580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
1264580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     *
1265580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     * @return true, if the new MTU value has been requested successfully
1266580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     * @hide
1267580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach     */
1268580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach    public boolean configureMTU(int mtu) {
1269580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach        if (DBG) Log.d(TAG, "configureMTU() - device: " + mDevice.getAddress()
1270580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach                            + " mtu: " + mtu);
1271580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach        if (mService == null || mClientIf == 0) return false;
1272580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach
1273580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach        try {
1274580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach            mService.configureMTU(mClientIf, mDevice.getAddress(), mtu);
1275580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach        } catch (RemoteException e) {
1276580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach            Log.e(TAG,"",e);
1277580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach            return false;
1278580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach        }
1279580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach
1280580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach        return true;
1281580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach    }
1282580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach
1283580b0a13028ed2187964735a5515d87900d241ceAndre Eisenbach    /**
1284ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
1285ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * with {@link BluetoothProfile#GATT} as argument
12869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
1287ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @throws UnsupportedOperationException
12889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
12899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    @Override
12909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public int getConnectionState(BluetoothDevice device) {
1291ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        throw new UnsupportedOperationException("Use BluetoothManager#getConnectionState instead.");
12929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
12939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1295ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
1296ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * with {@link BluetoothProfile#GATT} as argument
12979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
1298ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @throws UnsupportedOperationException
12999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
13009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    @Override
13019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public List<BluetoothDevice> getConnectedDevices() {
1302ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        throw new UnsupportedOperationException
1303ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            ("Use BluetoothManager#getConnectedDevices instead.");
13049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
13059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
13069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1307ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Not supported - please use
1308ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * {@link BluetoothManager#getDevicesMatchingConnectionStates(int, int[])}
1309ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * with {@link BluetoothProfile#GATT} as first argument
13109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
1311ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @throws UnsupportedOperationException
13129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
13139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    @Override
13149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
1315ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        throw new UnsupportedOperationException
1316ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            ("Use BluetoothManager#getDevicesMatchingConnectionStates instead.");
13179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
13189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta}
1319