blob: bffe64b35702df319368a6d77136ed19b2bc44ad [file] [log] [blame]
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.bluetooth;
18
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -080019import android.bluetooth.BluetoothDevice;
20import android.bluetooth.BluetoothProfile;
21import android.bluetooth.BluetoothProfile.ServiceListener;
22import android.bluetooth.IBluetoothManager;
23import android.bluetooth.IBluetoothStateChangeCallback;
24
25import android.content.ComponentName;
26import android.content.Context;
27import android.content.Intent;
28import android.content.ServiceConnection;
29import android.os.IBinder;
30import android.os.ParcelUuid;
31import android.os.RemoteException;
32import android.os.ServiceManager;
33import android.util.Log;
34
35import java.util.ArrayList;
36import java.util.List;
37import java.util.UUID;
38
39/**
Matthew Xieddf7e472013-03-01 18:41:02 -080040 * Public API for the Bluetooth GATT Profile.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -080041 *
Matthew Xieddf7e472013-03-01 18:41:02 -080042 * <p>This class provides Bluetooth GATT functionality to enable communication
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -080043 * with Bluetooth Smart or Smart Ready devices.
44 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -080045 * <p>To connect to a remote peripheral device, create a {@link BluetoothGattCallback}
Matthew Xie33ec9842013-04-03 00:29:27 -070046 * and call {@link BluetoothDevice#connectGatt} to get a instance of this class.
Matthew Xieddf7e472013-03-01 18:41:02 -080047 * GATT capable devices can be discovered using the Bluetooth device discovery or BLE
48 * scan process.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -080049 */
50public final class BluetoothGatt implements BluetoothProfile {
51 private static final String TAG = "BluetoothGatt";
52 private static final boolean DBG = true;
Matthew Xieddf7e472013-03-01 18:41:02 -080053 private static final boolean VDBG = true;
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -080054
Matthew Xieddf7e472013-03-01 18:41:02 -080055 private final Context mContext;
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -080056 private IBluetoothGatt mService;
57 private BluetoothGattCallback mCallback;
58 private int mClientIf;
59 private boolean mAuthRetry = false;
Matthew Xieddf7e472013-03-01 18:41:02 -080060 private BluetoothDevice mDevice;
61 private boolean mAutoConnect;
62 private int mConnState;
63 private final Object mStateLock = new Object();
64
65 private static final int CONN_STATE_IDLE = 0;
66 private static final int CONN_STATE_CONNECTING = 1;
67 private static final int CONN_STATE_CONNECTED = 2;
68 private static final int CONN_STATE_DISCONNECTING = 3;
Matthew Xie33ec9842013-04-03 00:29:27 -070069 private static final int CONN_STATE_CLOSED = 4;
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -080070
71 private List<BluetoothGattService> mServices;
72
Matthew Xieddf7e472013-03-01 18:41:02 -080073 /** A GATT operation failed */
74 public static final int GATT_FAILURE = 0;
75
76 /** A GATT operation completed successfully */
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -080077 public static final int GATT_SUCCESS = 0;
78
Matthew Xieddf7e472013-03-01 18:41:02 -080079 /** GATT read operation is not permitted */
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -080080 public static final int GATT_READ_NOT_PERMITTED = 0x2;
81
Matthew Xieddf7e472013-03-01 18:41:02 -080082 /** GATT write operation is not permitted */
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -080083 public static final int GATT_WRITE_NOT_PERMITTED = 0x3;
84
85 /** Insufficient authentication for a given operation */
86 public static final int GATT_INSUFFICIENT_AUTHENTICATION = 0x5;
87
88 /** The given request is not supported */
89 public static final int GATT_REQUEST_NOT_SUPPORTED = 0x6;
90
91 /** Insufficient encryption for a given operation */
92 public static final int GATT_INSUFFICIENT_ENCRYPTION = 0xf;
93
94 /** A read or write operation was requested with an invalid offset */
95 public static final int GATT_INVALID_OFFSET = 0x7;
96
97 /** A write operation exceeds the maximum length of the attribute */
98 public static final int GATT_INVALID_ATTRIBUTE_LENGTH = 0xd;
99
100 /**
101 * No authentication required.
102 * @hide
103 */
104 /*package*/ static final int AUTHENTICATION_NONE = 0;
105
106 /**
107 * Authentication requested; no man-in-the-middle protection required.
108 * @hide
109 */
110 /*package*/ static final int AUTHENTICATION_NO_MITM = 1;
111
112 /**
113 * Authentication with man-in-the-middle protection requested.
114 * @hide
115 */
116 /*package*/ static final int AUTHENTICATION_MITM = 2;
117
118 /**
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800119 * Bluetooth GATT interface callbacks
120 */
121 private final IBluetoothGattCallback mBluetoothGattCallback =
122 new IBluetoothGattCallback.Stub() {
123 /**
124 * Application interface registered - app is ready to go
125 * @hide
126 */
127 public void onClientRegistered(int status, int clientIf) {
128 if (DBG) Log.d(TAG, "onClientRegistered() - status=" + status
129 + " clientIf=" + clientIf);
Matthew Xieddf7e472013-03-01 18:41:02 -0800130 if (VDBG) {
131 synchronized(mStateLock) {
132 if (mConnState != CONN_STATE_CONNECTING) {
133 Log.e(TAG, "Bad connection state: " + mConnState);
134 }
135 }
136 }
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800137 mClientIf = clientIf;
Matthew Xieddf7e472013-03-01 18:41:02 -0800138 if (status != GATT_SUCCESS) {
Matthew Xie33ec9842013-04-03 00:29:27 -0700139 mCallback.onConnectionStateChange(BluetoothGatt.this, GATT_FAILURE,
Matthew Xieddf7e472013-03-01 18:41:02 -0800140 BluetoothProfile.STATE_DISCONNECTED);
141 synchronized(mStateLock) {
142 mConnState = CONN_STATE_IDLE;
143 }
144 return;
145 }
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800146 try {
Matthew Xieddf7e472013-03-01 18:41:02 -0800147 mService.clientConnect(mClientIf, mDevice.getAddress(),
148 !mAutoConnect); // autoConnect is inverse of "isDirect"
149 } catch (RemoteException e) {
150 Log.e(TAG,"",e);
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800151 }
152 }
153
154 /**
155 * Client connection state changed
156 * @hide
157 */
158 public void onClientConnectionState(int status, int clientIf,
159 boolean connected, String address) {
160 if (DBG) Log.d(TAG, "onClientConnectionState() - status=" + status
161 + " clientIf=" + clientIf + " device=" + address);
Matthew Xieddf7e472013-03-01 18:41:02 -0800162 if (!address.equals(mDevice.getAddress())) {
163 return;
164 }
165 int profileState = connected ? BluetoothProfile.STATE_CONNECTED :
166 BluetoothProfile.STATE_DISCONNECTED;
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800167 try {
Matthew Xie33ec9842013-04-03 00:29:27 -0700168 mCallback.onConnectionStateChange(BluetoothGatt.this, status, profileState);
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800169 } catch (Exception ex) {
170 Log.w(TAG, "Unhandled exception: " + ex);
171 }
Matthew Xieddf7e472013-03-01 18:41:02 -0800172
173 synchronized(mStateLock) {
174 if (connected) {
175 mConnState = CONN_STATE_CONNECTED;
176 } else {
177 mConnState = CONN_STATE_IDLE;
178 }
179 }
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800180 }
181
182 /**
183 * Callback reporting an LE scan result.
184 * @hide
185 */
186 public void onScanResult(String address, int rssi, byte[] advData) {
Matthew Xieddf7e472013-03-01 18:41:02 -0800187 // no op
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800188 }
189
190 /**
191 * A new GATT service has been discovered.
192 * The service is added to the internal list and the search
193 * continues.
194 * @hide
195 */
196 public void onGetService(String address, int srvcType,
197 int srvcInstId, ParcelUuid srvcUuid) {
198 if (DBG) Log.d(TAG, "onGetService() - Device=" + address + " UUID=" + srvcUuid);
Matthew Xieddf7e472013-03-01 18:41:02 -0800199 if (!address.equals(mDevice.getAddress())) {
200 return;
201 }
202 mServices.add(new BluetoothGattService(mDevice, srvcUuid.getUuid(),
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800203 srvcInstId, srvcType));
204 }
205
206 /**
207 * An included service has been found durig GATT discovery.
208 * The included service is added to the respective parent.
209 * @hide
210 */
211 public void onGetIncludedService(String address, int srvcType,
212 int srvcInstId, ParcelUuid srvcUuid,
213 int inclSrvcType, int inclSrvcInstId,
214 ParcelUuid inclSrvcUuid) {
215 if (DBG) Log.d(TAG, "onGetIncludedService() - Device=" + address
216 + " UUID=" + srvcUuid + " Included=" + inclSrvcUuid);
217
Matthew Xieddf7e472013-03-01 18:41:02 -0800218 if (!address.equals(mDevice.getAddress())) {
219 return;
220 }
221 BluetoothGattService service = getService(mDevice,
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800222 srvcUuid.getUuid(), srvcInstId, srvcType);
Matthew Xieddf7e472013-03-01 18:41:02 -0800223 BluetoothGattService includedService = getService(mDevice,
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800224 inclSrvcUuid.getUuid(), inclSrvcInstId, inclSrvcType);
225
226 if (service != null && includedService != null) {
227 service.addIncludedService(includedService);
228 }
229 }
230
231 /**
232 * A new GATT characteristic has been discovered.
233 * Add the new characteristic to the relevant service and continue
234 * the remote device inspection.
235 * @hide
236 */
237 public void onGetCharacteristic(String address, int srvcType,
238 int srvcInstId, ParcelUuid srvcUuid,
239 int charInstId, ParcelUuid charUuid,
240 int charProps) {
241 if (DBG) Log.d(TAG, "onGetCharacteristic() - Device=" + address + " UUID=" +
242 charUuid);
243
Matthew Xieddf7e472013-03-01 18:41:02 -0800244 if (!address.equals(mDevice.getAddress())) {
245 return;
246 }
247 BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800248 srvcInstId, srvcType);
249 if (service != null) {
250 service.addCharacteristic(new BluetoothGattCharacteristic(
251 service, charUuid.getUuid(), charInstId, charProps, 0));
252 }
253 }
254
255 /**
256 * A new GATT descriptor has been discovered.
257 * Finally, add the descriptor to the related characteristic.
258 * This should conclude the remote device update.
259 * @hide
260 */
261 public void onGetDescriptor(String address, int srvcType,
262 int srvcInstId, ParcelUuid srvcUuid,
263 int charInstId, ParcelUuid charUuid,
264 ParcelUuid descUuid) {
265 if (DBG) Log.d(TAG, "onGetDescriptor() - Device=" + address + " UUID=" + descUuid);
266
Matthew Xieddf7e472013-03-01 18:41:02 -0800267 if (!address.equals(mDevice.getAddress())) {
268 return;
269 }
270 BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800271 srvcInstId, srvcType);
272 if (service == null) return;
273
274 BluetoothGattCharacteristic characteristic = service.getCharacteristic(
275 charUuid.getUuid());
276 if (characteristic == null) return;
277
278 characteristic.addDescriptor(new BluetoothGattDescriptor(
279 characteristic, descUuid.getUuid(), 0));
280 }
281
282 /**
283 * Remote search has been completed.
284 * The internal object structure should now reflect the state
285 * of the remote device database. Let the application know that
286 * we are done at this point.
287 * @hide
288 */
289 public void onSearchComplete(String address, int status) {
290 if (DBG) Log.d(TAG, "onSearchComplete() = Device=" + address + " Status=" + status);
Matthew Xieddf7e472013-03-01 18:41:02 -0800291 if (!address.equals(mDevice.getAddress())) {
292 return;
293 }
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800294 try {
Matthew Xie33ec9842013-04-03 00:29:27 -0700295 mCallback.onServicesDiscovered(BluetoothGatt.this, status);
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800296 } catch (Exception ex) {
297 Log.w(TAG, "Unhandled exception: " + ex);
298 }
299 }
300
301 /**
302 * Remote characteristic has been read.
303 * Updates the internal value.
304 * @hide
305 */
306 public void onCharacteristicRead(String address, int status, int srvcType,
307 int srvcInstId, ParcelUuid srvcUuid,
308 int charInstId, ParcelUuid charUuid, byte[] value) {
309 if (DBG) Log.d(TAG, "onCharacteristicRead() - Device=" + address
310 + " UUID=" + charUuid + " Status=" + status);
311
Matthew Xieddf7e472013-03-01 18:41:02 -0800312 if (!address.equals(mDevice.getAddress())) {
313 return;
314 }
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800315 if ((status == GATT_INSUFFICIENT_AUTHENTICATION
316 || status == GATT_INSUFFICIENT_ENCRYPTION)
317 && mAuthRetry == false) {
318 try {
319 mAuthRetry = true;
320 mService.readCharacteristic(mClientIf, address,
321 srvcType, srvcInstId, srvcUuid,
322 charInstId, charUuid, AUTHENTICATION_MITM);
323 return;
324 } catch (RemoteException e) {
325 Log.e(TAG,"",e);
326 }
327 }
328
329 mAuthRetry = false;
330
Matthew Xieddf7e472013-03-01 18:41:02 -0800331 BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800332 srvcInstId, srvcType);
333 if (service == null) return;
334
335 BluetoothGattCharacteristic characteristic = service.getCharacteristic(
336 charUuid.getUuid(), charInstId);
337 if (characteristic == null) return;
338
339 if (status == 0) characteristic.setValue(value);
340
341 try {
Matthew Xie33ec9842013-04-03 00:29:27 -0700342 mCallback.onCharacteristicRead(BluetoothGatt.this, characteristic, status);
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800343 } catch (Exception ex) {
344 Log.w(TAG, "Unhandled exception: " + ex);
345 }
346 }
347
348 /**
349 * Characteristic has been written to the remote device.
350 * Let the app know how we did...
351 * @hide
352 */
353 public void onCharacteristicWrite(String address, int status, int srvcType,
354 int srvcInstId, ParcelUuid srvcUuid,
355 int charInstId, ParcelUuid charUuid) {
356 if (DBG) Log.d(TAG, "onCharacteristicWrite() - Device=" + address
357 + " UUID=" + charUuid + " Status=" + status);
358
Matthew Xieddf7e472013-03-01 18:41:02 -0800359 if (!address.equals(mDevice.getAddress())) {
360 return;
361 }
362 BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800363 srvcInstId, srvcType);
364 if (service == null) return;
365
366 BluetoothGattCharacteristic characteristic = service.getCharacteristic(
367 charUuid.getUuid(), charInstId);
368 if (characteristic == null) return;
369
370 if ((status == GATT_INSUFFICIENT_AUTHENTICATION
371 || status == GATT_INSUFFICIENT_ENCRYPTION)
372 && mAuthRetry == false) {
373 try {
374 mAuthRetry = true;
375 mService.writeCharacteristic(mClientIf, address,
376 srvcType, srvcInstId, srvcUuid, charInstId, charUuid,
377 characteristic.getWriteType(), AUTHENTICATION_MITM,
378 characteristic.getValue());
379 return;
380 } catch (RemoteException e) {
381 Log.e(TAG,"",e);
382 }
383 }
384
385 mAuthRetry = false;
386
387 try {
Matthew Xie33ec9842013-04-03 00:29:27 -0700388 mCallback.onCharacteristicWrite(BluetoothGatt.this, characteristic, status);
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800389 } catch (Exception ex) {
390 Log.w(TAG, "Unhandled exception: " + ex);
391 }
392 }
393
394 /**
395 * Remote characteristic has been updated.
396 * Updates the internal value.
397 * @hide
398 */
399 public void onNotify(String address, int srvcType,
400 int srvcInstId, ParcelUuid srvcUuid,
401 int charInstId, ParcelUuid charUuid,
402 byte[] value) {
403 if (DBG) Log.d(TAG, "onNotify() - Device=" + address + " UUID=" + charUuid);
404
Matthew Xieddf7e472013-03-01 18:41:02 -0800405 if (!address.equals(mDevice.getAddress())) {
406 return;
407 }
408 BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800409 srvcInstId, srvcType);
410 if (service == null) return;
411
412 BluetoothGattCharacteristic characteristic = service.getCharacteristic(
413 charUuid.getUuid(), charInstId);
414 if (characteristic == null) return;
415
416 characteristic.setValue(value);
417
418 try {
Matthew Xie33ec9842013-04-03 00:29:27 -0700419 mCallback.onCharacteristicChanged(BluetoothGatt.this, characteristic);
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800420 } catch (Exception ex) {
421 Log.w(TAG, "Unhandled exception: " + ex);
422 }
423 }
424
425 /**
426 * Descriptor has been read.
427 * @hide
428 */
429 public void onDescriptorRead(String address, int status, int srvcType,
430 int srvcInstId, ParcelUuid srvcUuid,
431 int charInstId, ParcelUuid charUuid,
432 ParcelUuid descrUuid, byte[] value) {
433 if (DBG) Log.d(TAG, "onDescriptorRead() - Device=" + address + " UUID=" + charUuid);
434
Matthew Xieddf7e472013-03-01 18:41:02 -0800435 if (!address.equals(mDevice.getAddress())) {
436 return;
437 }
438 BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800439 srvcInstId, srvcType);
440 if (service == null) return;
441
442 BluetoothGattCharacteristic characteristic = service.getCharacteristic(
443 charUuid.getUuid(), charInstId);
444 if (characteristic == null) return;
445
446 BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
447 descrUuid.getUuid());
448 if (descriptor == null) return;
449
450 if (status == 0) descriptor.setValue(value);
451
452 if ((status == GATT_INSUFFICIENT_AUTHENTICATION
453 || status == GATT_INSUFFICIENT_ENCRYPTION)
454 && mAuthRetry == false) {
455 try {
456 mAuthRetry = true;
457 mService.readDescriptor(mClientIf, address,
458 srvcType, srvcInstId, srvcUuid, charInstId, charUuid,
459 descrUuid, AUTHENTICATION_MITM);
460 } catch (RemoteException e) {
461 Log.e(TAG,"",e);
462 }
463 }
464
465 mAuthRetry = true;
466
467 try {
Matthew Xie33ec9842013-04-03 00:29:27 -0700468 mCallback.onDescriptorRead(BluetoothGatt.this, descriptor, status);
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800469 } catch (Exception ex) {
470 Log.w(TAG, "Unhandled exception: " + ex);
471 }
472 }
473
474 /**
475 * Descriptor write operation complete.
476 * @hide
477 */
478 public void onDescriptorWrite(String address, int status, int srvcType,
479 int srvcInstId, ParcelUuid srvcUuid,
480 int charInstId, ParcelUuid charUuid,
481 ParcelUuid descrUuid) {
482 if (DBG) Log.d(TAG, "onDescriptorWrite() - Device=" + address + " UUID=" + charUuid);
483
Matthew Xieddf7e472013-03-01 18:41:02 -0800484 if (!address.equals(mDevice.getAddress())) {
485 return;
486 }
487 BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800488 srvcInstId, srvcType);
489 if (service == null) return;
490
491 BluetoothGattCharacteristic characteristic = service.getCharacteristic(
492 charUuid.getUuid(), charInstId);
493 if (characteristic == null) return;
494
495 BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
496 descrUuid.getUuid());
497 if (descriptor == null) return;
498
499 if ((status == GATT_INSUFFICIENT_AUTHENTICATION
500 || status == GATT_INSUFFICIENT_ENCRYPTION)
501 && mAuthRetry == false) {
502 try {
503 mAuthRetry = true;
504 mService.writeDescriptor(mClientIf, address,
505 srvcType, srvcInstId, srvcUuid, charInstId, charUuid,
506 descrUuid, characteristic.getWriteType(),
507 AUTHENTICATION_MITM, descriptor.getValue());
508 } catch (RemoteException e) {
509 Log.e(TAG,"",e);
510 }
511 }
512
513 mAuthRetry = false;
514
515 try {
Matthew Xie33ec9842013-04-03 00:29:27 -0700516 mCallback.onDescriptorWrite(BluetoothGatt.this, descriptor, status);
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800517 } catch (Exception ex) {
518 Log.w(TAG, "Unhandled exception: " + ex);
519 }
520 }
521
522 /**
523 * Prepared write transaction completed (or aborted)
524 * @hide
525 */
526 public void onExecuteWrite(String address, int status) {
527 if (DBG) Log.d(TAG, "onExecuteWrite() - Device=" + address
528 + " status=" + status);
Matthew Xieddf7e472013-03-01 18:41:02 -0800529 if (!address.equals(mDevice.getAddress())) {
530 return;
531 }
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800532 try {
Matthew Xie33ec9842013-04-03 00:29:27 -0700533 mCallback.onReliableWriteCompleted(BluetoothGatt.this, status);
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800534 } catch (Exception ex) {
535 Log.w(TAG, "Unhandled exception: " + ex);
536 }
537 }
538
539 /**
540 * Remote device RSSI has been read
541 * @hide
542 */
543 public void onReadRemoteRssi(String address, int rssi, int status) {
544 if (DBG) Log.d(TAG, "onReadRemoteRssi() - Device=" + address +
545 " rssi=" + rssi + " status=" + status);
Matthew Xieddf7e472013-03-01 18:41:02 -0800546 if (!address.equals(mDevice.getAddress())) {
547 return;
548 }
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800549 try {
Matthew Xie33ec9842013-04-03 00:29:27 -0700550 mCallback.onReadRemoteRssi(BluetoothGatt.this, rssi, status);
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800551 } catch (Exception ex) {
552 Log.w(TAG, "Unhandled exception: " + ex);
553 }
554 }
555 };
556
Matthew Xieddf7e472013-03-01 18:41:02 -0800557 /*package*/ BluetoothGatt(Context context, IBluetoothGatt iGatt, BluetoothDevice device) {
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800558 mContext = context;
Matthew Xieddf7e472013-03-01 18:41:02 -0800559 mService = iGatt;
560 mDevice = device;
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800561 mServices = new ArrayList<BluetoothGattService>();
562
Matthew Xieddf7e472013-03-01 18:41:02 -0800563 mConnState = CONN_STATE_IDLE;
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800564 }
565
566 /**
Matthew Xie33ec9842013-04-03 00:29:27 -0700567 * Close this Bluetooth GATT client.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800568 */
Matthew Xie33ec9842013-04-03 00:29:27 -0700569 public void close() {
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800570 if (DBG) Log.d(TAG, "close()");
571
572 unregisterApp();
Matthew Xie33ec9842013-04-03 00:29:27 -0700573 mConnState = CONN_STATE_CLOSED;
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800574 }
575
576 /**
577 * Returns a service by UUID, instance and type.
578 * @hide
579 */
580 /*package*/ BluetoothGattService getService(BluetoothDevice device, UUID uuid,
581 int instanceId, int type) {
582 for(BluetoothGattService svc : mServices) {
583 if (svc.getDevice().equals(device) &&
584 svc.getType() == type &&
585 svc.getInstanceId() == instanceId &&
586 svc.getUuid().equals(uuid)) {
587 return svc;
588 }
589 }
590 return null;
591 }
592
593
594 /**
Matthew Xieddf7e472013-03-01 18:41:02 -0800595 * Register an application callback to start using GATT.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800596 *
Matthew Xieddf7e472013-03-01 18:41:02 -0800597 * <p>This is an asynchronous call. The callback {@link BluetoothGattCallback#onAppRegistered}
598 * is used to notify success or failure if the function returns true.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800599 *
600 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
601 *
Matthew Xieddf7e472013-03-01 18:41:02 -0800602 * @param callback GATT callback handler that will receive asynchronous callbacks.
603 * @return If true, the callback will be called to notify success or failure,
604 * false on immediate error
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800605 */
Matthew Xieddf7e472013-03-01 18:41:02 -0800606 private boolean registerApp(BluetoothGattCallback callback) {
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800607 if (DBG) Log.d(TAG, "registerApp()");
608 if (mService == null) return false;
609
610 mCallback = callback;
611 UUID uuid = UUID.randomUUID();
612 if (DBG) Log.d(TAG, "registerApp() - UUID=" + uuid);
613
614 try {
615 mService.registerClient(new ParcelUuid(uuid), mBluetoothGattCallback);
616 } catch (RemoteException e) {
617 Log.e(TAG,"",e);
618 return false;
619 }
620
621 return true;
622 }
623
624 /**
625 * Unregister the current application and callbacks.
626 */
Matthew Xieddf7e472013-03-01 18:41:02 -0800627 private void unregisterApp() {
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800628 if (DBG) Log.d(TAG, "unregisterApp() - mClientIf=" + mClientIf);
629 if (mService == null || mClientIf == 0) return;
630
631 try {
632 mCallback = null;
633 mService.unregisterClient(mClientIf);
634 mClientIf = 0;
635 } catch (RemoteException e) {
636 Log.e(TAG,"",e);
637 }
638 }
639
640 /**
Matthew Xieddf7e472013-03-01 18:41:02 -0800641 * Initiate a connection to a Bluetooth GATT capable device.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800642 *
643 * <p>The connection may not be established right away, but will be
644 * completed when the remote device is available. A
645 * {@link BluetoothGattCallback#onConnectionStateChange} callback will be
646 * invoked when the connection state changes as a result of this function.
647 *
648 * <p>The autoConnect paramter determines whether to actively connect to
649 * the remote device, or rather passively scan and finalize the connection
650 * when the remote device is in range/available. Generally, the first ever
651 * connection to a device should be direct (autoConnect set to false) and
652 * subsequent connections to known devices should be invoked with the
Matthew Xieddf7e472013-03-01 18:41:02 -0800653 * autoConnect parameter set to true.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800654 *
655 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
656 *
657 * @param device Remote device to connect to
658 * @param autoConnect Whether to directly connect to the remote device (false)
659 * or to automatically connect as soon as the remote
660 * device becomes available (true).
661 * @return true, if the connection attempt was initiated successfully
662 */
Matthew Xieddf7e472013-03-01 18:41:02 -0800663 /*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallback callback) {
664 if (DBG) Log.d(TAG, "connect() - device: " + mDevice.getAddress() + ", auto: " + autoConnect);
665 synchronized(mStateLock) {
666 if (mConnState != CONN_STATE_IDLE) {
667 throw new IllegalStateException("Not idle");
668 }
669 mConnState = CONN_STATE_CONNECTING;
670 }
671 if (!registerApp(callback)) {
672 synchronized(mStateLock) {
673 mConnState = CONN_STATE_IDLE;
674 }
675 Log.e(TAG, "Failed to register callback");
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800676 return false;
677 }
678
Matthew Xieddf7e472013-03-01 18:41:02 -0800679 // the connection will continue after successful callback registration
680 mAutoConnect = autoConnect;
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800681 return true;
682 }
683
684 /**
685 * Disconnects an established connection, or cancels a connection attempt
686 * currently in progress.
687 *
688 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800689 */
Matthew Xieddf7e472013-03-01 18:41:02 -0800690 public void disconnect() {
691 if (DBG) Log.d(TAG, "cancelOpen() - device: " + mDevice.getAddress());
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800692 if (mService == null || mClientIf == 0) return;
693
694 try {
Matthew Xieddf7e472013-03-01 18:41:02 -0800695 mService.clientDisconnect(mClientIf, mDevice.getAddress());
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800696 } catch (RemoteException e) {
697 Log.e(TAG,"",e);
698 }
Matthew Xie33ec9842013-04-03 00:29:27 -0700699 }
700
701 /**
702 * Connect back to remote device.
703 *
704 * <p>This method is used to re-connect to a remote device after the
705 * connection has been dropped. If the device is not in range, the
706 * re-connection will be triggered once the device is back in range.
707 *
708 * @return true, if the connection attempt was initiated successfully
709 */
710 public boolean connect() {
711 try {
712 mService.clientConnect(mClientIf, mDevice.getAddress(),
713 false); // autoConnect is inverse of "isDirect"
714 return true;
715 } catch (RemoteException e) {
716 Log.e(TAG,"",e);
717 return false;
718 }
719 }
720
721 /**
722 * Return the remote bluetooth device this GATT client targets to
723 *
724 * @return remote bluetooth device
725 */
726 public BluetoothDevice getDevice() {
727 return mDevice;
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800728 }
729
730 /**
731 * Discovers services offered by a remote device as well as their
732 * characteristics and descriptors.
733 *
734 * <p>This is an asynchronous operation. Once service discovery is completed,
735 * the {@link BluetoothGattCallback#onServicesDiscovered} callback is
736 * triggered. If the discovery was successful, the remote services can be
737 * retrieved using the {@link #getServices} function.
738 *
739 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
740 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800741 * @return true, if the remote service discovery has been started
742 */
Matthew Xieddf7e472013-03-01 18:41:02 -0800743 public boolean discoverServices() {
744 if (DBG) Log.d(TAG, "discoverServices() - device: " + mDevice.getAddress());
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800745 if (mService == null || mClientIf == 0) return false;
746
747 mServices.clear();
748
749 try {
Matthew Xieddf7e472013-03-01 18:41:02 -0800750 mService.discoverServices(mClientIf, mDevice.getAddress());
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800751 } catch (RemoteException e) {
752 Log.e(TAG,"",e);
753 return false;
754 }
755
756 return true;
757 }
758
759 /**
760 * Returns a list of GATT services offered by the remote device.
761 *
762 * <p>This function requires that service discovery has been completed
763 * for the given device.
764 *
765 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
766 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800767 * @return List of services on the remote device. Returns an empty list
768 * if service discovery has not yet been performed.
769 */
Matthew Xieddf7e472013-03-01 18:41:02 -0800770 public List<BluetoothGattService> getServices() {
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800771 List<BluetoothGattService> result =
772 new ArrayList<BluetoothGattService>();
773
774 for (BluetoothGattService service : mServices) {
Matthew Xieddf7e472013-03-01 18:41:02 -0800775 if (service.getDevice().equals(mDevice)) {
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800776 result.add(service);
777 }
778 }
779
780 return result;
781 }
782
783 /**
784 * Returns a {@link BluetoothGattService}, if the requested UUID is
785 * supported by the remote device.
786 *
787 * <p>This function requires that service discovery has been completed
788 * for the given device.
789 *
790 * <p>If multiple instances of the same service (as identified by UUID)
791 * exist, the first instance of the service is returned.
792 *
793 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
794 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800795 * @param uuid UUID of the requested service
796 * @return BluetoothGattService if supported, or null if the requested
797 * service is not offered by the remote device.
798 */
Matthew Xieddf7e472013-03-01 18:41:02 -0800799 public BluetoothGattService getService(UUID uuid) {
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800800 for (BluetoothGattService service : mServices) {
Matthew Xieddf7e472013-03-01 18:41:02 -0800801 if (service.getDevice().equals(mDevice) &&
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800802 service.getUuid().equals(uuid)) {
803 return service;
804 }
805 }
806
807 return null;
808 }
809
810 /**
811 * Reads the requested characteristic from the associated remote device.
812 *
813 * <p>This is an asynchronous operation. The result of the read operation
814 * is reported by the {@link BluetoothGattCallback#onCharacteristicRead}
815 * callback.
816 *
817 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
818 *
819 * @param characteristic Characteristic to read from the remote device
820 * @return true, if the read operation was initiated successfully
821 */
822 public boolean readCharacteristic(BluetoothGattCharacteristic characteristic) {
823 if ((characteristic.getProperties() &
824 BluetoothGattCharacteristic.PROPERTY_READ) == 0) return false;
825
826 if (DBG) Log.d(TAG, "readCharacteristic() - uuid: " + characteristic.getUuid());
827 if (mService == null || mClientIf == 0) return false;
828
829 BluetoothGattService service = characteristic.getService();
830 if (service == null) return false;
831
832 BluetoothDevice device = service.getDevice();
833 if (device == null) return false;
834
835 try {
836 mService.readCharacteristic(mClientIf, device.getAddress(),
837 service.getType(), service.getInstanceId(),
838 new ParcelUuid(service.getUuid()), characteristic.getInstanceId(),
839 new ParcelUuid(characteristic.getUuid()), AUTHENTICATION_NONE);
840 } catch (RemoteException e) {
841 Log.e(TAG,"",e);
842 return false;
843 }
844
845 return true;
846 }
847
848 /**
Matthew Xieddf7e472013-03-01 18:41:02 -0800849 * Writes a given characteristic and its values to the associated remote device.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800850 *
851 * <p>Once the write operation has been completed, the
852 * {@link BluetoothGattCallback#onCharacteristicWrite} callback is invoked,
853 * reporting the result of the operation.
854 *
855 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
856 *
857 * @param characteristic Characteristic to write on the remote device
858 * @return true, if the write operation was initiated successfully
859 */
860 public boolean writeCharacteristic(BluetoothGattCharacteristic characteristic) {
861 if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE) == 0
862 && (characteristic.getProperties() &
863 BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) == 0) return false;
864
865 if (DBG) Log.d(TAG, "writeCharacteristic() - uuid: " + characteristic.getUuid());
866 if (mService == null || mClientIf == 0) return false;
867
868 BluetoothGattService service = characteristic.getService();
869 if (service == null) return false;
870
871 BluetoothDevice device = service.getDevice();
872 if (device == null) return false;
873
874 try {
875 mService.writeCharacteristic(mClientIf, device.getAddress(),
876 service.getType(), service.getInstanceId(),
877 new ParcelUuid(service.getUuid()), characteristic.getInstanceId(),
878 new ParcelUuid(characteristic.getUuid()),
879 characteristic.getWriteType(), AUTHENTICATION_NONE,
880 characteristic.getValue());
881 } catch (RemoteException e) {
882 Log.e(TAG,"",e);
883 return false;
884 }
885
886 return true;
887 }
888
889 /**
890 * Reads the value for a given descriptor from the associated remote device.
891 *
892 * <p>Once the read operation has been completed, the
893 * {@link BluetoothGattCallback#onDescriptorRead} callback is
894 * triggered, signaling the result of the operation.
895 *
896 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
897 *
898 * @param descriptor Descriptor value to read from the remote device
899 * @return true, if the read operation was initiated successfully
900 */
901 public boolean readDescriptor(BluetoothGattDescriptor descriptor) {
902 if (DBG) Log.d(TAG, "readDescriptor() - uuid: " + descriptor.getUuid());
903 if (mService == null || mClientIf == 0) return false;
904
905 BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic();
906 if (characteristic == null) return false;
907
908 BluetoothGattService service = characteristic.getService();
909 if (service == null) return false;
910
911 BluetoothDevice device = service.getDevice();
912 if (device == null) return false;
913
914 try {
915 mService.readDescriptor(mClientIf, device.getAddress(),
916 service.getType(), service.getInstanceId(),
917 new ParcelUuid(service.getUuid()), characteristic.getInstanceId(),
918 new ParcelUuid(characteristic.getUuid()),
919 new ParcelUuid(descriptor.getUuid()), AUTHENTICATION_NONE);
920 } catch (RemoteException e) {
921 Log.e(TAG,"",e);
922 return false;
923 }
924
925 return true;
926 }
927
928 /**
929 * Write the value of a given descriptor to the associated remote device.
930 *
931 * <p>A {@link BluetoothGattCallback#onDescriptorWrite} callback is
932 * triggered to report the result of the write operation.
933 *
934 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
935 *
936 * @param descriptor Descriptor to write to the associated remote device
937 * @return true, if the write operation was initiated successfully
938 */
939 public boolean writeDescriptor(BluetoothGattDescriptor descriptor) {
940 if (DBG) Log.d(TAG, "writeDescriptor() - uuid: " + descriptor.getUuid());
941 if (mService == null || mClientIf == 0) return false;
942
943 BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic();
944 if (characteristic == null) return false;
945
946 BluetoothGattService service = characteristic.getService();
947 if (service == null) return false;
948
949 BluetoothDevice device = service.getDevice();
950 if (device == null) return false;
951
952 try {
953 mService.writeDescriptor(mClientIf, device.getAddress(),
954 service.getType(), service.getInstanceId(),
955 new ParcelUuid(service.getUuid()), characteristic.getInstanceId(),
956 new ParcelUuid(characteristic.getUuid()),
957 new ParcelUuid(descriptor.getUuid()),
958 characteristic.getWriteType(), AUTHENTICATION_NONE,
959 descriptor.getValue());
960 } catch (RemoteException e) {
961 Log.e(TAG,"",e);
962 return false;
963 }
964
965 return true;
966 }
967
968 /**
969 * Initiates a reliable write transaction for a given remote device.
970 *
971 * <p>Once a reliable write transaction has been initiated, all calls
972 * to {@link #writeCharacteristic} are sent to the remote device for
973 * verification and queued up for atomic execution. The application will
974 * receive an {@link BluetoothGattCallback#onCharacteristicWrite} callback
975 * in response to every {@link #writeCharacteristic} call and is responsible
976 * for verifying if the value has been transmitted accurately.
977 *
978 * <p>After all characteristics have been queued up and verified,
979 * {@link #executeReliableWrite} will execute all writes. If a characteristic
980 * was not written correctly, calling {@link #abortReliableWrite} will
981 * cancel the current transaction without commiting any values on the
982 * remote device.
983 *
984 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
985 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800986 * @return true, if the reliable write transaction has been initiated
987 */
Matthew Xieddf7e472013-03-01 18:41:02 -0800988 public boolean beginReliableWrite() {
989 if (DBG) Log.d(TAG, "beginReliableWrite() - device: " + mDevice.getAddress());
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800990 if (mService == null || mClientIf == 0) return false;
991
992 try {
Matthew Xieddf7e472013-03-01 18:41:02 -0800993 mService.beginReliableWrite(mClientIf, mDevice.getAddress());
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800994 } catch (RemoteException e) {
995 Log.e(TAG,"",e);
996 return false;
997 }
998
999 return true;
1000 }
1001
1002 /**
1003 * Executes a reliable write transaction for a given remote device.
1004 *
1005 * <p>This function will commit all queued up characteristic write
1006 * operations for a given remote device.
1007 *
1008 * <p>A {@link BluetoothGattCallback#onReliableWriteCompleted} callback is
1009 * invoked to indicate whether the transaction has been executed correctly.
1010 *
1011 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
1012 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001013 * @return true, if the request to execute the transaction has been sent
1014 */
Matthew Xieddf7e472013-03-01 18:41:02 -08001015 public boolean executeReliableWrite() {
1016 if (DBG) Log.d(TAG, "executeReliableWrite() - device: " + mDevice.getAddress());
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001017 if (mService == null || mClientIf == 0) return false;
1018
1019 try {
Matthew Xieddf7e472013-03-01 18:41:02 -08001020 mService.endReliableWrite(mClientIf, mDevice.getAddress(), true);
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001021 } catch (RemoteException e) {
1022 Log.e(TAG,"",e);
1023 return false;
1024 }
1025
1026 return true;
1027 }
1028
1029 /**
1030 * Cancels a reliable write transaction for a given device.
1031 *
1032 * <p>Calling this function will discard all queued characteristic write
1033 * operations for a given remote device.
1034 *
1035 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001036 */
Matthew Xieddf7e472013-03-01 18:41:02 -08001037 public void abortReliableWrite(BluetoothDevice mDevice) {
1038 if (DBG) Log.d(TAG, "abortReliableWrite() - device: " + mDevice.getAddress());
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001039 if (mService == null || mClientIf == 0) return;
1040
1041 try {
Matthew Xieddf7e472013-03-01 18:41:02 -08001042 mService.endReliableWrite(mClientIf, mDevice.getAddress(), false);
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001043 } catch (RemoteException e) {
1044 Log.e(TAG,"",e);
1045 }
1046 }
1047
1048 /**
1049 * Enable or disable notifications/indications for a given characteristic.
1050 *
1051 * <p>Once notifications are enabled for a characteristic, a
1052 * {@link BluetoothGattCallback#onCharacteristicChanged} callback will be
1053 * triggered if the remote device indicates that the given characteristic
1054 * has changed.
1055 *
1056 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
1057 *
1058 * @param characteristic The characteristic for which to enable notifications
1059 * @param enable Set to true to enable notifications/indications
1060 * @return true, if the requested notification status was set successfully
1061 */
1062 public boolean setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
1063 boolean enable) {
1064 if (DBG) Log.d(TAG, "setCharacteristicNotification() - uuid: " + characteristic.getUuid()
1065 + " enable: " + enable);
1066 if (mService == null || mClientIf == 0) return false;
1067
1068 BluetoothGattService service = characteristic.getService();
1069 if (service == null) return false;
1070
1071 BluetoothDevice device = service.getDevice();
1072 if (device == null) return false;
1073
1074 try {
1075 mService.registerForNotification(mClientIf, device.getAddress(),
1076 service.getType(), service.getInstanceId(),
1077 new ParcelUuid(service.getUuid()), characteristic.getInstanceId(),
1078 new ParcelUuid(characteristic.getUuid()),
1079 enable);
1080 } catch (RemoteException e) {
1081 Log.e(TAG,"",e);
1082 return false;
1083 }
1084
1085 return true;
1086 }
1087
1088 /**
1089 * Clears the internal cache and forces a refresh of the services from the
1090 * remote device.
1091 * @hide
1092 */
Matthew Xieddf7e472013-03-01 18:41:02 -08001093 public boolean refresh() {
1094 if (DBG) Log.d(TAG, "refresh() - device: " + mDevice.getAddress());
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001095 if (mService == null || mClientIf == 0) return false;
1096
1097 try {
Matthew Xieddf7e472013-03-01 18:41:02 -08001098 mService.refreshDevice(mClientIf, mDevice.getAddress());
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001099 } catch (RemoteException e) {
1100 Log.e(TAG,"",e);
1101 return false;
1102 }
1103
1104 return true;
1105 }
1106
1107 /**
1108 * Read the RSSI for a connected remote device.
1109 *
1110 * <p>The {@link BluetoothGattCallback#onReadRemoteRssi} callback will be
1111 * invoked when the RSSI value has been read.
1112 *
1113 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
1114 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001115 * @return true, if the RSSI value has been requested successfully
1116 */
Matthew Xieddf7e472013-03-01 18:41:02 -08001117 public boolean readRemoteRssi() {
1118 if (DBG) Log.d(TAG, "readRssi() - device: " + mDevice.getAddress());
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001119 if (mService == null || mClientIf == 0) return false;
1120
1121 try {
Matthew Xieddf7e472013-03-01 18:41:02 -08001122 mService.readRemoteRssi(mClientIf, mDevice.getAddress());
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001123 } catch (RemoteException e) {
1124 Log.e(TAG,"",e);
1125 return false;
1126 }
1127
1128 return true;
1129 }
1130
1131 /**
Matthew Xieddf7e472013-03-01 18:41:02 -08001132 * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
1133 * with {@link BluetoothProfile#GATT} as argument
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001134 *
Matthew Xieddf7e472013-03-01 18:41:02 -08001135 * @throws UnsupportedOperationException
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001136 */
1137 @Override
1138 public int getConnectionState(BluetoothDevice device) {
Matthew Xieddf7e472013-03-01 18:41:02 -08001139 throw new UnsupportedOperationException("Use BluetoothManager#getConnectionState instead.");
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001140 }
1141
1142 /**
Matthew Xieddf7e472013-03-01 18:41:02 -08001143 * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
1144 * with {@link BluetoothProfile#GATT} as argument
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001145 *
Matthew Xieddf7e472013-03-01 18:41:02 -08001146 * @throws UnsupportedOperationException
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001147 */
1148 @Override
1149 public List<BluetoothDevice> getConnectedDevices() {
Matthew Xieddf7e472013-03-01 18:41:02 -08001150 throw new UnsupportedOperationException
1151 ("Use BluetoothManager#getConnectedDevices instead.");
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001152 }
1153
1154 /**
Matthew Xieddf7e472013-03-01 18:41:02 -08001155 * Not supported - please use
1156 * {@link BluetoothManager#getDevicesMatchingConnectionStates(int, int[])}
1157 * with {@link BluetoothProfile#GATT} as first argument
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001158 *
Matthew Xieddf7e472013-03-01 18:41:02 -08001159 * @throws UnsupportedOperationException
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001160 */
1161 @Override
1162 public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
Matthew Xieddf7e472013-03-01 18:41:02 -08001163 throw new UnsupportedOperationException
1164 ("Use BluetoothManager#getDevicesMatchingConnectionStates instead.");
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001165 }
1166}