1 /* 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 17 package android.bluetooth; 18 19 import android.bluetooth.BluetoothAdapter; 20 import android.bluetooth.BluetoothDevice; 21 import android.bluetooth.BluetoothProfile; 22 import android.content.Context; 23 import android.os.ParcelUuid; 24 import android.os.RemoteException; 25 import android.util.Log; 26 27 import java.util.ArrayList; 28 import java.util.List; 29 import java.util.UUID; 30 31 /** 32 * Public API for the Bluetooth GATT Profile server role. 33 * 34 * <p>This class provides Bluetooth GATT server role functionality, 35 * allowing applications to create Bluetooth Smart services and 36 * characteristics. 37 * 38 * <p>BluetoothGattServer is a proxy object for controlling the Bluetooth Service 39 * via IPC. Use {@link BluetoothManager#openGattServer} to get an instance 40 * of this class. 41 */ 42 public final class BluetoothGattServer implements BluetoothProfile { 43 private static final String TAG = "BluetoothGattServer"; 44 private static final boolean DBG = true; 45 private static final boolean VDBG = false; 46 47 private BluetoothAdapter mAdapter; 48 private IBluetoothGatt mService; 49 private BluetoothGattServerCallback mCallback; 50 51 private Object mServerIfLock = new Object(); 52 private int mServerIf; 53 private int mTransport; 54 private List<BluetoothGattService> mServices; 55 56 private static final int CALLBACK_REG_TIMEOUT = 10000; 57 58 /** 59 * Bluetooth GATT interface callbacks 60 */ 61 private final IBluetoothGattServerCallback mBluetoothGattServerCallback = 62 new IBluetoothGattServerCallback.Stub() { 63 /** 64 * Application interface registered - app is ready to go 65 * @hide 66 */ 67 public void onServerRegistered(int status, int serverIf) { 68 if (DBG) Log.d(TAG, "onServerRegistered() - status=" + status 69 + " serverIf=" + serverIf); 70 synchronized(mServerIfLock) { 71 if (mCallback != null) { 72 mServerIf = serverIf; 73 mServerIfLock.notify(); 74 } else { 75 // registration timeout 76 Log.e(TAG, "onServerRegistered: mCallback is null"); 77 } 78 } 79 } 80 81 /** 82 * Callback reporting an LE scan result. 83 * @hide 84 */ 85 public void onScanResult(String address, int rssi, byte[] advData) { 86 if (VDBG) Log.d(TAG, "onScanResult() - Device=" + address + " RSSI=" +rssi); 87 // no op 88 } 89 90 /** 91 * Server connection state changed 92 * @hide 93 */ 94 public void onServerConnectionState(int status, int serverIf, 95 boolean connected, String address) { 96 if (DBG) Log.d(TAG, "onServerConnectionState() - status=" + status 97 + " serverIf=" + serverIf + " device=" + address); 98 try { 99 mCallback.onConnectionStateChange(mAdapter.getRemoteDevice(address), status, 100 connected ? BluetoothProfile.STATE_CONNECTED : 101 BluetoothProfile.STATE_DISCONNECTED); 102 } catch (Exception ex) { 103 Log.w(TAG, "Unhandled exception in callback", ex); 104 } 105 } 106 107 /** 108 * Service has been added 109 * @hide 110 */ 111 public void onServiceAdded(int status, int srvcType, 112 int srvcInstId, ParcelUuid srvcId) { 113 UUID srvcUuid = srvcId.getUuid(); 114 if (DBG) Log.d(TAG, "onServiceAdded() - service=" + srvcUuid 115 + "status=" + status); 116 117 BluetoothGattService service = getService(srvcUuid, srvcInstId, srvcType); 118 if (service == null) return; 119 120 try { 121 mCallback.onServiceAdded((int)status, service); 122 } catch (Exception ex) { 123 Log.w(TAG, "Unhandled exception in callback", ex); 124 } 125 } 126 127 /** 128 * Remote client characteristic read request. 129 * @hide 130 */ 131 public void onCharacteristicReadRequest(String address, int transId, 132 int offset, boolean isLong, int srvcType, int srvcInstId, 133 ParcelUuid srvcId, int charInstId, ParcelUuid charId) { 134 UUID srvcUuid = srvcId.getUuid(); 135 UUID charUuid = charId.getUuid(); 136 if (VDBG) Log.d(TAG, "onCharacteristicReadRequest() - " 137 + "service=" + srvcUuid + ", characteristic=" + charUuid); 138 139 BluetoothDevice device = mAdapter.getRemoteDevice(address); 140 BluetoothGattService service = getService(srvcUuid, srvcInstId, srvcType); 141 if (service == null) return; 142 143 BluetoothGattCharacteristic characteristic = service.getCharacteristic(charUuid); 144 if (characteristic == null) return; 145 146 try { 147 mCallback.onCharacteristicReadRequest(device, transId, offset, characteristic); 148 } catch (Exception ex) { 149 Log.w(TAG, "Unhandled exception in callback", ex); 150 } 151 } 152 153 /** 154 * Remote client descriptor read request. 155 * @hide 156 */ 157 public void onDescriptorReadRequest(String address, int transId, 158 int offset, boolean isLong, int srvcType, int srvcInstId, 159 ParcelUuid srvcId, int charInstId, ParcelUuid charId, 160 ParcelUuid descrId) { 161 UUID srvcUuid = srvcId.getUuid(); 162 UUID charUuid = charId.getUuid(); 163 UUID descrUuid = descrId.getUuid(); 164 if (VDBG) Log.d(TAG, "onCharacteristicReadRequest() - " 165 + "service=" + srvcUuid + ", characteristic=" + charUuid 166 + "descriptor=" + descrUuid); 167 168 BluetoothDevice device = mAdapter.getRemoteDevice(address); 169 BluetoothGattService service = getService(srvcUuid, srvcInstId, srvcType); 170 if (service == null) return; 171 172 BluetoothGattCharacteristic characteristic = service.getCharacteristic(charUuid); 173 if (characteristic == null) return; 174 175 BluetoothGattDescriptor descriptor = characteristic.getDescriptor(descrUuid); 176 if (descriptor == null) return; 177 178 try { 179 mCallback.onDescriptorReadRequest(device, transId, offset, descriptor); 180 } catch (Exception ex) { 181 Log.w(TAG, "Unhandled exception in callback", ex); 182 } 183 } 184 185 /** 186 * Remote client characteristic write request. 187 * @hide 188 */ 189 public void onCharacteristicWriteRequest(String address, int transId, 190 int offset, int length, boolean isPrep, boolean needRsp, 191 int srvcType, int srvcInstId, ParcelUuid srvcId, 192 int charInstId, ParcelUuid charId, byte[] value) { 193 UUID srvcUuid = srvcId.getUuid(); 194 UUID charUuid = charId.getUuid(); 195 if (VDBG) Log.d(TAG, "onCharacteristicWriteRequest() - " 196 + "service=" + srvcUuid + ", characteristic=" + charUuid); 197 198 BluetoothDevice device = mAdapter.getRemoteDevice(address); 199 BluetoothGattService service = getService(srvcUuid, srvcInstId, srvcType); 200 if (service == null) return; 201 202 BluetoothGattCharacteristic characteristic = service.getCharacteristic(charUuid); 203 if (characteristic == null) return; 204 205 try { 206 mCallback.onCharacteristicWriteRequest(device, transId, characteristic, 207 isPrep, needRsp, offset, value); 208 } catch (Exception ex) { 209 Log.w(TAG, "Unhandled exception in callback", ex); 210 } 211 212 } 213 214 /** 215 * Remote client descriptor write request. 216 * @hide 217 */ 218 public void onDescriptorWriteRequest(String address, int transId, 219 int offset, int length, boolean isPrep, boolean needRsp, 220 int srvcType, int srvcInstId, ParcelUuid srvcId, 221 int charInstId, ParcelUuid charId, ParcelUuid descrId, 222 byte[] value) { 223 UUID srvcUuid = srvcId.getUuid(); 224 UUID charUuid = charId.getUuid(); 225 UUID descrUuid = descrId.getUuid(); 226 if (VDBG) Log.d(TAG, "onDescriptorWriteRequest() - " 227 + "service=" + srvcUuid + ", characteristic=" + charUuid 228 + "descriptor=" + descrUuid); 229 230 BluetoothDevice device = mAdapter.getRemoteDevice(address); 231 232 BluetoothGattService service = getService(srvcUuid, srvcInstId, srvcType); 233 if (service == null) return; 234 235 BluetoothGattCharacteristic characteristic = service.getCharacteristic(charUuid); 236 if (characteristic == null) return; 237 238 BluetoothGattDescriptor descriptor = characteristic.getDescriptor(descrUuid); 239 if (descriptor == null) return; 240 241 try { 242 mCallback.onDescriptorWriteRequest(device, transId, descriptor, 243 isPrep, needRsp, offset, value); 244 } catch (Exception ex) { 245 Log.w(TAG, "Unhandled exception in callback", ex); 246 } 247 } 248 249 /** 250 * Execute pending writes. 251 * @hide 252 */ 253 public void onExecuteWrite(String address, int transId, 254 boolean execWrite) { 255 if (DBG) Log.d(TAG, "onExecuteWrite() - " 256 + "device=" + address + ", transId=" + transId 257 + "execWrite=" + execWrite); 258 259 BluetoothDevice device = mAdapter.getRemoteDevice(address); 260 if (device == null) return; 261 262 try { 263 mCallback.onExecuteWrite(device, transId, execWrite); 264 } catch (Exception ex) { 265 Log.w(TAG, "Unhandled exception in callback", ex); 266 } 267 } 268 269 /** 270 * A notification/indication has been sent. 271 * @hide 272 */ 273 public void onNotificationSent(String address, int status) { 274 if (VDBG) Log.d(TAG, "onNotificationSent() - " 275 + "device=" + address + ", status=" + status); 276 277 BluetoothDevice device = mAdapter.getRemoteDevice(address); 278 if (device == null) return; 279 280 try { 281 mCallback.onNotificationSent(device, status); 282 } catch (Exception ex) { 283 Log.w(TAG, "Unhandled exception: " + ex); 284 } 285 } 286 287 /** 288 * The MTU for a connection has changed 289 * @hide 290 */ 291 public void onMtuChanged(String address, int mtu) { 292 if (DBG) Log.d(TAG, "onMtuChanged() - " 293 + "device=" + address + ", mtu=" + mtu); 294 295 BluetoothDevice device = mAdapter.getRemoteDevice(address); 296 if (device == null) return; 297 298 try { 299 mCallback.onMtuChanged(device, mtu); 300 } catch (Exception ex) { 301 Log.w(TAG, "Unhandled exception: " + ex); 302 } 303 } 304 }; 305 306 /** 307 * Create a BluetoothGattServer proxy object. 308 */ BluetoothGattServer(IBluetoothGatt iGatt, int transport)309 /*package*/ BluetoothGattServer(IBluetoothGatt iGatt, int transport) { 310 mService = iGatt; 311 mAdapter = BluetoothAdapter.getDefaultAdapter(); 312 mCallback = null; 313 mServerIf = 0; 314 mTransport = transport; 315 mServices = new ArrayList<BluetoothGattService>(); 316 } 317 318 /** 319 * Close this GATT server instance. 320 * 321 * Application should call this method as early as possible after it is done with 322 * this GATT server. 323 */ close()324 public void close() { 325 if (DBG) Log.d(TAG, "close()"); 326 unregisterCallback(); 327 } 328 329 /** 330 * Register an application callback to start using GattServer. 331 * 332 * <p>This is an asynchronous call. The callback is used to notify 333 * success or failure if the function returns true. 334 * 335 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 336 * 337 * @param callback GATT callback handler that will receive asynchronous 338 * callbacks. 339 * @return true, the callback will be called to notify success or failure, 340 * false on immediate error 341 */ registerCallback(BluetoothGattServerCallback callback)342 /*package*/ boolean registerCallback(BluetoothGattServerCallback callback) { 343 if (DBG) Log.d(TAG, "registerCallback()"); 344 if (mService == null) { 345 Log.e(TAG, "GATT service not available"); 346 return false; 347 } 348 UUID uuid = UUID.randomUUID(); 349 if (DBG) Log.d(TAG, "registerCallback() - UUID=" + uuid); 350 351 synchronized(mServerIfLock) { 352 if (mCallback != null) { 353 Log.e(TAG, "App can register callback only once"); 354 return false; 355 } 356 357 mCallback = callback; 358 try { 359 mService.registerServer(new ParcelUuid(uuid), mBluetoothGattServerCallback); 360 } catch (RemoteException e) { 361 Log.e(TAG,"",e); 362 mCallback = null; 363 return false; 364 } 365 366 try { 367 mServerIfLock.wait(CALLBACK_REG_TIMEOUT); 368 } catch (InterruptedException e) { 369 Log.e(TAG, "" + e); 370 mCallback = null; 371 } 372 373 if (mServerIf == 0) { 374 mCallback = null; 375 return false; 376 } else { 377 return true; 378 } 379 } 380 } 381 382 /** 383 * Unregister the current application and callbacks. 384 */ unregisterCallback()385 private void unregisterCallback() { 386 if (DBG) Log.d(TAG, "unregisterCallback() - mServerIf=" + mServerIf); 387 if (mService == null || mServerIf == 0) return; 388 389 try { 390 mCallback = null; 391 mService.unregisterServer(mServerIf); 392 mServerIf = 0; 393 } catch (RemoteException e) { 394 Log.e(TAG,"",e); 395 } 396 } 397 398 /** 399 * Returns a service by UUID, instance and type. 400 * @hide 401 */ getService(UUID uuid, int instanceId, int type)402 /*package*/ BluetoothGattService getService(UUID uuid, int instanceId, int type) { 403 for(BluetoothGattService svc : mServices) { 404 if (svc.getType() == type && 405 svc.getInstanceId() == instanceId && 406 svc.getUuid().equals(uuid)) { 407 return svc; 408 } 409 } 410 return null; 411 } 412 413 /** 414 * Initiate a connection to a Bluetooth GATT capable device. 415 * 416 * <p>The connection may not be established right away, but will be 417 * completed when the remote device is available. A 418 * {@link BluetoothGattServerCallback#onConnectionStateChange} callback will be 419 * invoked when the connection state changes as a result of this function. 420 * 421 * <p>The autoConnect paramter determines whether to actively connect to 422 * the remote device, or rather passively scan and finalize the connection 423 * when the remote device is in range/available. Generally, the first ever 424 * connection to a device should be direct (autoConnect set to false) and 425 * subsequent connections to known devices should be invoked with the 426 * autoConnect parameter set to true. 427 * 428 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 429 * 430 * @param autoConnect Whether to directly connect to the remote device (false) 431 * or to automatically connect as soon as the remote 432 * device becomes available (true). 433 * @return true, if the connection attempt was initiated successfully 434 */ connect(BluetoothDevice device, boolean autoConnect)435 public boolean connect(BluetoothDevice device, boolean autoConnect) { 436 if (DBG) Log.d(TAG, "connect() - device: " + device.getAddress() + ", auto: " + autoConnect); 437 if (mService == null || mServerIf == 0) return false; 438 439 try { 440 mService.serverConnect(mServerIf, device.getAddress(), 441 autoConnect ? false : true,mTransport); // autoConnect is inverse of "isDirect" 442 } catch (RemoteException e) { 443 Log.e(TAG,"",e); 444 return false; 445 } 446 447 return true; 448 } 449 450 /** 451 * Disconnects an established connection, or cancels a connection attempt 452 * currently in progress. 453 * 454 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 455 * 456 * @param device Remote device 457 */ cancelConnection(BluetoothDevice device)458 public void cancelConnection(BluetoothDevice device) { 459 if (DBG) Log.d(TAG, "cancelConnection() - device: " + device.getAddress()); 460 if (mService == null || mServerIf == 0) return; 461 462 try { 463 mService.serverDisconnect(mServerIf, device.getAddress()); 464 } catch (RemoteException e) { 465 Log.e(TAG,"",e); 466 } 467 } 468 469 /** 470 * Send a response to a read or write request to a remote device. 471 * 472 * <p>This function must be invoked in when a remote read/write request 473 * is received by one of these callback methods: 474 * 475 * <ul> 476 * <li>{@link BluetoothGattServerCallback#onCharacteristicReadRequest} 477 * <li>{@link BluetoothGattServerCallback#onCharacteristicWriteRequest} 478 * <li>{@link BluetoothGattServerCallback#onDescriptorReadRequest} 479 * <li>{@link BluetoothGattServerCallback#onDescriptorWriteRequest} 480 * </ul> 481 * 482 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 483 * 484 * @param device The remote device to send this response to 485 * @param requestId The ID of the request that was received with the callback 486 * @param status The status of the request to be sent to the remote devices 487 * @param offset Value offset for partial read/write response 488 * @param value The value of the attribute that was read/written (optional) 489 */ sendResponse(BluetoothDevice device, int requestId, int status, int offset, byte[] value)490 public boolean sendResponse(BluetoothDevice device, int requestId, 491 int status, int offset, byte[] value) { 492 if (VDBG) Log.d(TAG, "sendResponse() - device: " + device.getAddress()); 493 if (mService == null || mServerIf == 0) return false; 494 495 try { 496 mService.sendResponse(mServerIf, device.getAddress(), requestId, 497 status, offset, value); 498 } catch (RemoteException e) { 499 Log.e(TAG,"",e); 500 return false; 501 } 502 return true; 503 } 504 505 /** 506 * Send a notification or indication that a local characteristic has been 507 * updated. 508 * 509 * <p>A notification or indication is sent to the remote device to signal 510 * that the characteristic has been updated. This function should be invoked 511 * for every client that requests notifications/indications by writing 512 * to the "Client Configuration" descriptor for the given characteristic. 513 * 514 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 515 * 516 * @param device The remote device to receive the notification/indication 517 * @param characteristic The local characteristic that has been updated 518 * @param confirm true to request confirmation from the client (indication), 519 * false to send a notification 520 * @throws IllegalArgumentException 521 * @return true, if the notification has been triggered successfully 522 */ notifyCharacteristicChanged(BluetoothDevice device, BluetoothGattCharacteristic characteristic, boolean confirm)523 public boolean notifyCharacteristicChanged(BluetoothDevice device, 524 BluetoothGattCharacteristic characteristic, boolean confirm) { 525 if (VDBG) Log.d(TAG, "notifyCharacteristicChanged() - device: " + device.getAddress()); 526 if (mService == null || mServerIf == 0) return false; 527 528 BluetoothGattService service = characteristic.getService(); 529 if (service == null) return false; 530 531 if (characteristic.getValue() == null) { 532 throw new IllegalArgumentException("Chracteristic value is empty. Use " 533 + "BluetoothGattCharacteristic#setvalue to update"); 534 } 535 536 try { 537 mService.sendNotification(mServerIf, device.getAddress(), 538 service.getType(), service.getInstanceId(), 539 new ParcelUuid(service.getUuid()), characteristic.getInstanceId(), 540 new ParcelUuid(characteristic.getUuid()), confirm, 541 characteristic.getValue()); 542 } catch (RemoteException e) { 543 Log.e(TAG,"",e); 544 return false; 545 } 546 547 return true; 548 } 549 550 /** 551 * Add a service to the list of services to be hosted. 552 * 553 * <p>Once a service has been addded to the the list, the service and its 554 * included characteristics will be provided by the local device. 555 * 556 * <p>If the local device has already exposed services when this function 557 * is called, a service update notification will be sent to all clients. 558 * 559 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 560 * 561 * @param service Service to be added to the list of services provided 562 * by this device. 563 * @return true, if the service has been added successfully 564 */ addService(BluetoothGattService service)565 public boolean addService(BluetoothGattService service) { 566 if (DBG) Log.d(TAG, "addService() - service: " + service.getUuid()); 567 if (mService == null || mServerIf == 0) return false; 568 569 mServices.add(service); 570 571 try { 572 mService.beginServiceDeclaration(mServerIf, service.getType(), 573 service.getInstanceId(), service.getHandles(), 574 new ParcelUuid(service.getUuid()), service.isAdvertisePreferred()); 575 576 List<BluetoothGattService> includedServices = service.getIncludedServices(); 577 for (BluetoothGattService includedService : includedServices) { 578 mService.addIncludedService(mServerIf, 579 includedService.getType(), 580 includedService.getInstanceId(), 581 new ParcelUuid(includedService.getUuid())); 582 } 583 584 List<BluetoothGattCharacteristic> characteristics = service.getCharacteristics(); 585 for (BluetoothGattCharacteristic characteristic : characteristics) { 586 int permission = ((characteristic.getKeySize() - 7) << 12) 587 + characteristic.getPermissions(); 588 mService.addCharacteristic(mServerIf, 589 new ParcelUuid(characteristic.getUuid()), 590 characteristic.getProperties(), permission); 591 592 List<BluetoothGattDescriptor> descriptors = characteristic.getDescriptors(); 593 for (BluetoothGattDescriptor descriptor: descriptors) { 594 permission = ((characteristic.getKeySize() - 7) << 12) 595 + descriptor.getPermissions(); 596 mService.addDescriptor(mServerIf, 597 new ParcelUuid(descriptor.getUuid()), permission); 598 } 599 } 600 601 mService.endServiceDeclaration(mServerIf); 602 } catch (RemoteException e) { 603 Log.e(TAG,"",e); 604 return false; 605 } 606 607 return true; 608 } 609 610 /** 611 * Removes a service from the list of services to be provided. 612 * 613 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 614 * 615 * @param service Service to be removed. 616 * @return true, if the service has been removed 617 */ removeService(BluetoothGattService service)618 public boolean removeService(BluetoothGattService service) { 619 if (DBG) Log.d(TAG, "removeService() - service: " + service.getUuid()); 620 if (mService == null || mServerIf == 0) return false; 621 622 BluetoothGattService intService = getService(service.getUuid(), 623 service.getInstanceId(), service.getType()); 624 if (intService == null) return false; 625 626 try { 627 mService.removeService(mServerIf, service.getType(), 628 service.getInstanceId(), new ParcelUuid(service.getUuid())); 629 mServices.remove(intService); 630 } catch (RemoteException e) { 631 Log.e(TAG,"",e); 632 return false; 633 } 634 635 return true; 636 } 637 638 /** 639 * Remove all services from the list of provided services. 640 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 641 */ clearServices()642 public void clearServices() { 643 if (DBG) Log.d(TAG, "clearServices()"); 644 if (mService == null || mServerIf == 0) return; 645 646 try { 647 mService.clearServices(mServerIf); 648 mServices.clear(); 649 } catch (RemoteException e) { 650 Log.e(TAG,"",e); 651 } 652 } 653 654 /** 655 * Returns a list of GATT services offered by this device. 656 * 657 * <p>An application must call {@link #addService} to add a serice to the 658 * list of services offered by this device. 659 * 660 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 661 * 662 * @return List of services. Returns an empty list 663 * if no services have been added yet. 664 */ getServices()665 public List<BluetoothGattService> getServices() { 666 return mServices; 667 } 668 669 /** 670 * Returns a {@link BluetoothGattService} from the list of services offered 671 * by this device. 672 * 673 * <p>If multiple instances of the same service (as identified by UUID) 674 * exist, the first instance of the service is returned. 675 * 676 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 677 * 678 * @param uuid UUID of the requested service 679 * @return BluetoothGattService if supported, or null if the requested 680 * service is not offered by this device. 681 */ getService(UUID uuid)682 public BluetoothGattService getService(UUID uuid) { 683 for (BluetoothGattService service : mServices) { 684 if (service.getUuid().equals(uuid)) { 685 return service; 686 } 687 } 688 689 return null; 690 } 691 692 693 /** 694 * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)} 695 * with {@link BluetoothProfile#GATT} as argument 696 * 697 * @throws UnsupportedOperationException 698 */ 699 @Override getConnectionState(BluetoothDevice device)700 public int getConnectionState(BluetoothDevice device) { 701 throw new UnsupportedOperationException("Use BluetoothManager#getConnectionState instead."); 702 } 703 704 /** 705 * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)} 706 * with {@link BluetoothProfile#GATT} as argument 707 * 708 * @throws UnsupportedOperationException 709 */ 710 @Override getConnectedDevices()711 public List<BluetoothDevice> getConnectedDevices() { 712 throw new UnsupportedOperationException 713 ("Use BluetoothManager#getConnectedDevices instead."); 714 } 715 716 /** 717 * Not supported - please use 718 * {@link BluetoothManager#getDevicesMatchingConnectionStates(int, int[])} 719 * with {@link BluetoothProfile#GATT} as first argument 720 * 721 * @throws UnsupportedOperationException 722 */ 723 @Override getDevicesMatchingConnectionStates(int[] states)724 public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 725 throw new UnsupportedOperationException 726 ("Use BluetoothManager#getDevicesMatchingConnectionStates instead."); 727 } 728 } 729