19908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta/*
29908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Copyright (C) 2013 The Android Open Source Project
39908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta *
49908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Licensed under the Apache License, Version 2.0 (the "License");
59908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * you may not use this file except in compliance with the License.
69908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * You may obtain a copy of the License at
79908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta *
89908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta *      http://www.apache.org/licenses/LICENSE-2.0
99908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta *
109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Unless required by applicable law or agreed to in writing, software
119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * distributed under the License is distributed on an "AS IS" BASIS,
129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * See the License for the specific language governing permissions and
149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * limitations under the License.
159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */
169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battapackage android.bluetooth;
189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.bluetooth.BluetoothDevice;
209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.bluetooth.BluetoothProfile;
219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.bluetooth.BluetoothProfile.ServiceListener;
229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.bluetooth.IBluetoothManager;
239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.bluetooth.IBluetoothStateChangeCallback;
249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.content.ComponentName;
269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.content.Context;
279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.content.Intent;
289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.content.ServiceConnection;
299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.os.IBinder;
309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.os.ParcelUuid;
319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.os.RemoteException;
329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.os.ServiceManager;
339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.util.Log;
349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport java.util.ArrayList;
369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport java.util.List;
379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport java.util.UUID;
389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta/**
40ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * Public API for the Bluetooth GATT Profile.
419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta *
42ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * <p>This class provides Bluetooth GATT functionality to enable communication
439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * with Bluetooth Smart or Smart Ready devices.
449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta *
459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>To connect to a remote peripheral device, create a {@link BluetoothGattCallback}
4633ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie * and call {@link BluetoothDevice#connectGatt} to get a instance of this class.
47ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * GATT capable devices can be discovered using the Bluetooth device discovery or BLE
48ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * scan process.
499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */
509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battapublic final class BluetoothGatt implements BluetoothProfile {
519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private static final String TAG = "BluetoothGatt";
529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private static final boolean DBG = true;
53ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private static final boolean VDBG = true;
549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
55ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private final Context mContext;
569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private IBluetoothGatt mService;
579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private BluetoothGattCallback mCallback;
589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private int mClientIf;
599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private boolean mAuthRetry = false;
60ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private BluetoothDevice mDevice;
61ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private boolean mAutoConnect;
62ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private int mConnState;
63ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private final Object mStateLock = new Object();
64ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie
65ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private static final int CONN_STATE_IDLE = 0;
66ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private static final int CONN_STATE_CONNECTING = 1;
67ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private static final int CONN_STATE_CONNECTED = 2;
68ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private static final int CONN_STATE_DISCONNECTING = 3;
6933ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    private static final int CONN_STATE_CLOSED = 4;
709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private List<BluetoothGattService> mServices;
729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
73ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    /** A GATT operation completed successfully */
749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_SUCCESS = 0;
759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
76ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    /** GATT read operation is not permitted */
779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_READ_NOT_PERMITTED = 0x2;
789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
79ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    /** GATT write operation is not permitted */
809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_WRITE_NOT_PERMITTED = 0x3;
819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /** Insufficient authentication for a given operation */
839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_INSUFFICIENT_AUTHENTICATION = 0x5;
849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /** The given request is not supported */
869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_REQUEST_NOT_SUPPORTED = 0x6;
879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /** Insufficient encryption for a given operation */
899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_INSUFFICIENT_ENCRYPTION = 0xf;
909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /** A read or write operation was requested with an invalid offset */
929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_INVALID_OFFSET = 0x7;
939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /** A write operation exceeds the maximum length of the attribute */
959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public static final int GATT_INVALID_ATTRIBUTE_LENGTH = 0xd;
969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9790ca807f7b2037499112d1c49c4b0793cc780540Matthew Xie    /** A GATT operation failed, errors other than the above */
9890ca807f7b2037499112d1c49c4b0793cc780540Matthew Xie    public static final int GATT_FAILURE = 0x101;
9990ca807f7b2037499112d1c49c4b0793cc780540Matthew Xie
1009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * No authentication required.
1029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @hide
1039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /*package*/ static final int AUTHENTICATION_NONE = 0;
1059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Authentication requested; no man-in-the-middle protection required.
1089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @hide
1099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /*package*/ static final int AUTHENTICATION_NO_MITM = 1;
1119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Authentication with man-in-the-middle protection requested.
1149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @hide
1159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /*package*/ static final int AUTHENTICATION_MITM = 2;
1179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Bluetooth GATT interface callbacks
1209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private final IBluetoothGattCallback mBluetoothGattCallback =
1229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        new IBluetoothGattCallback.Stub() {
1239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
1249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Application interface registered - app is ready to go
1259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
1269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
1279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onClientRegistered(int status, int clientIf) {
1289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onClientRegistered() - status=" + status
1299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    + " clientIf=" + clientIf);
130ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (VDBG) {
131ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    synchronized(mStateLock) {
132ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        if (mConnState != CONN_STATE_CONNECTING) {
133ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                            Log.e(TAG, "Bad connection state: " + mConnState);
134ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        }
135ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    }
136ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
1379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                mClientIf = clientIf;
138ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (status != GATT_SUCCESS) {
13933ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onConnectionStateChange(BluetoothGatt.this, GATT_FAILURE,
140ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                                                      BluetoothProfile.STATE_DISCONNECTED);
141ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    synchronized(mStateLock) {
142ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        mConnState = CONN_STATE_IDLE;
143ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    }
144ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
145ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
1469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
147ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    mService.clientConnect(mClientIf, mDevice.getAddress(),
148ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                                           !mAutoConnect); // autoConnect is inverse of "isDirect"
149ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                } catch (RemoteException e) {
150ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    Log.e(TAG,"",e);
1519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
1529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
1539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
1559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Client connection state changed
1569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
1579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
1589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onClientConnectionState(int status, int clientIf,
1599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                boolean connected, String address) {
1609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onClientConnectionState() - status=" + status
1619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                 + " clientIf=" + clientIf + " device=" + address);
162ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
163ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
164ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
165ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                int profileState = connected ? BluetoothProfile.STATE_CONNECTED :
166ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                                               BluetoothProfile.STATE_DISCONNECTED;
1679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
16833ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onConnectionStateChange(BluetoothGatt.this, status, profileState);
1699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
1700998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
1719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
172ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie
173ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                synchronized(mStateLock) {
174ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    if (connected) {
175ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        mConnState = CONN_STATE_CONNECTED;
176ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    } else {
177ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        mConnState = CONN_STATE_IDLE;
178ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    }
179ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
1809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
1819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
1839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Callback reporting an LE scan result.
1849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
1859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
1869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onScanResult(String address, int rssi, byte[] advData) {
187ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                // no op
1889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
1899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
1919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * A new GATT service has been discovered.
1929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * The service is added to the internal list and the search
1939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * continues.
1949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
1959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
1969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onGetService(String address, int srvcType,
1979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                     int srvcInstId, ParcelUuid srvcUuid) {
1989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onGetService() - Device=" + address + " UUID=" + srvcUuid);
199ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
200ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
201ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
202ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                mServices.add(new BluetoothGattService(mDevice, srvcUuid.getUuid(),
2039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                       srvcInstId, srvcType));
2049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
2059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
2079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * An included service has been found durig GATT discovery.
2089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * The included service is added to the respective parent.
2099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
2109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
2119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onGetIncludedService(String address, int srvcType,
2129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                             int srvcInstId, ParcelUuid srvcUuid,
2139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                             int inclSrvcType, int inclSrvcInstId,
2149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                             ParcelUuid inclSrvcUuid) {
2159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onGetIncludedService() - Device=" + address
2169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    + " UUID=" + srvcUuid + " Included=" + inclSrvcUuid);
2179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
218ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
219ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
220ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
221ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice,
2229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        srvcUuid.getUuid(), srvcInstId, srvcType);
223ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService includedService = getService(mDevice,
2249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        inclSrvcUuid.getUuid(), inclSrvcInstId, inclSrvcType);
2259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service != null && includedService != null) {
2279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    service.addIncludedService(includedService);
2289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
2299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
2309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
2329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * A new GATT characteristic has been discovered.
2339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Add the new characteristic to the relevant service and continue
2349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * the remote device inspection.
2359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
2369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
2379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onGetCharacteristic(String address, int srvcType,
2389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int srvcInstId, ParcelUuid srvcUuid,
2399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charInstId, ParcelUuid charUuid,
2409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charProps) {
2419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onGetCharacteristic() - Device=" + address + " UUID=" +
2429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                               charUuid);
2439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
244ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
245ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
246ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
247ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
2489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                          srvcInstId, srvcType);
2499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service != null) {
2509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    service.addCharacteristic(new BluetoothGattCharacteristic(
2519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                           service, charUuid.getUuid(), charInstId, charProps, 0));
2529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
2539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
2549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
2569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * A new GATT descriptor has been discovered.
2579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Finally, add the descriptor to the related characteristic.
2589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * This should conclude the remote device update.
2599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
2609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
2619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onGetDescriptor(String address, int srvcType,
2629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int srvcInstId, ParcelUuid srvcUuid,
2639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charInstId, ParcelUuid charUuid,
26425b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                             int descrInstId, ParcelUuid descUuid) {
2659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onGetDescriptor() - Device=" + address + " UUID=" + descUuid);
2669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
267ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
268ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
269ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
270ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
2719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                          srvcInstId, srvcType);
2729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service == null) return;
2739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic characteristic = service.getCharacteristic(
2759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    charUuid.getUuid());
2769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (characteristic == null) return;
2779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                characteristic.addDescriptor(new BluetoothGattDescriptor(
27925b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                    characteristic, descUuid.getUuid(), descrInstId, 0));
2809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
2819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
2839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Remote search has been completed.
2849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * The internal object structure should now reflect the state
2859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * of the remote device database. Let the application know that
2869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * we are done at this point.
2879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
2889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
2899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onSearchComplete(String address, int status) {
2909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onSearchComplete() = Device=" + address + " Status=" + status);
291ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
292ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
293ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
2949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
29533ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onServicesDiscovered(BluetoothGatt.this, status);
2969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
2970998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
2989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
2999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
3009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
3029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Remote characteristic has been read.
3039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Updates the internal value.
3049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
3059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
3069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onCharacteristicRead(String address, int status, int srvcType,
3079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int srvcInstId, ParcelUuid srvcUuid,
3089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charInstId, ParcelUuid charUuid, byte[] value) {
3099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onCharacteristicRead() - Device=" + address
3109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            + " UUID=" + charUuid + " Status=" + status);
3119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
312ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
313ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
314ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
3159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if ((status == GATT_INSUFFICIENT_AUTHENTICATION
3169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  || status == GATT_INSUFFICIENT_ENCRYPTION)
3179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  && mAuthRetry == false) {
3189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    try {
3199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mAuthRetry = true;
3209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mService.readCharacteristic(mClientIf, address,
3219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            srvcType, srvcInstId, srvcUuid,
3229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            charInstId, charUuid, AUTHENTICATION_MITM);
3239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        return;
3249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    } catch (RemoteException e) {
3259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        Log.e(TAG,"",e);
3269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    }
3279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
3289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                mAuthRetry = false;
3309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
331ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
3329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                          srvcInstId, srvcType);
3339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service == null) return;
3349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic characteristic = service.getCharacteristic(
3369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        charUuid.getUuid(), charInstId);
3379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (characteristic == null) return;
3389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (status == 0) characteristic.setValue(value);
3409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
34233ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onCharacteristicRead(BluetoothGatt.this, characteristic, status);
3439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
3440998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
3459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
3469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
3479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
3499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Characteristic has been written to the remote device.
3509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Let the app know how we did...
3519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
3529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
3539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onCharacteristicWrite(String address, int status, int srvcType,
3549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int srvcInstId, ParcelUuid srvcUuid,
3559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charInstId, ParcelUuid charUuid) {
3569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onCharacteristicWrite() - Device=" + address
3579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            + " UUID=" + charUuid + " Status=" + status);
3589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
359ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
360ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
361ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
362ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
3639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                          srvcInstId, srvcType);
3649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service == null) return;
3659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic characteristic = service.getCharacteristic(
3679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        charUuid.getUuid(), charInstId);
3689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (characteristic == null) return;
3699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if ((status == GATT_INSUFFICIENT_AUTHENTICATION
3719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  || status == GATT_INSUFFICIENT_ENCRYPTION)
3729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  && mAuthRetry == false) {
3739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    try {
3749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mAuthRetry = true;
3759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mService.writeCharacteristic(mClientIf, address,
3769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            srvcType, srvcInstId, srvcUuid, charInstId, charUuid,
3779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            characteristic.getWriteType(), AUTHENTICATION_MITM,
3789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            characteristic.getValue());
3799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        return;
3809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    } catch (RemoteException e) {
3819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        Log.e(TAG,"",e);
3829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    }
3839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
3849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                mAuthRetry = false;
3869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
38833ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onCharacteristicWrite(BluetoothGatt.this, characteristic, status);
3899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
3900998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
3919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
3929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
3939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
3959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Remote characteristic has been updated.
3969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Updates the internal value.
3979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
3989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
3999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onNotify(String address, int srvcType,
4009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int srvcInstId, ParcelUuid srvcUuid,
4019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charInstId, ParcelUuid charUuid,
4029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             byte[] value) {
4039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onNotify() - Device=" + address + " UUID=" + charUuid);
4049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
405ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
406ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
407ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
408ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
4099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                          srvcInstId, srvcType);
4109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service == null) return;
4119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic characteristic = service.getCharacteristic(
4139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        charUuid.getUuid(), charInstId);
4149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (characteristic == null) return;
4159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                characteristic.setValue(value);
4179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
41933ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onCharacteristicChanged(BluetoothGatt.this, characteristic);
4209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
4210998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
4229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
4239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
4249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
4269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Descriptor has been read.
4279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
4289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
4299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onDescriptorRead(String address, int status, int srvcType,
4309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int srvcInstId, ParcelUuid srvcUuid,
4319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charInstId, ParcelUuid charUuid,
43225b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                             int descrInstId, ParcelUuid descrUuid,
43325b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                             byte[] value) {
4349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onDescriptorRead() - Device=" + address + " UUID=" + charUuid);
4359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
436ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
437ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
438ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
439ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
4409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                          srvcInstId, srvcType);
4419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service == null) return;
4429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic characteristic = service.getCharacteristic(
4449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        charUuid.getUuid(), charInstId);
4459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (characteristic == null) return;
4469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
44825b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                        descrUuid.getUuid(), descrInstId);
4499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (descriptor == null) return;
4509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (status == 0) descriptor.setValue(value);
4529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if ((status == GATT_INSUFFICIENT_AUTHENTICATION
4549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  || status == GATT_INSUFFICIENT_ENCRYPTION)
4559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  && mAuthRetry == false) {
4569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    try {
4579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mAuthRetry = true;
4589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mService.readDescriptor(mClientIf, address,
4599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            srvcType, srvcInstId, srvcUuid, charInstId, charUuid,
46025b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                            descrInstId, descrUuid, AUTHENTICATION_MITM);
4619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    } catch (RemoteException e) {
4629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        Log.e(TAG,"",e);
4639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    }
4649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
4659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                mAuthRetry = true;
4679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
46933ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onDescriptorRead(BluetoothGatt.this, descriptor, status);
4709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
4710998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
4729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
4739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
4749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
4769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Descriptor write operation complete.
4779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
4789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
4799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onDescriptorWrite(String address, int status, int srvcType,
4809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int srvcInstId, ParcelUuid srvcUuid,
4819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                             int charInstId, ParcelUuid charUuid,
48225b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                             int descrInstId, ParcelUuid descrUuid) {
4839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onDescriptorWrite() - Device=" + address + " UUID=" + charUuid);
4849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
485ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
486ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
487ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
488ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
4899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                          srvcInstId, srvcType);
4909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service == null) return;
4919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic characteristic = service.getCharacteristic(
4939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        charUuid.getUuid(), charInstId);
4949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (characteristic == null) return;
4959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
49725b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                        descrUuid.getUuid(), descrInstId);
4989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (descriptor == null) return;
4999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if ((status == GATT_INSUFFICIENT_AUTHENTICATION
5019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  || status == GATT_INSUFFICIENT_ENCRYPTION)
5029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                  && mAuthRetry == false) {
5039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    try {
5049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mAuthRetry = true;
5059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        mService.writeDescriptor(mClientIf, address,
5069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            srvcType, srvcInstId, srvcUuid, charInstId, charUuid,
50725b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                            descrInstId, descrUuid, characteristic.getWriteType(),
5089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            AUTHENTICATION_MITM, descriptor.getValue());
5099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    } catch (RemoteException e) {
5109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        Log.e(TAG,"",e);
5119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    }
5129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
5139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                mAuthRetry = false;
5159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
51733ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onDescriptorWrite(BluetoothGatt.this, descriptor, status);
5189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
5190998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
5209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
5219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
5229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
5249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Prepared write transaction completed (or aborted)
5259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
5269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
5279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onExecuteWrite(String address, int status) {
5289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onExecuteWrite() - Device=" + address
5299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    + " status=" + status);
530ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
531ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
532ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
5339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
53433ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onReliableWriteCompleted(BluetoothGatt.this, status);
5359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
5360998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
5379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
5389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
5399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
5419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Remote device RSSI has been read
5429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
5439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
5449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onReadRemoteRssi(String address, int rssi, int status) {
5459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onReadRemoteRssi() - Device=" + address +
5469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            " rssi=" + rssi + " status=" + status);
547ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                if (!address.equals(mDevice.getAddress())) {
548ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    return;
549ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                }
5509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
55133ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                    mCallback.onReadRemoteRssi(BluetoothGatt.this, rssi, status);
5529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
5530998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood                    Log.w(TAG, "Unhandled exception in callback", ex);
5549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
5559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
556f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach
557f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach            /**
558f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach             * Listen command status callback
559f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach             * @hide
560f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach             */
561f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach            public void onListen(int status) {
562f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach                if (DBG) Log.d(TAG, "onListen() - status=" + status);
563f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach            }
5649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        };
5659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
566ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    /*package*/ BluetoothGatt(Context context, IBluetoothGatt iGatt, BluetoothDevice device) {
5679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        mContext = context;
568ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        mService = iGatt;
569ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        mDevice = device;
5709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        mServices = new ArrayList<BluetoothGattService>();
5719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
572ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        mConnState = CONN_STATE_IDLE;
5739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
5749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
57633ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * Close this Bluetooth GATT client.
577b30f91e38c19f6728d836293446d4b9c76705e7fMatthew Xie     *
578b30f91e38c19f6728d836293446d4b9c76705e7fMatthew Xie     * Application should call this method as early as possible after it is done with
579b30f91e38c19f6728d836293446d4b9c76705e7fMatthew Xie     * this GATT client.
5809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
58133ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    public void close() {
5829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "close()");
5839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        unregisterApp();
58533ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie        mConnState = CONN_STATE_CLOSED;
5869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
5879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
5899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Returns a service by UUID, instance and type.
5909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @hide
5919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
5929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /*package*/ BluetoothGattService getService(BluetoothDevice device, UUID uuid,
5939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                int instanceId, int type) {
5949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        for(BluetoothGattService svc : mServices) {
5959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            if (svc.getDevice().equals(device) &&
5969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                svc.getType() == type &&
5979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                svc.getInstanceId() == instanceId &&
5989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                svc.getUuid().equals(uuid)) {
5999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                return svc;
6009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
6019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
6029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return null;
6039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
6049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
607ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Register an application callback to start using GATT.
6089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
609ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * <p>This is an asynchronous call. The callback {@link BluetoothGattCallback#onAppRegistered}
610ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * is used to notify success or failure if the function returns true.
6119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
6129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
6139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
614ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @param callback GATT callback handler that will receive asynchronous callbacks.
615ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @return If true, the callback will be called to notify success or failure,
616ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     *         false on immediate error
6179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
618ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private boolean registerApp(BluetoothGattCallback callback) {
6199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "registerApp()");
6209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null) return false;
6219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        mCallback = callback;
6239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        UUID uuid = UUID.randomUUID();
6249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "registerApp() - UUID=" + uuid);
6259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
6279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.registerClient(new ParcelUuid(uuid), mBluetoothGattCallback);
6289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
6299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
6309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
6319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
6329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
6349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
6359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
6379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Unregister the current application and callbacks.
6389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
639ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private void unregisterApp() {
6409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "unregisterApp() - mClientIf=" + mClientIf);
6419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return;
6429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
6449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mCallback = null;
6459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.unregisterClient(mClientIf);
6469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mClientIf = 0;
6479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
6489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
6499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
6509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
6519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
653ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Initiate a connection to a Bluetooth GATT capable device.
6549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
6559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>The connection may not be established right away, but will be
6569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * completed when the remote device is available. A
6579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * {@link BluetoothGattCallback#onConnectionStateChange} callback will be
6589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * invoked when the connection state changes as a result of this function.
6599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
6609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>The autoConnect paramter determines whether to actively connect to
6619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * the remote device, or rather passively scan and finalize the connection
6629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * when the remote device is in range/available. Generally, the first ever
6639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * connection to a device should be direct (autoConnect set to false) and
6649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * subsequent connections to known devices should be invoked with the
665ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * autoConnect parameter set to true.
6669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
6679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
6689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
6699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param device Remote device to connect to
6709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param autoConnect Whether to directly connect to the remote device (false)
6719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *                    or to automatically connect as soon as the remote
6729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *                    device becomes available (true).
6739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the connection attempt was initiated successfully
6749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
675ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    /*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallback callback) {
676ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "connect() - device: " + mDevice.getAddress() + ", auto: " + autoConnect);
677ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        synchronized(mStateLock) {
678ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            if (mConnState != CONN_STATE_IDLE) {
679ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                throw new IllegalStateException("Not idle");
680ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            }
681ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mConnState = CONN_STATE_CONNECTING;
682ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        }
683ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (!registerApp(callback)) {
684ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            synchronized(mStateLock) {
685ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                mConnState = CONN_STATE_IDLE;
686ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            }
687ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            Log.e(TAG, "Failed to register callback");
6889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
6899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
6909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
691ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        // the connection will continue after successful callback registration
692ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        mAutoConnect = autoConnect;
6939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
6949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
6959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
696f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach   /**
697f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach     * Starts or stops sending of advertisement packages to listen for connection
698f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach     * requests from a central devices.
699f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach     *
700f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
701f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach     *
702f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach     * @param start Start or stop advertising
703f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach     */
704f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach    /*package*/ void listen(boolean start) {
705c5470778a4fa8cc22e234fdcfe93fca39de63d36Matthew Xie        if (mContext == null || !mContext.getResources().
706c5470778a4fa8cc22e234fdcfe93fca39de63d36Matthew Xie            getBoolean(com.android.internal.R.bool.config_bluetooth_le_peripheral_mode_supported)) {
707c5470778a4fa8cc22e234fdcfe93fca39de63d36Matthew Xie            throw new UnsupportedOperationException("BluetoothGatt#listen is blocked");
708c5470778a4fa8cc22e234fdcfe93fca39de63d36Matthew Xie        }
709f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach        if (DBG) Log.d(TAG, "listen() - start: " + start);
710f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach        if (mService == null || mClientIf == 0) return;
711f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach
712f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach        try {
713f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach            mService.clientListen(mClientIf, start);
714f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach        } catch (RemoteException e) {
715f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach            Log.e(TAG,"",e);
716f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach        }
717f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach    }
718f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach
719f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach    /**
720f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach     * Sets the advertising data contained in the adv. response packet.
721f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach     *
722f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
723f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach     *
724f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach     * @param advData true to set adv. data, false to set scan response
725f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach     * @param includeName Inlucde the name in the adv. response
726f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach     * @param includeTxPower Include TX power value
727f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach     * @param minInterval Minimum desired scan interval (optional)
728f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach     * @param maxInterval Maximum desired scan interval (optional)
729f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach     * @param appearance The appearance flags for the device (optional)
730f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach     * @param manufacturerData Manufacturer specific data including company ID (optional)
731f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach     */
732f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach    /*package*/ void setAdvData(boolean advData, boolean includeName, boolean includeTxPower,
733f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach                           Integer minInterval, Integer maxInterval,
734f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach                           Integer appearance, Byte[] manufacturerData) {
735c5470778a4fa8cc22e234fdcfe93fca39de63d36Matthew Xie        if (mContext == null || !mContext.getResources().
736c5470778a4fa8cc22e234fdcfe93fca39de63d36Matthew Xie            getBoolean(com.android.internal.R.bool.config_bluetooth_le_peripheral_mode_supported)) {
737c5470778a4fa8cc22e234fdcfe93fca39de63d36Matthew Xie            throw new UnsupportedOperationException("BluetoothGatt#setAdvData is blocked");
738c5470778a4fa8cc22e234fdcfe93fca39de63d36Matthew Xie        }
739f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach        if (DBG) Log.d(TAG, "setAdvData()");
740f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach        if (mService == null || mClientIf == 0) return;
741f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach
742f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach        byte[] data = new byte[0];
743f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach        if (manufacturerData != null) {
744f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach            data = new byte[manufacturerData.length];
745f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach            for(int i = 0; i != manufacturerData.length; ++i) {
746f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach                data[i] = manufacturerData[i];
747f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach            }
748f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach        }
749f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach
750f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach        try {
751f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach            mService.setAdvData(mClientIf, !advData,
752f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach                includeName, includeTxPower,
753f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach                minInterval != null ? minInterval : 0,
754f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach                maxInterval != null ? maxInterval : 0,
755f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach                appearance != null ? appearance : 0, data);
756f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach        } catch (RemoteException e) {
757f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach            Log.e(TAG,"",e);
758f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach        }
759f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach    }
760f46b21aa99fb3bbe4c8b446ff1d362c38f972099Andre Eisenbach
7619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
7629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Disconnects an established connection, or cancels a connection attempt
7639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * currently in progress.
7649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
7659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
7669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
767ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public void disconnect() {
768ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "cancelOpen() - device: " + mDevice.getAddress());
7699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return;
7709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
7719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
772ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.clientDisconnect(mClientIf, mDevice.getAddress());
7739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
7749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
7759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
77633ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    }
77733ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie
77833ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    /**
77933ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * Connect back to remote device.
78033ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     *
78133ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * <p>This method is used to re-connect to a remote device after the
78233ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * connection has been dropped. If the device is not in range, the
78333ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * re-connection will be triggered once the device is back in range.
78433ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     *
78533ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * @return true, if the connection attempt was initiated successfully
78633ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     */
78733ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    public boolean connect() {
78833ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie        try {
78933ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie            mService.clientConnect(mClientIf, mDevice.getAddress(),
79033ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie                                   false); // autoConnect is inverse of "isDirect"
79133ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie            return true;
79233ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie        } catch (RemoteException e) {
79333ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie            Log.e(TAG,"",e);
79433ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie            return false;
79533ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie        }
79633ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    }
79733ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie
79833ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    /**
79933ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * Return the remote bluetooth device this GATT client targets to
80033ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     *
80133ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     * @return remote bluetooth device
80233ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie     */
80333ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie    public BluetoothDevice getDevice() {
80433ec9840c70ddc7cd008ecf2660c441defc5f302Matthew Xie        return mDevice;
8059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
8069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
8089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Discovers services offered by a remote device as well as their
8099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * characteristics and descriptors.
8109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>This is an asynchronous operation. Once service discovery is completed,
8129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * the {@link BluetoothGattCallback#onServicesDiscovered} callback is
8139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * triggered. If the discovery was successful, the remote services can be
8149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * retrieved using the {@link #getServices} function.
8159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
8179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the remote service discovery has been started
8199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
820ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public boolean discoverServices() {
821ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "discoverServices() - device: " + mDevice.getAddress());
8229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
8239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        mServices.clear();
8259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
827ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.discoverServices(mClientIf, mDevice.getAddress());
8289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
8299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
8309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
8319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
8329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
8349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
8359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
8379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Returns a list of GATT services offered by the remote device.
8389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>This function requires that service discovery has been completed
8409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * for the given device.
8419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
8439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return List of services on the remote device. Returns an empty list
8459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *         if service discovery has not yet been performed.
8469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
847ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public List<BluetoothGattService> getServices() {
8489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        List<BluetoothGattService> result =
8499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ArrayList<BluetoothGattService>();
8509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        for (BluetoothGattService service : mServices) {
852ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            if (service.getDevice().equals(mDevice)) {
8539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                result.add(service);
8549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
8559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
8569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return result;
8589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
8599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
8619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Returns a {@link BluetoothGattService}, if the requested UUID is
8629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * supported by the remote device.
8639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>This function requires that service discovery has been completed
8659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * for the given device.
8669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>If multiple instances of the same service (as identified by UUID)
8689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * exist, the first instance of the service is returned.
8699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
8719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param uuid UUID of the requested service
8739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return BluetoothGattService if supported, or null if the requested
8749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *         service is not offered by the remote device.
8759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
876ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public BluetoothGattService getService(UUID uuid) {
8779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        for (BluetoothGattService service : mServices) {
878ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            if (service.getDevice().equals(mDevice) &&
8799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                service.getUuid().equals(uuid)) {
8809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                return service;
8819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
8829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
8839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return null;
8859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
8869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
8879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
8889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Reads the requested characteristic from the associated remote device.
8899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>This is an asynchronous operation. The result of the read operation
8919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * is reported by the {@link BluetoothGattCallback#onCharacteristicRead}
8929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * callback.
8939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
8959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
8969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param characteristic Characteristic to read from the remote device
8979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the read operation was initiated successfully
8989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
8999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public boolean readCharacteristic(BluetoothGattCharacteristic characteristic) {
9009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if ((characteristic.getProperties() &
9019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic.PROPERTY_READ) == 0) return false;
9029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "readCharacteristic() - uuid: " + characteristic.getUuid());
9049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
9059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattService service = characteristic.getService();
9079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (service == null) return false;
9089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothDevice device = service.getDevice();
9109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (device == null) return false;
9119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
9139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.readCharacteristic(mClientIf, device.getAddress(),
9149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                service.getType(), service.getInstanceId(),
9159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ParcelUuid(service.getUuid()), characteristic.getInstanceId(),
9169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ParcelUuid(characteristic.getUuid()), AUTHENTICATION_NONE);
9179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
9189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
9199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
9209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
9219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
9239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
9249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
926ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Writes a given characteristic and its values to the associated remote device.
9279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Once the write operation has been completed, the
9299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * {@link BluetoothGattCallback#onCharacteristicWrite} callback is invoked,
9309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * reporting the result of the operation.
9319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
9339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param characteristic Characteristic to write on the remote device
9359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the write operation was initiated successfully
9369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
9379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public boolean writeCharacteristic(BluetoothGattCharacteristic characteristic) {
9389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE) == 0
9399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            && (characteristic.getProperties() &
9409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) == 0) return false;
9419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "writeCharacteristic() - uuid: " + characteristic.getUuid());
9439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
9449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattService service = characteristic.getService();
9469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (service == null) return false;
9479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothDevice device = service.getDevice();
9499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (device == null) return false;
9509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
9529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.writeCharacteristic(mClientIf, device.getAddress(),
9539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                service.getType(), service.getInstanceId(),
9549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ParcelUuid(service.getUuid()), characteristic.getInstanceId(),
9559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ParcelUuid(characteristic.getUuid()),
9569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                characteristic.getWriteType(), AUTHENTICATION_NONE,
9579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                characteristic.getValue());
9589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
9599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
9609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
9619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
9629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
9649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
9659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
9679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Reads the value for a given descriptor from the associated remote device.
9689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Once the read operation has been completed, the
9709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * {@link BluetoothGattCallback#onDescriptorRead} callback is
9719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * triggered, signaling the result of the operation.
9729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
9749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
9759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param descriptor Descriptor value to read from the remote device
9769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the read operation was initiated successfully
9779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
9789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public boolean readDescriptor(BluetoothGattDescriptor descriptor) {
9799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "readDescriptor() - uuid: " + descriptor.getUuid());
9809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
9819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic();
9839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (characteristic == null) return false;
9849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattService service = characteristic.getService();
9869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (service == null) return false;
9879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothDevice device = service.getDevice();
9899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (device == null) return false;
9909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
9919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
99225b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach            mService.readDescriptor(mClientIf, device.getAddress(), service.getType(),
99325b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                service.getInstanceId(), new ParcelUuid(service.getUuid()),
99425b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                characteristic.getInstanceId(), new ParcelUuid(characteristic.getUuid()),
99525b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                descriptor.getInstanceId(), new ParcelUuid(descriptor.getUuid()),
99625b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                AUTHENTICATION_NONE);
9979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
9989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
9999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
10009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
10019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
10039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
10049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
10069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Write the value of a given descriptor to the associated remote device.
10079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>A {@link BluetoothGattCallback#onDescriptorWrite} callback is
10099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * triggered to report the result of the write operation.
10109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
10129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param descriptor Descriptor to write to the associated remote device
10149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the write operation was initiated successfully
10159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
10169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public boolean writeDescriptor(BluetoothGattDescriptor descriptor) {
10179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "writeDescriptor() - uuid: " + descriptor.getUuid());
10189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
10199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic();
10219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (characteristic == null) return false;
10229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattService service = characteristic.getService();
10249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (service == null) return false;
10259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothDevice device = service.getDevice();
10279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (device == null) return false;
10289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
103025b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach            mService.writeDescriptor(mClientIf, device.getAddress(), service.getType(),
103125b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                service.getInstanceId(), new ParcelUuid(service.getUuid()),
103225b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                characteristic.getInstanceId(), new ParcelUuid(characteristic.getUuid()),
103325b9cf953bd3e97f726f8c27d7a752b27c9a2373Andre Eisenbach                descriptor.getInstanceId(), new ParcelUuid(descriptor.getUuid()),
10349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                characteristic.getWriteType(), AUTHENTICATION_NONE,
10359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                descriptor.getValue());
10369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
10379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
10389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
10399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
10409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
10429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
10439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
10459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Initiates a reliable write transaction for a given remote device.
10469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Once a reliable write transaction has been initiated, all calls
10489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * to {@link #writeCharacteristic} are sent to the remote device for
10499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * verification and queued up for atomic execution. The application will
10509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * receive an {@link BluetoothGattCallback#onCharacteristicWrite} callback
10519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * in response to every {@link #writeCharacteristic} call and is responsible
10529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * for verifying if the value has been transmitted accurately.
10539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>After all characteristics have been queued up and verified,
10559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * {@link #executeReliableWrite} will execute all writes. If a characteristic
10569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * was not written correctly, calling {@link #abortReliableWrite} will
10579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * cancel the current transaction without commiting any values on the
10589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * remote device.
10599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
10619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the reliable write transaction has been initiated
10639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1064ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public boolean beginReliableWrite() {
1065ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "beginReliableWrite() - device: " + mDevice.getAddress());
10669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
10679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
1069ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.beginReliableWrite(mClientIf, mDevice.getAddress());
10709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
10719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
10729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
10739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
10749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
10769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
10779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
10799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Executes a reliable write transaction for a given remote device.
10809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>This function will commit all queued up characteristic write
10829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * operations for a given remote device.
10839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>A {@link BluetoothGattCallback#onReliableWriteCompleted} callback is
10859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * invoked to indicate whether the transaction has been executed correctly.
10869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
10889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
10899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the request to execute the transaction has been sent
10909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1091ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public boolean executeReliableWrite() {
1092ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "executeReliableWrite() - device: " + mDevice.getAddress());
10939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
10949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
10959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
1096ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.endReliableWrite(mClientIf, mDevice.getAddress(), true);
10979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
10989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
10999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
11009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
11019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
11039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
11049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
11069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Cancels a reliable write transaction for a given device.
11079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Calling this function will discard all queued characteristic write
11099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * operations for a given remote device.
11109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
11129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
111348f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du    public void abortReliableWrite() {
1114ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "abortReliableWrite() - device: " + mDevice.getAddress());
11159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return;
11169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
1118ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.endReliableWrite(mClientIf, mDevice.getAddress(), false);
11199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
11209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
11219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
11229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
11239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1125b7b7d7a05c164a56dd4155de4e84fc25ba706728John Du     * @deprecated Use {@link #abortReliableWrite()}
112648f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du     */
112748f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du    public void abortReliableWrite(BluetoothDevice mDevice) {
112848f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du        abortReliableWrite();
112948f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du    }
113048f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du
113148f8b5dbf6d387002abee1ec0da73446d2aab0dfJohn Du    /**
11329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Enable or disable notifications/indications for a given characteristic.
11339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Once notifications are enabled for a characteristic, a
11359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * {@link BluetoothGattCallback#onCharacteristicChanged} callback will be
11369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * triggered if the remote device indicates that the given characteristic
11379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * has changed.
11389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
11409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param characteristic The characteristic for which to enable notifications
11429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param enable Set to true to enable notifications/indications
11439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the requested notification status was set successfully
11449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
11459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public boolean setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
11469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                              boolean enable) {
11479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "setCharacteristicNotification() - uuid: " + characteristic.getUuid()
11489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                         + " enable: " + enable);
11499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
11509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattService service = characteristic.getService();
11529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (service == null) return false;
11539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothDevice device = service.getDevice();
11559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (device == null) return false;
11569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
11589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.registerForNotification(mClientIf, device.getAddress(),
11599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                service.getType(), service.getInstanceId(),
11609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ParcelUuid(service.getUuid()), characteristic.getInstanceId(),
11619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ParcelUuid(characteristic.getUuid()),
11629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                enable);
11639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
11649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
11659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
11669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
11679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
11699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
11709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
11729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Clears the internal cache and forces a refresh of the services from the
11739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * remote device.
11749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @hide
11759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1176ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public boolean refresh() {
1177ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "refresh() - device: " + mDevice.getAddress());
11789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
11799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
1181ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.refreshDevice(mClientIf, mDevice.getAddress());
11829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
11839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
11849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
11859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
11869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
11889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
11899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
11909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
11919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Read the RSSI for a connected remote device.
11929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>The {@link BluetoothGattCallback#onReadRemoteRssi} callback will be
11949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * invoked when the RSSI value has been read.
11959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
11979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
11989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the RSSI value has been requested successfully
11999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
1200ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public boolean readRemoteRssi() {
1201ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "readRssi() - device: " + mDevice.getAddress());
12029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mClientIf == 0) return false;
12039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
1205ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mService.readRemoteRssi(mClientIf, mDevice.getAddress());
12069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
12079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
12089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
12099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
12109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
12129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
12139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1215ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
1216ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * with {@link BluetoothProfile#GATT} as argument
12179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
1218ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @throws UnsupportedOperationException
12199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
12209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    @Override
12219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public int getConnectionState(BluetoothDevice device) {
1222ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        throw new UnsupportedOperationException("Use BluetoothManager#getConnectionState instead.");
12239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
12249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1226ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
1227ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * with {@link BluetoothProfile#GATT} as argument
12289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
1229ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @throws UnsupportedOperationException
12309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
12319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    @Override
12329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public List<BluetoothDevice> getConnectedDevices() {
1233ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        throw new UnsupportedOperationException
1234ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            ("Use BluetoothManager#getConnectedDevices instead.");
12359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
12369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
12379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
1238ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Not supported - please use
1239ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * {@link BluetoothManager#getDevicesMatchingConnectionStates(int, int[])}
1240ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * with {@link BluetoothProfile#GATT} as first argument
12419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
1242ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @throws UnsupportedOperationException
12439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
12449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    @Override
12459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
1246ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        throw new UnsupportedOperationException
1247ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            ("Use BluetoothManager#getDevicesMatchingConnectionStates instead.");
12489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
12499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta}
1250