blob: 69dc4e225f7ecd128cf70ac27b5456bb7ecd85ef [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 Xied21f6742013-05-26 21:03:16 +000073 /** A GATT operation failed */
74 public static final int GATT_FAILURE = 0;
75
Matthew Xieddf7e472013-03-01 18:41:02 -080076 /** 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.
Matthew Xieb30f91e2013-05-29 10:19:06 -0700568 *
569 * Application should call this method as early as possible after it is done with
570 * this GATT client.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800571 */
Matthew Xie33ec9842013-04-03 00:29:27 -0700572 public void close() {
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800573 if (DBG) Log.d(TAG, "close()");
574
575 unregisterApp();
Matthew Xie33ec9842013-04-03 00:29:27 -0700576 mConnState = CONN_STATE_CLOSED;
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800577 }
578
579 /**
580 * Returns a service by UUID, instance and type.
581 * @hide
582 */
583 /*package*/ BluetoothGattService getService(BluetoothDevice device, UUID uuid,
584 int instanceId, int type) {
585 for(BluetoothGattService svc : mServices) {
586 if (svc.getDevice().equals(device) &&
587 svc.getType() == type &&
588 svc.getInstanceId() == instanceId &&
589 svc.getUuid().equals(uuid)) {
590 return svc;
591 }
592 }
593 return null;
594 }
595
596
597 /**
Matthew Xieddf7e472013-03-01 18:41:02 -0800598 * Register an application callback to start using GATT.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800599 *
Matthew Xieddf7e472013-03-01 18:41:02 -0800600 * <p>This is an asynchronous call. The callback {@link BluetoothGattCallback#onAppRegistered}
601 * is used to notify success or failure if the function returns true.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800602 *
603 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
604 *
Matthew Xieddf7e472013-03-01 18:41:02 -0800605 * @param callback GATT callback handler that will receive asynchronous callbacks.
606 * @return If true, the callback will be called to notify success or failure,
607 * false on immediate error
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800608 */
Matthew Xieddf7e472013-03-01 18:41:02 -0800609 private boolean registerApp(BluetoothGattCallback callback) {
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800610 if (DBG) Log.d(TAG, "registerApp()");
611 if (mService == null) return false;
612
613 mCallback = callback;
614 UUID uuid = UUID.randomUUID();
615 if (DBG) Log.d(TAG, "registerApp() - UUID=" + uuid);
616
617 try {
618 mService.registerClient(new ParcelUuid(uuid), mBluetoothGattCallback);
619 } catch (RemoteException e) {
620 Log.e(TAG,"",e);
621 return false;
622 }
623
624 return true;
625 }
626
627 /**
628 * Unregister the current application and callbacks.
629 */
Matthew Xieddf7e472013-03-01 18:41:02 -0800630 private void unregisterApp() {
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800631 if (DBG) Log.d(TAG, "unregisterApp() - mClientIf=" + mClientIf);
632 if (mService == null || mClientIf == 0) return;
633
634 try {
635 mCallback = null;
636 mService.unregisterClient(mClientIf);
637 mClientIf = 0;
638 } catch (RemoteException e) {
639 Log.e(TAG,"",e);
640 }
641 }
642
643 /**
Matthew Xieddf7e472013-03-01 18:41:02 -0800644 * Initiate a connection to a Bluetooth GATT capable device.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800645 *
646 * <p>The connection may not be established right away, but will be
647 * completed when the remote device is available. A
648 * {@link BluetoothGattCallback#onConnectionStateChange} callback will be
649 * invoked when the connection state changes as a result of this function.
650 *
651 * <p>The autoConnect paramter determines whether to actively connect to
652 * the remote device, or rather passively scan and finalize the connection
653 * when the remote device is in range/available. Generally, the first ever
654 * connection to a device should be direct (autoConnect set to false) and
655 * subsequent connections to known devices should be invoked with the
Matthew Xieddf7e472013-03-01 18:41:02 -0800656 * autoConnect parameter set to true.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800657 *
658 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
659 *
660 * @param device Remote device to connect to
661 * @param autoConnect Whether to directly connect to the remote device (false)
662 * or to automatically connect as soon as the remote
663 * device becomes available (true).
664 * @return true, if the connection attempt was initiated successfully
665 */
Matthew Xieddf7e472013-03-01 18:41:02 -0800666 /*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallback callback) {
667 if (DBG) Log.d(TAG, "connect() - device: " + mDevice.getAddress() + ", auto: " + autoConnect);
668 synchronized(mStateLock) {
669 if (mConnState != CONN_STATE_IDLE) {
670 throw new IllegalStateException("Not idle");
671 }
672 mConnState = CONN_STATE_CONNECTING;
673 }
674 if (!registerApp(callback)) {
675 synchronized(mStateLock) {
676 mConnState = CONN_STATE_IDLE;
677 }
678 Log.e(TAG, "Failed to register callback");
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800679 return false;
680 }
681
Matthew Xieddf7e472013-03-01 18:41:02 -0800682 // the connection will continue after successful callback registration
683 mAutoConnect = autoConnect;
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800684 return true;
685 }
686
687 /**
688 * Disconnects an established connection, or cancels a connection attempt
689 * currently in progress.
690 *
691 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800692 */
Matthew Xieddf7e472013-03-01 18:41:02 -0800693 public void disconnect() {
694 if (DBG) Log.d(TAG, "cancelOpen() - device: " + mDevice.getAddress());
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800695 if (mService == null || mClientIf == 0) return;
696
697 try {
Matthew Xieddf7e472013-03-01 18:41:02 -0800698 mService.clientDisconnect(mClientIf, mDevice.getAddress());
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800699 } catch (RemoteException e) {
700 Log.e(TAG,"",e);
701 }
Matthew Xie33ec9842013-04-03 00:29:27 -0700702 }
703
704 /**
705 * Connect back to remote device.
706 *
707 * <p>This method is used to re-connect to a remote device after the
708 * connection has been dropped. If the device is not in range, the
709 * re-connection will be triggered once the device is back in range.
710 *
711 * @return true, if the connection attempt was initiated successfully
712 */
713 public boolean connect() {
714 try {
715 mService.clientConnect(mClientIf, mDevice.getAddress(),
716 false); // autoConnect is inverse of "isDirect"
717 return true;
718 } catch (RemoteException e) {
719 Log.e(TAG,"",e);
720 return false;
721 }
722 }
723
724 /**
725 * Return the remote bluetooth device this GATT client targets to
726 *
727 * @return remote bluetooth device
728 */
729 public BluetoothDevice getDevice() {
730 return mDevice;
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800731 }
732
733 /**
734 * Discovers services offered by a remote device as well as their
735 * characteristics and descriptors.
736 *
737 * <p>This is an asynchronous operation. Once service discovery is completed,
738 * the {@link BluetoothGattCallback#onServicesDiscovered} callback is
739 * triggered. If the discovery was successful, the remote services can be
740 * retrieved using the {@link #getServices} function.
741 *
742 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
743 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800744 * @return true, if the remote service discovery has been started
745 */
Matthew Xieddf7e472013-03-01 18:41:02 -0800746 public boolean discoverServices() {
747 if (DBG) Log.d(TAG, "discoverServices() - device: " + mDevice.getAddress());
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800748 if (mService == null || mClientIf == 0) return false;
749
750 mServices.clear();
751
752 try {
Matthew Xieddf7e472013-03-01 18:41:02 -0800753 mService.discoverServices(mClientIf, mDevice.getAddress());
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800754 } catch (RemoteException e) {
755 Log.e(TAG,"",e);
756 return false;
757 }
758
759 return true;
760 }
761
762 /**
763 * Returns a list of GATT services offered by the remote device.
764 *
765 * <p>This function requires that service discovery has been completed
766 * for the given device.
767 *
768 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
769 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800770 * @return List of services on the remote device. Returns an empty list
771 * if service discovery has not yet been performed.
772 */
Matthew Xieddf7e472013-03-01 18:41:02 -0800773 public List<BluetoothGattService> getServices() {
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800774 List<BluetoothGattService> result =
775 new ArrayList<BluetoothGattService>();
776
777 for (BluetoothGattService service : mServices) {
Matthew Xieddf7e472013-03-01 18:41:02 -0800778 if (service.getDevice().equals(mDevice)) {
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800779 result.add(service);
780 }
781 }
782
783 return result;
784 }
785
786 /**
787 * Returns a {@link BluetoothGattService}, if the requested UUID is
788 * supported by the remote device.
789 *
790 * <p>This function requires that service discovery has been completed
791 * for the given device.
792 *
793 * <p>If multiple instances of the same service (as identified by UUID)
794 * exist, the first instance of the service is returned.
795 *
796 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
797 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800798 * @param uuid UUID of the requested service
799 * @return BluetoothGattService if supported, or null if the requested
800 * service is not offered by the remote device.
801 */
Matthew Xieddf7e472013-03-01 18:41:02 -0800802 public BluetoothGattService getService(UUID uuid) {
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800803 for (BluetoothGattService service : mServices) {
Matthew Xieddf7e472013-03-01 18:41:02 -0800804 if (service.getDevice().equals(mDevice) &&
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800805 service.getUuid().equals(uuid)) {
806 return service;
807 }
808 }
809
810 return null;
811 }
812
813 /**
814 * Reads the requested characteristic from the associated remote device.
815 *
816 * <p>This is an asynchronous operation. The result of the read operation
817 * is reported by the {@link BluetoothGattCallback#onCharacteristicRead}
818 * callback.
819 *
820 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
821 *
822 * @param characteristic Characteristic to read from the remote device
823 * @return true, if the read operation was initiated successfully
824 */
825 public boolean readCharacteristic(BluetoothGattCharacteristic characteristic) {
826 if ((characteristic.getProperties() &
827 BluetoothGattCharacteristic.PROPERTY_READ) == 0) return false;
828
829 if (DBG) Log.d(TAG, "readCharacteristic() - uuid: " + characteristic.getUuid());
830 if (mService == null || mClientIf == 0) return false;
831
832 BluetoothGattService service = characteristic.getService();
833 if (service == null) return false;
834
835 BluetoothDevice device = service.getDevice();
836 if (device == null) return false;
837
838 try {
839 mService.readCharacteristic(mClientIf, device.getAddress(),
840 service.getType(), service.getInstanceId(),
841 new ParcelUuid(service.getUuid()), characteristic.getInstanceId(),
842 new ParcelUuid(characteristic.getUuid()), AUTHENTICATION_NONE);
843 } catch (RemoteException e) {
844 Log.e(TAG,"",e);
845 return false;
846 }
847
848 return true;
849 }
850
851 /**
Matthew Xieddf7e472013-03-01 18:41:02 -0800852 * Writes a given characteristic and its values to the associated remote device.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800853 *
854 * <p>Once the write operation has been completed, the
855 * {@link BluetoothGattCallback#onCharacteristicWrite} callback is invoked,
856 * reporting the result of the operation.
857 *
858 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
859 *
860 * @param characteristic Characteristic to write on the remote device
861 * @return true, if the write operation was initiated successfully
862 */
863 public boolean writeCharacteristic(BluetoothGattCharacteristic characteristic) {
864 if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE) == 0
865 && (characteristic.getProperties() &
866 BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) == 0) return false;
867
868 if (DBG) Log.d(TAG, "writeCharacteristic() - uuid: " + characteristic.getUuid());
869 if (mService == null || mClientIf == 0) return false;
870
871 BluetoothGattService service = characteristic.getService();
872 if (service == null) return false;
873
874 BluetoothDevice device = service.getDevice();
875 if (device == null) return false;
876
877 try {
878 mService.writeCharacteristic(mClientIf, device.getAddress(),
879 service.getType(), service.getInstanceId(),
880 new ParcelUuid(service.getUuid()), characteristic.getInstanceId(),
881 new ParcelUuid(characteristic.getUuid()),
882 characteristic.getWriteType(), AUTHENTICATION_NONE,
883 characteristic.getValue());
884 } catch (RemoteException e) {
885 Log.e(TAG,"",e);
886 return false;
887 }
888
889 return true;
890 }
891
892 /**
893 * Reads the value for a given descriptor from the associated remote device.
894 *
895 * <p>Once the read operation has been completed, the
896 * {@link BluetoothGattCallback#onDescriptorRead} callback is
897 * triggered, signaling the result of the operation.
898 *
899 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
900 *
901 * @param descriptor Descriptor value to read from the remote device
902 * @return true, if the read operation was initiated successfully
903 */
904 public boolean readDescriptor(BluetoothGattDescriptor descriptor) {
905 if (DBG) Log.d(TAG, "readDescriptor() - uuid: " + descriptor.getUuid());
906 if (mService == null || mClientIf == 0) return false;
907
908 BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic();
909 if (characteristic == null) return false;
910
911 BluetoothGattService service = characteristic.getService();
912 if (service == null) return false;
913
914 BluetoothDevice device = service.getDevice();
915 if (device == null) return false;
916
917 try {
918 mService.readDescriptor(mClientIf, device.getAddress(),
919 service.getType(), service.getInstanceId(),
920 new ParcelUuid(service.getUuid()), characteristic.getInstanceId(),
921 new ParcelUuid(characteristic.getUuid()),
922 new ParcelUuid(descriptor.getUuid()), AUTHENTICATION_NONE);
923 } catch (RemoteException e) {
924 Log.e(TAG,"",e);
925 return false;
926 }
927
928 return true;
929 }
930
931 /**
932 * Write the value of a given descriptor to the associated remote device.
933 *
934 * <p>A {@link BluetoothGattCallback#onDescriptorWrite} callback is
935 * triggered to report the result of the write operation.
936 *
937 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
938 *
939 * @param descriptor Descriptor to write to the associated remote device
940 * @return true, if the write operation was initiated successfully
941 */
942 public boolean writeDescriptor(BluetoothGattDescriptor descriptor) {
943 if (DBG) Log.d(TAG, "writeDescriptor() - uuid: " + descriptor.getUuid());
944 if (mService == null || mClientIf == 0) return false;
945
946 BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic();
947 if (characteristic == null) return false;
948
949 BluetoothGattService service = characteristic.getService();
950 if (service == null) return false;
951
952 BluetoothDevice device = service.getDevice();
953 if (device == null) return false;
954
955 try {
956 mService.writeDescriptor(mClientIf, device.getAddress(),
957 service.getType(), service.getInstanceId(),
958 new ParcelUuid(service.getUuid()), characteristic.getInstanceId(),
959 new ParcelUuid(characteristic.getUuid()),
960 new ParcelUuid(descriptor.getUuid()),
961 characteristic.getWriteType(), AUTHENTICATION_NONE,
962 descriptor.getValue());
963 } catch (RemoteException e) {
964 Log.e(TAG,"",e);
965 return false;
966 }
967
968 return true;
969 }
970
971 /**
972 * Initiates a reliable write transaction for a given remote device.
973 *
974 * <p>Once a reliable write transaction has been initiated, all calls
975 * to {@link #writeCharacteristic} are sent to the remote device for
976 * verification and queued up for atomic execution. The application will
977 * receive an {@link BluetoothGattCallback#onCharacteristicWrite} callback
978 * in response to every {@link #writeCharacteristic} call and is responsible
979 * for verifying if the value has been transmitted accurately.
980 *
981 * <p>After all characteristics have been queued up and verified,
982 * {@link #executeReliableWrite} will execute all writes. If a characteristic
983 * was not written correctly, calling {@link #abortReliableWrite} will
984 * cancel the current transaction without commiting any values on the
985 * remote device.
986 *
987 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
988 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800989 * @return true, if the reliable write transaction has been initiated
990 */
Matthew Xieddf7e472013-03-01 18:41:02 -0800991 public boolean beginReliableWrite() {
992 if (DBG) Log.d(TAG, "beginReliableWrite() - device: " + mDevice.getAddress());
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800993 if (mService == null || mClientIf == 0) return false;
994
995 try {
Matthew Xieddf7e472013-03-01 18:41:02 -0800996 mService.beginReliableWrite(mClientIf, mDevice.getAddress());
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800997 } catch (RemoteException e) {
998 Log.e(TAG,"",e);
999 return false;
1000 }
1001
1002 return true;
1003 }
1004
1005 /**
1006 * Executes a reliable write transaction for a given remote device.
1007 *
1008 * <p>This function will commit all queued up characteristic write
1009 * operations for a given remote device.
1010 *
1011 * <p>A {@link BluetoothGattCallback#onReliableWriteCompleted} callback is
1012 * invoked to indicate whether the transaction has been executed correctly.
1013 *
1014 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
1015 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001016 * @return true, if the request to execute the transaction has been sent
1017 */
Matthew Xieddf7e472013-03-01 18:41:02 -08001018 public boolean executeReliableWrite() {
1019 if (DBG) Log.d(TAG, "executeReliableWrite() - device: " + mDevice.getAddress());
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001020 if (mService == null || mClientIf == 0) return false;
1021
1022 try {
Matthew Xieddf7e472013-03-01 18:41:02 -08001023 mService.endReliableWrite(mClientIf, mDevice.getAddress(), true);
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001024 } catch (RemoteException e) {
1025 Log.e(TAG,"",e);
1026 return false;
1027 }
1028
1029 return true;
1030 }
1031
1032 /**
1033 * Cancels a reliable write transaction for a given device.
1034 *
1035 * <p>Calling this function will discard all queued characteristic write
1036 * operations for a given remote device.
1037 *
1038 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001039 */
Matthew Xieddf7e472013-03-01 18:41:02 -08001040 public void abortReliableWrite(BluetoothDevice mDevice) {
1041 if (DBG) Log.d(TAG, "abortReliableWrite() - device: " + mDevice.getAddress());
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001042 if (mService == null || mClientIf == 0) return;
1043
1044 try {
Matthew Xieddf7e472013-03-01 18:41:02 -08001045 mService.endReliableWrite(mClientIf, mDevice.getAddress(), false);
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001046 } catch (RemoteException e) {
1047 Log.e(TAG,"",e);
1048 }
1049 }
1050
1051 /**
1052 * Enable or disable notifications/indications for a given characteristic.
1053 *
1054 * <p>Once notifications are enabled for a characteristic, a
1055 * {@link BluetoothGattCallback#onCharacteristicChanged} callback will be
1056 * triggered if the remote device indicates that the given characteristic
1057 * has changed.
1058 *
1059 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
1060 *
1061 * @param characteristic The characteristic for which to enable notifications
1062 * @param enable Set to true to enable notifications/indications
1063 * @return true, if the requested notification status was set successfully
1064 */
1065 public boolean setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
1066 boolean enable) {
1067 if (DBG) Log.d(TAG, "setCharacteristicNotification() - uuid: " + characteristic.getUuid()
1068 + " enable: " + enable);
1069 if (mService == null || mClientIf == 0) return false;
1070
1071 BluetoothGattService service = characteristic.getService();
1072 if (service == null) return false;
1073
1074 BluetoothDevice device = service.getDevice();
1075 if (device == null) return false;
1076
1077 try {
1078 mService.registerForNotification(mClientIf, device.getAddress(),
1079 service.getType(), service.getInstanceId(),
1080 new ParcelUuid(service.getUuid()), characteristic.getInstanceId(),
1081 new ParcelUuid(characteristic.getUuid()),
1082 enable);
1083 } catch (RemoteException e) {
1084 Log.e(TAG,"",e);
1085 return false;
1086 }
1087
1088 return true;
1089 }
1090
1091 /**
1092 * Clears the internal cache and forces a refresh of the services from the
1093 * remote device.
1094 * @hide
1095 */
Matthew Xieddf7e472013-03-01 18:41:02 -08001096 public boolean refresh() {
1097 if (DBG) Log.d(TAG, "refresh() - device: " + mDevice.getAddress());
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001098 if (mService == null || mClientIf == 0) return false;
1099
1100 try {
Matthew Xieddf7e472013-03-01 18:41:02 -08001101 mService.refreshDevice(mClientIf, mDevice.getAddress());
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001102 } catch (RemoteException e) {
1103 Log.e(TAG,"",e);
1104 return false;
1105 }
1106
1107 return true;
1108 }
1109
1110 /**
1111 * Read the RSSI for a connected remote device.
1112 *
1113 * <p>The {@link BluetoothGattCallback#onReadRemoteRssi} callback will be
1114 * invoked when the RSSI value has been read.
1115 *
1116 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
1117 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001118 * @return true, if the RSSI value has been requested successfully
1119 */
Matthew Xieddf7e472013-03-01 18:41:02 -08001120 public boolean readRemoteRssi() {
1121 if (DBG) Log.d(TAG, "readRssi() - device: " + mDevice.getAddress());
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001122 if (mService == null || mClientIf == 0) return false;
1123
1124 try {
Matthew Xieddf7e472013-03-01 18:41:02 -08001125 mService.readRemoteRssi(mClientIf, mDevice.getAddress());
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001126 } catch (RemoteException e) {
1127 Log.e(TAG,"",e);
1128 return false;
1129 }
1130
1131 return true;
1132 }
1133
1134 /**
Matthew Xieddf7e472013-03-01 18:41:02 -08001135 * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
1136 * with {@link BluetoothProfile#GATT} as argument
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001137 *
Matthew Xieddf7e472013-03-01 18:41:02 -08001138 * @throws UnsupportedOperationException
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001139 */
1140 @Override
1141 public int getConnectionState(BluetoothDevice device) {
Matthew Xieddf7e472013-03-01 18:41:02 -08001142 throw new UnsupportedOperationException("Use BluetoothManager#getConnectionState instead.");
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001143 }
1144
1145 /**
Matthew Xieddf7e472013-03-01 18:41:02 -08001146 * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
1147 * with {@link BluetoothProfile#GATT} as argument
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001148 *
Matthew Xieddf7e472013-03-01 18:41:02 -08001149 * @throws UnsupportedOperationException
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001150 */
1151 @Override
1152 public List<BluetoothDevice> getConnectedDevices() {
Matthew Xieddf7e472013-03-01 18:41:02 -08001153 throw new UnsupportedOperationException
1154 ("Use BluetoothManager#getConnectedDevices instead.");
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001155 }
1156
1157 /**
Matthew Xieddf7e472013-03-01 18:41:02 -08001158 * Not supported - please use
1159 * {@link BluetoothManager#getDevicesMatchingConnectionStates(int, int[])}
1160 * with {@link BluetoothProfile#GATT} as first argument
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001161 *
Matthew Xieddf7e472013-03-01 18:41:02 -08001162 * @throws UnsupportedOperationException
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001163 */
1164 @Override
1165 public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
Matthew Xieddf7e472013-03-01 18:41:02 -08001166 throw new UnsupportedOperationException
1167 ("Use BluetoothManager#getDevicesMatchingConnectionStates instead.");
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001168 }
1169}