GattService.java revision 18591a7894c5e4516491438c2e758adf8d2ade90
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 17package com.android.bluetooth.gatt; 18 19import android.app.Service; 20import android.bluetooth.BluetoothAdapter; 21import android.bluetooth.BluetoothDevice; 22import android.bluetooth.BluetoothProfile; 23import android.bluetooth.BluetoothUuid; 24import android.bluetooth.IBluetoothGatt; 25import android.bluetooth.IBluetoothGattCallback; 26import android.bluetooth.IBluetoothGattServerCallback; 27import android.content.Intent; 28import android.os.IBinder; 29import android.os.ParcelUuid; 30import android.os.RemoteException; 31import android.util.Log; 32 33import com.android.bluetooth.btservice.ProfileService; 34 35import java.nio.ByteBuffer; 36import java.nio.ByteOrder; 37import java.util.ArrayList; 38import java.util.HashMap; 39import java.util.HashSet; 40import java.util.List; 41import java.util.Map; 42import java.util.Set; 43import java.util.UUID; 44 45/** 46 * Provides Bluetooth Gatt profile, as a service in 47 * the Bluetooth application. 48 * @hide 49 */ 50public class GattService extends ProfileService { 51 private static final boolean DBG = GattServiceConfig.DBG; 52 private static final String TAG = GattServiceConfig.TAG_PREFIX + "GattService"; 53 private static final int DEFAULT_SCAN_INTERVAL_MILLIS = 200; 54 55 /** 56 * Max packet size for ble advertising, defined in Bluetooth Specification Version 4.0 [Vol 3]. 57 */ 58 private static final int ADVERTISING_PACKET_MAX_BYTES = 31; 59 /** 60 * Size overhead for advertising flag. 61 */ 62 private static final int ADVERTISING_FLAGS_BYTES = 3; 63 /** 64 * Size overhead per field. Usually it's just one byte of field length and one byte of 65 * field type. 66 */ 67 private static final int FIELD_OVERHEAD_BYTES = 2; 68 69 /** 70 * Byte size of 16 bit service uuid. 71 */ 72 private static final int SHORT_UUID_BYTES = 2; 73 /** 74 * Byte size of 128 bit service uuid. 75 */ 76 private static final int FULL_UUID_BYTES = 16; 77 78 /** 79 * Search queue to serialize remote onbject inspection. 80 */ 81 SearchQueue mSearchQueue = new SearchQueue(); 82 83 /** 84 * List of our registered clients. 85 */ 86 87 class ClientMap extends ContextMap<IBluetoothGattCallback> {} 88 ClientMap mClientMap = new ClientMap(); 89 90 /** 91 * List of our registered server apps. 92 */ 93 class ServerMap extends ContextMap<IBluetoothGattServerCallback> {} 94 ServerMap mServerMap = new ServerMap(); 95 96 /** 97 * Server handle map. 98 */ 99 HandleMap mHandleMap = new HandleMap(); 100 private List<UUID> mAdvertisingServiceUuids = new ArrayList<UUID>(); 101 102 private int mAdvertisingClientIf = 0; 103 104 private byte[] mServiceData = new byte[0]; 105 private int mManufacturerCode = -1; 106 private byte[] mManufacturerData = new byte[0]; 107 private Integer mAdvertisingState = BluetoothAdapter.STATE_ADVERTISE_STOPPED; 108 private final Object mLock = new Object(); 109 110 /** 111 * Pending service declaration queue 112 */ 113 private List<ServiceDeclaration> mServiceDeclarations = new ArrayList<ServiceDeclaration>(); 114 115 private ServiceDeclaration addDeclaration() { 116 synchronized (mServiceDeclarations) { 117 mServiceDeclarations.add(new ServiceDeclaration()); 118 } 119 return getActiveDeclaration(); 120 } 121 122 private ServiceDeclaration getActiveDeclaration() { 123 synchronized (mServiceDeclarations) { 124 if (mServiceDeclarations.size() > 0) 125 return mServiceDeclarations.get(mServiceDeclarations.size() - 1); 126 } 127 return null; 128 } 129 130 private ServiceDeclaration getPendingDeclaration() { 131 synchronized (mServiceDeclarations) { 132 if (mServiceDeclarations.size() > 0) 133 return mServiceDeclarations.get(0); 134 } 135 return null; 136 } 137 138 private void removePendingDeclaration() { 139 synchronized (mServiceDeclarations) { 140 if (mServiceDeclarations.size() > 0) 141 mServiceDeclarations.remove(0); 142 } 143 } 144 145 /** 146 * List of clients interested in scan results. 147 */ 148 private List<ScanClient> mScanQueue = new ArrayList<ScanClient>(); 149 150 private ScanClient getScanClient(int appIf, boolean isServer) { 151 for(ScanClient client : mScanQueue) { 152 if (client.appIf == appIf && client.isServer == isServer) { 153 return client; 154 } 155 } 156 return null; 157 } 158 159 private void removeScanClient(int appIf, boolean isServer) { 160 for(ScanClient client : mScanQueue) { 161 if (client.appIf == appIf && client.isServer == isServer) { 162 mScanQueue.remove(client); 163 break; 164 } 165 } 166 } 167 168 /** 169 * Reliable write queue 170 */ 171 private Set<String> mReliableQueue = new HashSet<String>(); 172 173 static { 174 classInitNative(); 175 } 176 177 protected String getName() { 178 return TAG; 179 } 180 181 protected IProfileServiceBinder initBinder() { 182 return new BluetoothGattBinder(this); 183 } 184 185 protected boolean start() { 186 if (DBG) Log.d(TAG, "start()"); 187 initializeNative(); 188 return true; 189 } 190 191 protected boolean stop() { 192 if (DBG) Log.d(TAG, "stop()"); 193 mClientMap.clear(); 194 mServerMap.clear(); 195 mSearchQueue.clear(); 196 mScanQueue.clear(); 197 mHandleMap.clear(); 198 mServiceDeclarations.clear(); 199 mReliableQueue.clear(); 200 return true; 201 } 202 203 protected boolean cleanup() { 204 if (DBG) Log.d(TAG, "cleanup()"); 205 cleanupNative(); 206 return true; 207 } 208 209 @Override 210 public int onStartCommand(Intent intent, int flags, int startId) { 211 if (GattDebugUtils.handleDebugAction(this, intent)) { 212 return Service.START_NOT_STICKY; 213 } 214 return super.onStartCommand(intent, flags, startId); 215 } 216 217 /** 218 * DeathReceipient handlers used to unregister applications that 219 * disconnect ungracefully (ie. crash or forced close). 220 */ 221 222 class ClientDeathRecipient implements IBinder.DeathRecipient { 223 int mAppIf; 224 225 public ClientDeathRecipient(int appIf) { 226 mAppIf = appIf; 227 } 228 229 public void binderDied() { 230 if (DBG) Log.d(TAG, "Binder is dead - unregistering client (" + mAppIf + ")!"); 231 if (mAdvertisingClientIf == mAppIf) { 232 stopAdvertising(true); // force stop advertising. 233 } else { 234 stopScan(mAppIf, false); 235 } 236 unregisterClient(mAppIf); 237 } 238 } 239 240 class ServerDeathRecipient implements IBinder.DeathRecipient { 241 int mAppIf; 242 243 public ServerDeathRecipient(int appIf) { 244 mAppIf = appIf; 245 } 246 247 public void binderDied() { 248 if (DBG) Log.d(TAG, "Binder is dead - unregistering server (" + mAppIf + ")!"); 249 unregisterServer(mAppIf); 250 } 251 } 252 253 /** 254 * Handlers for incoming service calls 255 */ 256 private static class BluetoothGattBinder extends IBluetoothGatt.Stub implements IProfileServiceBinder { 257 private GattService mService; 258 259 public BluetoothGattBinder(GattService svc) { 260 mService = svc; 261 } 262 263 public boolean cleanup() { 264 mService = null; 265 return true; 266 } 267 268 private GattService getService() { 269 if (mService != null && mService.isAvailable()) return mService; 270 Log.e(TAG, "getService() - Service requested, but not available!"); 271 return null; 272 } 273 274 public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 275 GattService service = getService(); 276 if (service == null) return new ArrayList<BluetoothDevice>(); 277 return service.getDevicesMatchingConnectionStates(states); 278 } 279 280 public void registerClient(ParcelUuid uuid, IBluetoothGattCallback callback) { 281 GattService service = getService(); 282 if (service == null) return; 283 service.registerClient(uuid.getUuid(), callback); 284 } 285 286 public void unregisterClient(int clientIf) { 287 GattService service = getService(); 288 if (service == null) return; 289 service.unregisterClient(clientIf); 290 } 291 292 public void startScan(int appIf, boolean isServer) { 293 GattService service = getService(); 294 if (service == null) return; 295 service.startScan(appIf, isServer); 296 } 297 298 public void startScanWithUuids(int appIf, boolean isServer, ParcelUuid[] ids) { 299 GattService service = getService(); 300 if (service == null) return; 301 UUID[] uuids = new UUID[ids.length]; 302 for(int i = 0; i != ids.length; ++i) { 303 uuids[i] = ids[i].getUuid(); 304 } 305 service.startScanWithUuids(appIf, isServer, uuids); 306 } 307 308 public void stopScan(int appIf, boolean isServer) { 309 GattService service = getService(); 310 if (service == null) return; 311 service.stopScan(appIf, isServer); 312 } 313 314 public void clientConnect(int clientIf, String address, boolean isDirect, int transport) { 315 GattService service = getService(); 316 if (service == null) return; 317 service.clientConnect(clientIf, address, isDirect, transport); 318 } 319 320 public void clientDisconnect(int clientIf, String address) { 321 GattService service = getService(); 322 if (service == null) return; 323 service.clientDisconnect(clientIf, address); 324 } 325 326 public void refreshDevice(int clientIf, String address) { 327 GattService service = getService(); 328 if (service == null) return; 329 service.refreshDevice(clientIf, address); 330 } 331 332 public void discoverServices(int clientIf, String address) { 333 GattService service = getService(); 334 if (service == null) return; 335 service.discoverServices(clientIf, address); 336 } 337 338 public void readCharacteristic(int clientIf, String address, int srvcType, 339 int srvcInstanceId, ParcelUuid srvcId, 340 int charInstanceId, ParcelUuid charId, 341 int authReq) { 342 GattService service = getService(); 343 if (service == null) return; 344 service.readCharacteristic(clientIf, address, srvcType, srvcInstanceId, 345 srvcId.getUuid(), charInstanceId, 346 charId.getUuid(), authReq); 347 } 348 349 public void writeCharacteristic(int clientIf, String address, int srvcType, 350 int srvcInstanceId, ParcelUuid srvcId, 351 int charInstanceId, ParcelUuid charId, 352 int writeType, int authReq, byte[] value) { 353 GattService service = getService(); 354 if (service == null) return; 355 service.writeCharacteristic(clientIf, address, srvcType, srvcInstanceId, 356 srvcId.getUuid(), charInstanceId, 357 charId.getUuid(), writeType, authReq, 358 value); 359 } 360 361 public void readDescriptor(int clientIf, String address, int srvcType, 362 int srvcInstanceId, ParcelUuid srvcId, 363 int charInstanceId, ParcelUuid charId, 364 int descrInstanceId, ParcelUuid descrId, 365 int authReq) { 366 GattService service = getService(); 367 if (service == null) return; 368 service.readDescriptor(clientIf, address, srvcType, 369 srvcInstanceId, srvcId.getUuid(), 370 charInstanceId, charId.getUuid(), 371 descrInstanceId, descrId.getUuid(), 372 authReq); 373 } 374 375 public void writeDescriptor(int clientIf, String address, int srvcType, 376 int srvcInstanceId, ParcelUuid srvcId, 377 int charInstanceId, ParcelUuid charId, 378 int descrInstanceId, ParcelUuid descrId, 379 int writeType, int authReq, byte[] value) { 380 GattService service = getService(); 381 if (service == null) return; 382 service.writeDescriptor(clientIf, address, srvcType, 383 srvcInstanceId, srvcId.getUuid(), 384 charInstanceId, charId.getUuid(), 385 descrInstanceId, descrId.getUuid(), 386 writeType, authReq, value); 387 } 388 389 public void beginReliableWrite(int clientIf, String address) { 390 GattService service = getService(); 391 if (service == null) return; 392 service.beginReliableWrite(clientIf, address); 393 } 394 395 public void endReliableWrite(int clientIf, String address, boolean execute) { 396 GattService service = getService(); 397 if (service == null) return; 398 service.endReliableWrite(clientIf, address, execute); 399 } 400 401 public void registerForNotification(int clientIf, String address, int srvcType, 402 int srvcInstanceId, ParcelUuid srvcId, 403 int charInstanceId, ParcelUuid charId, 404 boolean enable) { 405 GattService service = getService(); 406 if (service == null) return; 407 service.registerForNotification(clientIf, address, srvcType, srvcInstanceId, 408 srvcId.getUuid(), charInstanceId, 409 charId.getUuid(), enable); 410 } 411 412 public void readRemoteRssi(int clientIf, String address) { 413 GattService service = getService(); 414 if (service == null) return; 415 service.readRemoteRssi(clientIf, address); 416 } 417 418 public void configureMTU(int clientIf, String address, int mtu) { 419 GattService service = getService(); 420 if (service == null) return; 421 service.configureMTU(clientIf, address, mtu); 422 } 423 424 public void registerServer(ParcelUuid uuid, IBluetoothGattServerCallback callback) { 425 GattService service = getService(); 426 if (service == null) return; 427 service.registerServer(uuid.getUuid(), callback); 428 } 429 430 public void unregisterServer(int serverIf) { 431 GattService service = getService(); 432 if (service == null) return; 433 service.unregisterServer(serverIf); 434 } 435 436 public void serverConnect(int serverIf, String address, boolean isDirect, int transport) { 437 GattService service = getService(); 438 if (service == null) return; 439 service.serverConnect(serverIf, address, isDirect, transport); 440 } 441 442 public void serverDisconnect(int serverIf, String address) { 443 GattService service = getService(); 444 if (service == null) return; 445 service.serverDisconnect(serverIf, address); 446 } 447 448 public void beginServiceDeclaration(int serverIf, int srvcType, 449 int srvcInstanceId, int minHandles, 450 ParcelUuid srvcId, boolean advertisePreferred) { 451 GattService service = getService(); 452 if (service == null) return; 453 service.beginServiceDeclaration(serverIf, srvcType, srvcInstanceId, 454 minHandles, srvcId.getUuid(), advertisePreferred); 455 } 456 457 public void addIncludedService(int serverIf, int srvcType, 458 int srvcInstanceId, ParcelUuid srvcId) { 459 GattService service = getService(); 460 if (service == null) return; 461 service.addIncludedService(serverIf, srvcType, srvcInstanceId, 462 srvcId.getUuid()); 463 } 464 465 public void addCharacteristic(int serverIf, ParcelUuid charId, 466 int properties, int permissions) { 467 GattService service = getService(); 468 if (service == null) return; 469 service.addCharacteristic(serverIf, charId.getUuid(), properties, 470 permissions); 471 } 472 473 public void addDescriptor(int serverIf, ParcelUuid descId, 474 int permissions) { 475 GattService service = getService(); 476 if (service == null) return; 477 service.addDescriptor(serverIf, descId.getUuid(), permissions); 478 } 479 480 public void endServiceDeclaration(int serverIf) { 481 GattService service = getService(); 482 if (service == null) return; 483 service.endServiceDeclaration(serverIf); 484 } 485 486 public void removeService(int serverIf, int srvcType, 487 int srvcInstanceId, ParcelUuid srvcId) { 488 GattService service = getService(); 489 if (service == null) return; 490 service.removeService(serverIf, srvcType, srvcInstanceId, 491 srvcId.getUuid()); 492 } 493 494 public void clearServices(int serverIf) { 495 GattService service = getService(); 496 if (service == null) return; 497 service.clearServices(serverIf); 498 } 499 500 public void sendResponse(int serverIf, String address, int requestId, 501 int status, int offset, byte[] value) { 502 GattService service = getService(); 503 if (service == null) return; 504 service.sendResponse(serverIf, address, requestId, status, offset, value); 505 } 506 507 public void sendNotification(int serverIf, String address, int srvcType, 508 int srvcInstanceId, ParcelUuid srvcId, 509 int charInstanceId, ParcelUuid charId, 510 boolean confirm, byte[] value) { 511 GattService service = getService(); 512 if (service == null) return; 513 service.sendNotification(serverIf, address, srvcType, srvcInstanceId, 514 srvcId.getUuid(), charInstanceId, charId.getUuid(), confirm, value); 515 } 516 517 @Override 518 public void startAdvertising(int appIf) throws RemoteException { 519 GattService service = getService(); 520 if (service == null) return; 521 service.startAdvertising(appIf); 522 } 523 524 @Override 525 public boolean isAdvertising() { 526 GattService service = getService(); 527 if (service == null) return false; 528 return service.isAdvertising(); 529 } 530 531 @Override 532 public void stopAdvertising() throws RemoteException { 533 GattService service = getService(); 534 if (service == null) return; 535 service.stopAdvertising(); 536 } 537 538 @Override 539 public boolean setAdvServiceData(byte[] serviceData) throws RemoteException { 540 GattService service = getService(); 541 if (service == null) return false; 542 return service.setAdvServiceData(serviceData); 543 } 544 545 @Override 546 public byte[] getAdvServiceData() throws RemoteException { 547 GattService service = getService(); 548 if (service == null) return null; 549 return service.getAdvServiceData(); 550 } 551 552 @Override 553 public boolean setAdvManufacturerCodeAndData(int manufactureCode, byte[] manufacturerData) 554 throws RemoteException { 555 GattService service = getService(); 556 if (service == null) return false; 557 return service.setAdvManufacturerCodeAndData(manufactureCode, manufacturerData); 558 } 559 560 @Override 561 public byte[] getAdvManufacturerData() throws RemoteException { 562 GattService service = getService(); 563 if (service == null) return null; 564 return service.getAdvManufacturerData(); 565 } 566 567 @Override 568 public List<ParcelUuid> getAdvServiceUuids() throws RemoteException { 569 GattService service = getService(); 570 if (service == null) return null; 571 return service.getAdvServiceUuids(); 572 } 573 574 @Override 575 public void removeAdvManufacturerCodeAndData(int manufacturerCode) throws RemoteException { 576 } 577 578 }; 579 580 /************************************************************************** 581 * Callback functions - CLIENT 582 *************************************************************************/ 583 584 void onScanResult(String address, int rssi, byte[] adv_data) { 585 if (DBG) Log.d(TAG, "onScanResult() - address=" + address 586 + ", rssi=" + rssi); 587 588 List<UUID> remoteUuids = parseUuids(adv_data); 589 for (ScanClient client : mScanQueue) { 590 if (client.uuids.length > 0) { 591 int matches = 0; 592 for (UUID search : client.uuids) { 593 for (UUID remote: remoteUuids) { 594 if (remote.equals(search)) { 595 ++matches; 596 break; // Only count 1st match in case of duplicates 597 } 598 } 599 } 600 601 if (matches < client.uuids.length) continue; 602 } 603 604 if (!client.isServer) { 605 ClientMap.App app = mClientMap.getById(client.appIf); 606 if (app != null) { 607 try { 608 app.callback.onScanResult(address, rssi, adv_data); 609 } catch (RemoteException e) { 610 Log.e(TAG, "Exception: " + e); 611 mClientMap.remove(client.appIf); 612 mScanQueue.remove(client); 613 } 614 } 615 } else { 616 ServerMap.App app = mServerMap.getById(client.appIf); 617 if (app != null) { 618 try { 619 app.callback.onScanResult(address, rssi, adv_data); 620 } catch (RemoteException e) { 621 Log.e(TAG, "Exception: " + e); 622 mServerMap.remove(client.appIf); 623 mScanQueue.remove(client); 624 } 625 } 626 } 627 } 628 } 629 630 void onClientRegistered(int status, int clientIf, long uuidLsb, long uuidMsb) 631 throws RemoteException { 632 UUID uuid = new UUID(uuidMsb, uuidLsb); 633 if (DBG) Log.d(TAG, "onClientRegistered() - UUID=" + uuid + ", clientIf=" + clientIf); 634 ClientMap.App app = mClientMap.getByUuid(uuid); 635 if (app != null) { 636 app.id = clientIf; 637 app.linkToDeath(new ClientDeathRecipient(clientIf)); 638 app.callback.onClientRegistered(status, clientIf); 639 } 640 } 641 642 void onConnected(int clientIf, int connId, int status, String address) 643 throws RemoteException { 644 if (DBG) Log.d(TAG, "onConnected() - clientIf=" + clientIf 645 + ", connId=" + connId + ", address=" + address); 646 647 if (status == 0) mClientMap.addConnection(clientIf, connId, address); 648 ClientMap.App app = mClientMap.getById(clientIf); 649 if (app != null) { 650 app.callback.onClientConnectionState(status, clientIf, true, address); 651 } 652 } 653 654 void onDisconnected(int clientIf, int connId, int status, String address) 655 throws RemoteException { 656 if (DBG) Log.d(TAG, "onDisconnected() - clientIf=" + clientIf 657 + ", connId=" + connId + ", address=" + address); 658 659 mClientMap.removeConnection(clientIf, connId); 660 mSearchQueue.removeConnId(connId); 661 ClientMap.App app = mClientMap.getById(clientIf); 662 if (app != null) { 663 app.callback.onClientConnectionState(status, clientIf, false, address); 664 } 665 } 666 667 void onSearchCompleted(int connId, int status) throws RemoteException { 668 if (DBG) Log.d(TAG, "onSearchCompleted() - connId=" + connId+ ", status=" + status); 669 // We got all services, now let's explore characteristics... 670 continueSearch(connId, status); 671 } 672 673 void onSearchResult(int connId, int srvcType, 674 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb) 675 throws RemoteException { 676 UUID uuid = new UUID(srvcUuidMsb, srvcUuidLsb); 677 String address = mClientMap.addressByConnId(connId); 678 679 if (DBG) Log.d(TAG, "onSearchResult() - address=" + address + ", uuid=" + uuid); 680 681 mSearchQueue.add(connId, srvcType, srvcInstId, srvcUuidLsb, srvcUuidMsb); 682 683 ClientMap.App app = mClientMap.getByConnId(connId); 684 if (app != null) { 685 app.callback.onGetService(address, srvcType, srvcInstId, 686 new ParcelUuid(uuid)); 687 } 688 } 689 690 void onGetCharacteristic(int connId, int status, int srvcType, 691 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 692 int charInstId, long charUuidLsb, long charUuidMsb, 693 int charProp) throws RemoteException { 694 695 UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 696 UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 697 String address = mClientMap.addressByConnId(connId); 698 699 if (DBG) Log.d(TAG, "onGetCharacteristic() - address=" + address 700 + ", status=" + status + ", charUuid=" + charUuid + ", prop=" + charProp); 701 702 if (status == 0) { 703 mSearchQueue.add(connId, srvcType, 704 srvcInstId, srvcUuidLsb, srvcUuidMsb, 705 charInstId, charUuidLsb, charUuidMsb); 706 707 ClientMap.App app = mClientMap.getByConnId(connId); 708 if (app != null) { 709 app.callback.onGetCharacteristic(address, srvcType, 710 srvcInstId, new ParcelUuid(srvcUuid), 711 charInstId, new ParcelUuid(charUuid), charProp); 712 } 713 714 // Get next characteristic in the current service 715 gattClientGetCharacteristicNative(connId, srvcType, 716 srvcInstId, srvcUuidLsb, srvcUuidMsb, 717 charInstId, charUuidLsb, charUuidMsb); 718 } else { 719 // Check for included services next 720 gattClientGetIncludedServiceNative(connId, 721 srvcType, srvcInstId, srvcUuidLsb, srvcUuidMsb, 722 0,0,0,0); 723 } 724 } 725 726 void onGetDescriptor(int connId, int status, int srvcType, 727 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 728 int charInstId, long charUuidLsb, long charUuidMsb, 729 int descrInstId, long descrUuidLsb, long descrUuidMsb) throws RemoteException { 730 731 UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 732 UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 733 UUID descUuid = new UUID(descrUuidMsb, descrUuidLsb); 734 String address = mClientMap.addressByConnId(connId); 735 736 if (DBG) Log.d(TAG, "onGetDescriptor() - address=" + address 737 + ", status=" + status + ", descUuid=" + descUuid); 738 739 if (status == 0) { 740 ClientMap.App app = mClientMap.getByConnId(connId); 741 if (app != null) { 742 app.callback.onGetDescriptor(address, srvcType, 743 srvcInstId, new ParcelUuid(srvcUuid), 744 charInstId, new ParcelUuid(charUuid), 745 descrInstId, new ParcelUuid(descUuid)); 746 } 747 748 // Get next descriptor for the current characteristic 749 gattClientGetDescriptorNative(connId, srvcType, 750 srvcInstId, srvcUuidLsb, srvcUuidMsb, 751 charInstId, charUuidLsb, charUuidMsb, 752 descrInstId, descrUuidLsb, descrUuidMsb); 753 } else { 754 // Explore the next service 755 continueSearch(connId, 0); 756 } 757 } 758 759 void onGetIncludedService(int connId, int status, int srvcType, 760 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, int inclSrvcType, 761 int inclSrvcInstId, long inclSrvcUuidLsb, long inclSrvcUuidMsb) 762 throws RemoteException { 763 UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 764 UUID inclSrvcUuid = new UUID(inclSrvcUuidMsb, inclSrvcUuidLsb); 765 String address = mClientMap.addressByConnId(connId); 766 767 if (DBG) Log.d(TAG, "onGetIncludedService() - address=" + address 768 + ", status=" + status + ", uuid=" + srvcUuid 769 + ", inclUuid=" + inclSrvcUuid); 770 771 if (status == 0) { 772 ClientMap.App app = mClientMap.getByConnId(connId); 773 if (app != null) { 774 app.callback.onGetIncludedService(address, 775 srvcType, srvcInstId, new ParcelUuid(srvcUuid), 776 inclSrvcType, inclSrvcInstId, new ParcelUuid(inclSrvcUuid)); 777 } 778 779 // Find additional included services 780 gattClientGetIncludedServiceNative(connId, 781 srvcType, srvcInstId, srvcUuidLsb, srvcUuidMsb, 782 inclSrvcType, inclSrvcInstId, inclSrvcUuidLsb, inclSrvcUuidMsb); 783 } else { 784 // Discover descriptors now 785 continueSearch(connId, 0); 786 } 787 } 788 789 void onRegisterForNotifications(int connId, int status, int registered, int srvcType, 790 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 791 int charInstId, long charUuidLsb, long charUuidMsb) { 792 UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 793 UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 794 String address = mClientMap.addressByConnId(connId); 795 796 if (DBG) Log.d(TAG, "onRegisterForNotifications() - address=" + address 797 + ", status=" + status + ", registered=" + registered 798 + ", charUuid=" + charUuid); 799 } 800 801 void onNotify(int connId, String address, int srvcType, 802 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 803 int charInstId, long charUuidLsb, long charUuidMsb, 804 boolean isNotify, byte[] data) throws RemoteException { 805 UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 806 UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 807 808 if (DBG) Log.d(TAG, "onNotify() - address=" + address 809 + ", charUuid=" + charUuid + ", length=" + data.length); 810 811 ClientMap.App app = mClientMap.getByConnId(connId); 812 if (app != null) { 813 app.callback.onNotify(address, srvcType, 814 srvcInstId, new ParcelUuid(srvcUuid), 815 charInstId, new ParcelUuid(charUuid), 816 data); 817 } 818 } 819 820 void onReadCharacteristic(int connId, int status, int srvcType, 821 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 822 int charInstId, long charUuidLsb, long charUuidMsb, 823 int charType, byte[] data) throws RemoteException { 824 825 UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 826 UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 827 String address = mClientMap.addressByConnId(connId); 828 829 if (DBG) Log.d(TAG, "onReadCharacteristic() - address=" + address 830 + ", status=" + status + ", length=" + data.length); 831 832 ClientMap.App app = mClientMap.getByConnId(connId); 833 if (app != null) { 834 app.callback.onCharacteristicRead(address, status, srvcType, 835 srvcInstId, new ParcelUuid(srvcUuid), 836 charInstId, new ParcelUuid(charUuid), data); 837 } 838 } 839 840 void onWriteCharacteristic(int connId, int status, int srvcType, 841 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 842 int charInstId, long charUuidLsb, long charUuidMsb) 843 throws RemoteException { 844 845 UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 846 UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 847 String address = mClientMap.addressByConnId(connId); 848 849 if (DBG) Log.d(TAG, "onWriteCharacteristic() - address=" + address 850 + ", status=" + status); 851 852 ClientMap.App app = mClientMap.getByConnId(connId); 853 if (app != null) { 854 app.callback.onCharacteristicWrite(address, status, srvcType, 855 srvcInstId, new ParcelUuid(srvcUuid), 856 charInstId, new ParcelUuid(charUuid)); 857 } 858 } 859 860 void onExecuteCompleted(int connId, int status) throws RemoteException { 861 String address = mClientMap.addressByConnId(connId); 862 if (DBG) Log.d(TAG, "onExecuteCompleted() - address=" + address 863 + ", status=" + status); 864 865 ClientMap.App app = mClientMap.getByConnId(connId); 866 if (app != null) { 867 app.callback.onExecuteWrite(address, status); 868 } 869 } 870 871 void onReadDescriptor(int connId, int status, int srvcType, 872 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 873 int charInstId, long charUuidLsb, long charUuidMsb, 874 int descrInstId, long descrUuidLsb, long descrUuidMsb, 875 int charType, byte[] data) throws RemoteException { 876 877 UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 878 UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 879 UUID descrUuid = new UUID(descrUuidMsb, descrUuidLsb); 880 String address = mClientMap.addressByConnId(connId); 881 882 if (DBG) Log.d(TAG, "onReadDescriptor() - address=" + address 883 + ", status=" + status + ", length=" + data.length); 884 885 ClientMap.App app = mClientMap.getByConnId(connId); 886 if (app != null) { 887 app.callback.onDescriptorRead(address, status, srvcType, 888 srvcInstId, new ParcelUuid(srvcUuid), 889 charInstId, new ParcelUuid(charUuid), 890 descrInstId, new ParcelUuid(descrUuid), data); 891 } 892 } 893 894 void onWriteDescriptor(int connId, int status, int srvcType, 895 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 896 int charInstId, long charUuidLsb, long charUuidMsb, 897 int descrInstId, long descrUuidLsb, long descrUuidMsb) throws RemoteException { 898 899 UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 900 UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 901 UUID descrUuid = new UUID(descrUuidMsb, descrUuidLsb); 902 String address = mClientMap.addressByConnId(connId); 903 904 if (DBG) Log.d(TAG, "onWriteDescriptor() - address=" + address 905 + ", status=" + status); 906 907 ClientMap.App app = mClientMap.getByConnId(connId); 908 if (app != null) { 909 app.callback.onDescriptorWrite(address, status, srvcType, 910 srvcInstId, new ParcelUuid(srvcUuid), 911 charInstId, new ParcelUuid(charUuid), 912 descrInstId, new ParcelUuid(descrUuid)); 913 } 914 } 915 916 void onReadRemoteRssi(int clientIf, String address, 917 int rssi, int status) throws RemoteException{ 918 if (DBG) Log.d(TAG, "onReadRemoteRssi() - clientIf=" + clientIf + " address=" + 919 address + ", rssi=" + rssi + ", status=" + status); 920 921 ClientMap.App app = mClientMap.getById(clientIf); 922 if (app != null) { 923 app.callback.onReadRemoteRssi(address, rssi, status); 924 } 925 } 926 927 void onAdvertiseCallback(int status, int clientIf) throws RemoteException { 928 if (DBG) Log.d(TAG, "onClientListen() status=" + status); 929 synchronized (mLock) { 930 if (DBG) Log.d(TAG, "state" + mAdvertisingState); 931 // Invalid advertising state 932 if (mAdvertisingState == BluetoothAdapter.STATE_ADVERTISE_STARTED || 933 mAdvertisingState == BluetoothAdapter.STATE_ADVERTISE_STOPPED) { 934 Log.e(TAG, "invalid callback state " + mAdvertisingState); 935 return; 936 } 937 938 // Force stop advertising, no callback. 939 if (mAdvertisingState == BluetoothAdapter.STATE_ADVERTISE_FORCE_STOPPING) { 940 mAdvertisingState = BluetoothAdapter.STATE_ADVERTISE_STOPPED; 941 mAdvertisingClientIf = 0; 942 sendBroadcast(new Intent( 943 BluetoothAdapter.ACTION_BLUETOOTH_ADVERTISING_STOPPED)); 944 return; 945 } 946 947 if (mAdvertisingState == BluetoothAdapter.STATE_ADVERTISE_STARTING) { 948 if (status == 0) { 949 mAdvertisingClientIf = clientIf; 950 mAdvertisingState = BluetoothAdapter.STATE_ADVERTISE_STARTED; 951 sendBroadcast(new Intent( 952 BluetoothAdapter.ACTION_BLUETOOTH_ADVERTISING_STARTED)); 953 } else { 954 mAdvertisingState = BluetoothAdapter.STATE_ADVERTISE_STOPPED; 955 } 956 } else if (mAdvertisingState == BluetoothAdapter.STATE_ADVERTISE_STOPPING) { 957 if (status == 0) { 958 mAdvertisingState = BluetoothAdapter.STATE_ADVERTISE_STOPPED; 959 sendBroadcast(new Intent( 960 BluetoothAdapter.ACTION_BLUETOOTH_ADVERTISING_STOPPED)); 961 mAdvertisingClientIf = 0; 962 } else { 963 mAdvertisingState = BluetoothAdapter.STATE_ADVERTISE_STARTED; 964 } 965 } 966 } 967 ClientMap.App app = mClientMap.getById(clientIf); 968 if (app == null || app.callback == null) { 969 Log.e(TAG, "app or callback is null"); 970 return; 971 } 972 app.callback.onAdvertiseStateChange(mAdvertisingState, status); 973 } 974 975 void onConfigureMTU(int connId, int status, int mtu) throws RemoteException { 976 String address = mClientMap.addressByConnId(connId); 977 978 if (DBG) Log.d(TAG, "onConfigureMTU() address=" + address + ", status=" 979 + status + ", mtu=" + mtu); 980 981 ClientMap.App app = mClientMap.getByConnId(connId); 982 if (app != null) { 983 app.callback.onConfigureMTU(address, mtu, status); 984 } 985 } 986 987 /************************************************************************** 988 * GATT Service functions - Shared CLIENT/SERVER 989 *************************************************************************/ 990 991 List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 992 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 993 994 final int DEVICE_TYPE_BREDR = 0x1; 995 996 Map<BluetoothDevice, Integer> deviceStates = new HashMap<BluetoothDevice, 997 Integer>(); 998 999 // Add paired LE devices 1000 1001 Set<BluetoothDevice> bondedDevices = mAdapter.getBondedDevices(); 1002 for (BluetoothDevice device : bondedDevices) { 1003 if (getDeviceType(device) != DEVICE_TYPE_BREDR) { 1004 deviceStates.put(device, BluetoothProfile.STATE_DISCONNECTED); 1005 } 1006 } 1007 1008 // Add connected deviceStates 1009 1010 Set<String> connectedDevices = new HashSet<String>(); 1011 connectedDevices.addAll(mClientMap.getConnectedDevices()); 1012 connectedDevices.addAll(mServerMap.getConnectedDevices()); 1013 1014 for (String address : connectedDevices ) { 1015 BluetoothDevice device = mAdapter.getRemoteDevice(address); 1016 if (device != null) { 1017 deviceStates.put(device, BluetoothProfile.STATE_CONNECTED); 1018 } 1019 } 1020 1021 // Create matching device sub-set 1022 1023 List<BluetoothDevice> deviceList = new ArrayList<BluetoothDevice>(); 1024 1025 for (Map.Entry<BluetoothDevice, Integer> entry : deviceStates.entrySet()) { 1026 for(int state : states) { 1027 if (entry.getValue() == state) { 1028 deviceList.add(entry.getKey()); 1029 } 1030 } 1031 } 1032 1033 return deviceList; 1034 } 1035 1036 void startScan(int appIf, boolean isServer) { 1037 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); 1038 1039 if (DBG) Log.d(TAG, "startScan() - queue=" + mScanQueue.size()); 1040 1041 if (getScanClient(appIf, isServer) == null) { 1042 if (DBG) Log.d(TAG, "startScan() - adding client=" + appIf); 1043 mScanQueue.add(new ScanClient(appIf, isServer)); 1044 } 1045 1046 gattClientScanNative(appIf, true); 1047 } 1048 1049 void startScanWithUuids(int appIf, boolean isServer, UUID[] uuids) { 1050 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); 1051 1052 if (DBG) Log.d(TAG, "startScanWithUuids() - queue=" + mScanQueue.size()); 1053 1054 if (getScanClient(appIf, isServer) == null) { 1055 if (DBG) Log.d(TAG, "startScanWithUuids() - adding client=" + appIf); 1056 mScanQueue.add(new ScanClient(appIf, isServer, uuids)); 1057 } 1058 1059 gattClientScanNative(appIf, true); 1060 } 1061 1062 void stopScan(int appIf, boolean isServer) { 1063 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH_ADMIN permission"); 1064 1065 if (DBG) Log.d(TAG, "stopScan() - queue=" + mScanQueue.size()); 1066 removeScanClient(appIf, isServer); 1067 1068 if (mScanQueue.isEmpty()) { 1069 if (DBG) Log.d(TAG, "stopScan() - queue empty; stopping scan"); 1070 gattClientScanNative(appIf, false); 1071 } 1072 } 1073 1074 /************************************************************************** 1075 * GATT Service functions - CLIENT 1076 *************************************************************************/ 1077 1078 void registerClient(UUID uuid, IBluetoothGattCallback callback) { 1079 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1080 1081 if (DBG) Log.d(TAG, "registerClient() - UUID=" + uuid); 1082 mClientMap.add(uuid, callback); 1083 gattClientRegisterAppNative(uuid.getLeastSignificantBits(), 1084 uuid.getMostSignificantBits()); 1085 } 1086 1087 void unregisterClient(int clientIf) { 1088 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1089 1090 if (DBG) Log.d(TAG, "unregisterClient() - clientIf=" + clientIf); 1091 mClientMap.remove(clientIf); 1092 gattClientUnregisterAppNative(clientIf); 1093 } 1094 1095 void clientConnect(int clientIf, String address, boolean isDirect, int transport) { 1096 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1097 1098 if (DBG) Log.d(TAG, "clientConnect() - address=" + address + ", isDirect=" + isDirect); 1099 gattClientConnectNative(clientIf, address, isDirect, transport); 1100 } 1101 1102 void clientDisconnect(int clientIf, String address) { 1103 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1104 1105 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1106 if (DBG) Log.d(TAG, "clientDisconnect() - address=" + address + ", connId=" + connId); 1107 1108 gattClientDisconnectNative(clientIf, address, connId != null ? connId : 0); 1109 } 1110 1111 synchronized boolean setAdvServiceData(byte[] serviceData) { 1112 enforcePrivilegedPermission(); 1113 if (serviceData == null) return false; 1114 // Calculate how many more bytes are needed for advertising service data field. 1115 int extraBytes = (mServiceData == null) ? 1116 FIELD_OVERHEAD_BYTES + serviceData.length : 1117 serviceData.length - mServiceData.length; 1118 if (getAvailableSize() < extraBytes) { 1119 Log.e(TAG, "cannot set service data, available size " + getAvailableSize()); 1120 return false; 1121 } 1122 mServiceData = serviceData; 1123 return true; 1124 } 1125 1126 byte[] getAdvServiceData() { 1127 enforcePrivilegedPermission(); 1128 return mServiceData; 1129 } 1130 1131 synchronized boolean setAdvManufacturerCodeAndData( 1132 int manufacturerCode, byte[] manufacturerData) { 1133 enforcePrivilegedPermission(); 1134 if (manufacturerCode <= 0 || manufacturerData == null) { 1135 return false; 1136 } 1137 if (mManufacturerCode > 0 && mManufacturerData != null) { 1138 Log.e(TAG, "manufacture data is already set"); 1139 return false; 1140 } 1141 if (getAvailableSize() < 1142 FIELD_OVERHEAD_BYTES + manufacturerData.length) { 1143 Log.e(TAG, "cannot set manu data, available size " + getAvailableSize()); 1144 return false; 1145 } 1146 this.mManufacturerCode = manufacturerCode; 1147 this.mManufacturerData = manufacturerData; 1148 return true; 1149 } 1150 1151 void removeAdvManufacturerCodeAndData(int manufacturerCode) { 1152 enforcePrivilegedPermission(); 1153 if (mManufacturerCode != manufacturerCode) { 1154 return; 1155 } 1156 mManufacturerCode = -1; 1157 mManufacturerData = new byte[0]; 1158 } 1159 1160 byte[] getAdvManufacturerData() { 1161 enforcePrivilegedPermission(); 1162 return mManufacturerData; 1163 } 1164 1165 synchronized List<ParcelUuid> getAdvServiceUuids() { 1166 enforcePrivilegedPermission();; 1167 boolean fullUuidFound = false; 1168 List<ParcelUuid> serviceUuids = new ArrayList<ParcelUuid>(); 1169 for (HandleMap.Entry entry : mHandleMap.mEntries) { 1170 if (entry.advertisePreferred) { 1171 ParcelUuid parcelUuid = new ParcelUuid(entry.uuid); 1172 if (BluetoothUuid.isShortUuid(parcelUuid)) { 1173 serviceUuids.add(parcelUuid); 1174 } else { 1175 // Allow at most one 128 bit service uuid to be advertised. 1176 if (!fullUuidFound) { 1177 fullUuidFound = true; 1178 serviceUuids.add(parcelUuid); 1179 } 1180 } 1181 } 1182 } 1183 return serviceUuids; 1184 } 1185 1186 boolean isAdvertising() { 1187 enforcePrivilegedPermission(); 1188 return mAdvertisingState != BluetoothAdapter.STATE_ADVERTISE_STOPPED; 1189 } 1190 1191 void startAdvertising(int clientIf) { 1192 enforcePrivilegedPermission(); 1193 if (DBG) Log.d(TAG, "start advertising for app - " + clientIf); 1194 List<ParcelUuid> serviceUuids = getAdvServiceUuids(); 1195 int advertisingServiceUuidLength = serviceUuids == null ? 0 : serviceUuids.size(); 1196 1197 // Note according to Bluetooth Spec Version 4.0, for advertising and scan response data 1198 // "all numerical multi-byte entities and values shall use little-endian byte order". 1199 ByteBuffer advertisingUuidBytes = ByteBuffer.allocate(advertisingServiceUuidLength * 16) 1200 .order(ByteOrder.LITTLE_ENDIAN); 1201 for (ParcelUuid parcelUuid : serviceUuids) { 1202 UUID uuid = parcelUuid.getUuid(); 1203 // Least signifcant bits first as the advertising uuid should be in little-endian. 1204 advertisingUuidBytes.putLong(uuid.getLeastSignificantBits()) 1205 .putLong(uuid.getMostSignificantBits()); 1206 } 1207 1208 // Set advertising data. 1209 gattSetAdvDataNative(clientIf, 1210 false, // not scan response data 1211 false, // no device name 1212 false, // no tx power included 1213 DEFAULT_SCAN_INTERVAL_MILLIS, 1214 DEFAULT_SCAN_INTERVAL_MILLIS, 1215 0, // no appearance limit 1216 mManufacturerData, 1217 mServiceData, 1218 advertisingUuidBytes.array()); 1219 1220 // Start advertising if advertising is not already started. 1221 if (!isAdvertising()) { 1222 gattAdvertiseNative(clientIf, true); 1223 mAdvertisingClientIf = clientIf; 1224 mAdvertisingState = BluetoothAdapter.STATE_ADVERTISE_STARTING; 1225 } 1226 } 1227 1228 void stopAdvertising() { 1229 stopAdvertising(false); 1230 } 1231 1232 void stopAdvertising(boolean forceStop) { 1233 enforcePrivilegedPermission(); 1234 gattAdvertiseNative(mAdvertisingClientIf, false); 1235 synchronized (mLock) { 1236 if (forceStop) { 1237 mAdvertisingState = BluetoothAdapter.STATE_ADVERTISE_FORCE_STOPPING; 1238 } else { 1239 mAdvertisingState = BluetoothAdapter.STATE_ADVERTISE_STOPPING; 1240 } 1241 } 1242 } 1243 1244 List<String> getConnectedDevices() { 1245 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1246 1247 Set<String> connectedDevAddress = new HashSet<String>(); 1248 connectedDevAddress.addAll(mClientMap.getConnectedDevices()); 1249 connectedDevAddress.addAll(mServerMap.getConnectedDevices()); 1250 List<String> connectedDeviceList = new ArrayList<String>(connectedDevAddress); 1251 return connectedDeviceList; 1252 } 1253 1254 void refreshDevice(int clientIf, String address) { 1255 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1256 1257 if (DBG) Log.d(TAG, "refreshDevice() - address=" + address); 1258 gattClientRefreshNative(clientIf, address); 1259 } 1260 1261 void discoverServices(int clientIf, String address) { 1262 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1263 1264 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1265 if (DBG) Log.d(TAG, "discoverServices() - address=" + address + ", connId=" + connId); 1266 1267 if (connId != null) 1268 gattClientSearchServiceNative(connId, true, 0, 0); 1269 else 1270 Log.e(TAG, "discoverServices() - No connection for " + address + "..."); 1271 } 1272 1273 void readCharacteristic(int clientIf, String address, int srvcType, 1274 int srvcInstanceId, UUID srvcUuid, 1275 int charInstanceId, UUID charUuid, int authReq) { 1276 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1277 1278 if (DBG) Log.d(TAG, "readCharacteristic() - address=" + address); 1279 1280 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1281 if (connId != null) 1282 gattClientReadCharacteristicNative(connId, srvcType, 1283 srvcInstanceId, srvcUuid.getLeastSignificantBits(), 1284 srvcUuid.getMostSignificantBits(), charInstanceId, 1285 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1286 authReq); 1287 else 1288 Log.e(TAG, "readCharacteristic() - No connection for " + address + "..."); 1289 } 1290 1291 void writeCharacteristic(int clientIf, String address, int srvcType, 1292 int srvcInstanceId, UUID srvcUuid, 1293 int charInstanceId, UUID charUuid, int writeType, 1294 int authReq, byte[] value) { 1295 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1296 1297 if (DBG) Log.d(TAG, "writeCharacteristic() - address=" + address); 1298 1299 if (mReliableQueue.contains(address)) writeType = 3; // Prepared write 1300 1301 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1302 if (connId != null) 1303 gattClientWriteCharacteristicNative(connId, srvcType, 1304 srvcInstanceId, srvcUuid.getLeastSignificantBits(), 1305 srvcUuid.getMostSignificantBits(), charInstanceId, 1306 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1307 writeType, authReq, value); 1308 else 1309 Log.e(TAG, "writeCharacteristic() - No connection for " + address + "..."); 1310 } 1311 1312 void readDescriptor(int clientIf, String address, int srvcType, 1313 int srvcInstanceId, UUID srvcUuid, 1314 int charInstanceId, UUID charUuid, 1315 int descrInstanceId, UUID descrUuid, 1316 int authReq) { 1317 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1318 1319 if (DBG) Log.d(TAG, "readDescriptor() - address=" + address); 1320 1321 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1322 if (connId != null) 1323 gattClientReadDescriptorNative(connId, srvcType, 1324 srvcInstanceId, 1325 srvcUuid.getLeastSignificantBits(), srvcUuid.getMostSignificantBits(), 1326 charInstanceId, 1327 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1328 descrInstanceId, 1329 descrUuid.getLeastSignificantBits(), descrUuid.getMostSignificantBits(), 1330 authReq); 1331 else 1332 Log.e(TAG, "readDescriptor() - No connection for " + address + "..."); 1333 }; 1334 1335 void writeDescriptor(int clientIf, String address, int srvcType, 1336 int srvcInstanceId, UUID srvcUuid, 1337 int charInstanceId, UUID charUuid, 1338 int descrInstanceId, UUID descrUuid, 1339 int writeType, int authReq, byte[] value) { 1340 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1341 1342 if (DBG) Log.d(TAG, "writeDescriptor() - address=" + address); 1343 1344 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1345 if (connId != null) 1346 gattClientWriteDescriptorNative(connId, srvcType, 1347 srvcInstanceId, 1348 srvcUuid.getLeastSignificantBits(), srvcUuid.getMostSignificantBits(), 1349 charInstanceId, 1350 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1351 descrInstanceId, 1352 descrUuid.getLeastSignificantBits(), descrUuid.getMostSignificantBits(), 1353 writeType, authReq, value); 1354 else 1355 Log.e(TAG, "writeDescriptor() - No connection for " + address + "..."); 1356 } 1357 1358 void beginReliableWrite(int clientIf, String address) { 1359 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1360 1361 if (DBG) Log.d(TAG, "beginReliableWrite() - address=" + address); 1362 mReliableQueue.add(address); 1363 } 1364 1365 void endReliableWrite(int clientIf, String address, boolean execute) { 1366 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1367 1368 if (DBG) Log.d(TAG, "endReliableWrite() - address=" + address 1369 + " execute: " + execute); 1370 mReliableQueue.remove(address); 1371 1372 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1373 if (connId != null) gattClientExecuteWriteNative(connId, execute); 1374 } 1375 1376 void registerForNotification(int clientIf, String address, int srvcType, 1377 int srvcInstanceId, UUID srvcUuid, 1378 int charInstanceId, UUID charUuid, 1379 boolean enable) { 1380 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1381 1382 if (DBG) Log.d(TAG, "registerForNotification() - address=" + address + " enable: " + enable); 1383 1384 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1385 if (connId != null) { 1386 gattClientRegisterForNotificationsNative(clientIf, address, 1387 srvcType, srvcInstanceId, srvcUuid.getLeastSignificantBits(), 1388 srvcUuid.getMostSignificantBits(), charInstanceId, 1389 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1390 enable); 1391 } else { 1392 Log.e(TAG, "registerForNotification() - No connection for " + address + "..."); 1393 } 1394 } 1395 1396 void readRemoteRssi(int clientIf, String address) { 1397 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1398 1399 if (DBG) Log.d(TAG, "readRemoteRssi() - address=" + address); 1400 gattClientReadRemoteRssiNative(clientIf, address); 1401 } 1402 1403 void configureMTU(int clientIf, String address, int mtu) { 1404 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1405 1406 if (DBG) Log.d(TAG, "configureMTU() - address=" + address + " mtu=" + mtu); 1407 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1408 if (connId != null) { 1409 gattClientConfigureMTUNative(connId, mtu); 1410 } else { 1411 Log.e(TAG, "configureMTU() - No connection for " + address + "..."); 1412 } 1413 } 1414 1415 /************************************************************************** 1416 * Callback functions - SERVER 1417 *************************************************************************/ 1418 1419 void onServerRegistered(int status, int serverIf, long uuidLsb, long uuidMsb) 1420 throws RemoteException { 1421 1422 UUID uuid = new UUID(uuidMsb, uuidLsb); 1423 if (DBG) Log.d(TAG, "onServerRegistered() - UUID=" + uuid + ", serverIf=" + serverIf); 1424 ServerMap.App app = mServerMap.getByUuid(uuid); 1425 if (app != null) { 1426 app.id = serverIf; 1427 app.linkToDeath(new ServerDeathRecipient(serverIf)); 1428 app.callback.onServerRegistered(status, serverIf); 1429 } 1430 } 1431 1432 void onServiceAdded(int status, int serverIf, int srvcType, int srvcInstId, 1433 long srvcUuidLsb, long srvcUuidMsb, int srvcHandle) 1434 throws RemoteException { 1435 UUID uuid = new UUID(srvcUuidMsb, srvcUuidLsb); 1436 if (DBG) Log.d(TAG, "onServiceAdded() UUID=" + uuid + ", status=" + status 1437 + ", handle=" + srvcHandle); 1438 if (status == 0) { 1439 mHandleMap.addService(serverIf, srvcHandle, uuid, srvcType, srvcInstId, 1440 mAdvertisingServiceUuids.remove(uuid)); 1441 } 1442 1443 continueServiceDeclaration(serverIf, status, srvcHandle); 1444 } 1445 1446 void onIncludedServiceAdded(int status, int serverIf, int srvcHandle, 1447 int includedSrvcHandle) throws RemoteException { 1448 if (DBG) Log.d(TAG, "onIncludedServiceAdded() status=" + status 1449 + ", service=" + srvcHandle + ", included=" + includedSrvcHandle); 1450 continueServiceDeclaration(serverIf, status, srvcHandle); 1451 } 1452 1453 void onCharacteristicAdded(int status, int serverIf, 1454 long charUuidLsb, long charUuidMsb, 1455 int srvcHandle, int charHandle) 1456 throws RemoteException { 1457 UUID uuid = new UUID(charUuidMsb, charUuidLsb); 1458 if (DBG) Log.d(TAG, "onCharacteristicAdded() UUID=" + uuid + ", status=" + status 1459 + ", srvcHandle=" + srvcHandle + ", charHandle=" + charHandle); 1460 if (status == 0) 1461 mHandleMap.addCharacteristic(serverIf, charHandle, uuid, srvcHandle); 1462 continueServiceDeclaration(serverIf, status, srvcHandle); 1463 } 1464 1465 void onDescriptorAdded(int status, int serverIf, 1466 long descrUuidLsb, long descrUuidMsb, 1467 int srvcHandle, int descrHandle) 1468 throws RemoteException { 1469 UUID uuid = new UUID(descrUuidMsb, descrUuidLsb); 1470 if (DBG) Log.d(TAG, "onDescriptorAdded() UUID=" + uuid + ", status=" + status 1471 + ", srvcHandle=" + srvcHandle + ", descrHandle=" + descrHandle); 1472 if (status == 0) 1473 mHandleMap.addDescriptor(serverIf, descrHandle, uuid, srvcHandle); 1474 continueServiceDeclaration(serverIf, status, srvcHandle); 1475 } 1476 1477 void onServiceStarted(int status, int serverIf, int srvcHandle) 1478 throws RemoteException { 1479 if (DBG) Log.d(TAG, "onServiceStarted() srvcHandle=" + srvcHandle 1480 + ", status=" + status); 1481 if (status == 0) 1482 mHandleMap.setStarted(serverIf, srvcHandle, true); 1483 } 1484 1485 void onServiceStopped(int status, int serverIf, int srvcHandle) 1486 throws RemoteException { 1487 if (DBG) Log.d(TAG, "onServiceStopped() srvcHandle=" + srvcHandle 1488 + ", status=" + status); 1489 if (status == 0) 1490 mHandleMap.setStarted(serverIf, srvcHandle, false); 1491 stopNextService(serverIf, status); 1492 } 1493 1494 void onServiceDeleted(int status, int serverIf, int srvcHandle) { 1495 if (DBG) Log.d(TAG, "onServiceDeleted() srvcHandle=" + srvcHandle 1496 + ", status=" + status); 1497 mHandleMap.deleteService(serverIf, srvcHandle); 1498 } 1499 1500 void onClientConnected(String address, boolean connected, int connId, int serverIf) 1501 throws RemoteException { 1502 1503 if (DBG) Log.d(TAG, "onConnected() connId=" + connId 1504 + ", address=" + address + ", connected=" + connected); 1505 1506 ServerMap.App app = mServerMap.getById(serverIf); 1507 if (app == null) return; 1508 1509 if (connected) { 1510 mServerMap.addConnection(serverIf, connId, address); 1511 } else { 1512 mServerMap.removeConnection(serverIf, connId); 1513 } 1514 1515 app.callback.onServerConnectionState((byte)0, serverIf, connected, address); 1516 } 1517 1518 void onAttributeRead(String address, int connId, int transId, 1519 int attrHandle, int offset, boolean isLong) 1520 throws RemoteException { 1521 if (DBG) Log.d(TAG, "onAttributeRead() connId=" + connId 1522 + ", address=" + address + ", handle=" + attrHandle 1523 + ", requestId=" + transId + ", offset=" + offset); 1524 1525 HandleMap.Entry entry = mHandleMap.getByHandle(attrHandle); 1526 if (entry == null) return; 1527 1528 if (DBG) Log.d(TAG, "onAttributeRead() UUID=" + entry.uuid 1529 + ", serverIf=" + entry.serverIf + ", type=" + entry.type); 1530 1531 mHandleMap.addRequest(transId, attrHandle); 1532 1533 ServerMap.App app = mServerMap.getById(entry.serverIf); 1534 if (app == null) return; 1535 1536 switch(entry.type) { 1537 case HandleMap.TYPE_CHARACTERISTIC: 1538 { 1539 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1540 app.callback.onCharacteristicReadRequest(address, transId, offset, isLong, 1541 serviceEntry.serviceType, serviceEntry.instance, 1542 new ParcelUuid(serviceEntry.uuid), entry.instance, 1543 new ParcelUuid(entry.uuid)); 1544 break; 1545 } 1546 1547 case HandleMap.TYPE_DESCRIPTOR: 1548 { 1549 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1550 HandleMap.Entry charEntry = mHandleMap.getByHandle(entry.charHandle); 1551 app.callback.onDescriptorReadRequest(address, transId, offset, isLong, 1552 serviceEntry.serviceType, serviceEntry.instance, 1553 new ParcelUuid(serviceEntry.uuid), charEntry.instance, 1554 new ParcelUuid(charEntry.uuid), 1555 new ParcelUuid(entry.uuid)); 1556 break; 1557 } 1558 1559 default: 1560 Log.e(TAG, "onAttributeRead() - Requested unknown attribute type."); 1561 break; 1562 } 1563 } 1564 1565 void onAttributeWrite(String address, int connId, int transId, 1566 int attrHandle, int offset, int length, 1567 boolean needRsp, boolean isPrep, 1568 byte[] data) 1569 throws RemoteException { 1570 if (DBG) Log.d(TAG, "onAttributeWrite() connId=" + connId 1571 + ", address=" + address + ", handle=" + attrHandle 1572 + ", requestId=" + transId + ", isPrep=" + isPrep 1573 + ", offset=" + offset); 1574 1575 HandleMap.Entry entry = mHandleMap.getByHandle(attrHandle); 1576 if (entry == null) return; 1577 1578 if (DBG) Log.d(TAG, "onAttributeWrite() UUID=" + entry.uuid 1579 + ", serverIf=" + entry.serverIf + ", type=" + entry.type); 1580 1581 mHandleMap.addRequest(transId, attrHandle); 1582 1583 ServerMap.App app = mServerMap.getById(entry.serverIf); 1584 if (app == null) return; 1585 1586 switch(entry.type) { 1587 case HandleMap.TYPE_CHARACTERISTIC: 1588 { 1589 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1590 app.callback.onCharacteristicWriteRequest(address, transId, 1591 offset, length, isPrep, needRsp, 1592 serviceEntry.serviceType, serviceEntry.instance, 1593 new ParcelUuid(serviceEntry.uuid), entry.instance, 1594 new ParcelUuid(entry.uuid), data); 1595 break; 1596 } 1597 1598 case HandleMap.TYPE_DESCRIPTOR: 1599 { 1600 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1601 HandleMap.Entry charEntry = mHandleMap.getByHandle(entry.charHandle); 1602 app.callback.onDescriptorWriteRequest(address, transId, 1603 offset, length, isPrep, needRsp, 1604 serviceEntry.serviceType, serviceEntry.instance, 1605 new ParcelUuid(serviceEntry.uuid), charEntry.instance, 1606 new ParcelUuid(charEntry.uuid), 1607 new ParcelUuid(entry.uuid), data); 1608 break; 1609 } 1610 1611 default: 1612 Log.e(TAG, "onAttributeWrite() - Requested unknown attribute type."); 1613 break; 1614 } 1615 } 1616 1617 void onExecuteWrite(String address, int connId, int transId, int execWrite) 1618 throws RemoteException { 1619 if (DBG) Log.d(TAG, "onExecuteWrite() connId=" + connId 1620 + ", address=" + address + ", transId=" + transId); 1621 1622 ServerMap.App app = mServerMap.getByConnId(connId); 1623 if (app == null) return; 1624 1625 app.callback.onExecuteWrite(address, transId, execWrite == 1); 1626 } 1627 1628 void onResponseSendCompleted(int status, int attrHandle) { 1629 if (DBG) Log.d(TAG, "onResponseSendCompleted() handle=" + attrHandle); 1630 } 1631 1632 /************************************************************************** 1633 * GATT Service functions - SERVER 1634 *************************************************************************/ 1635 1636 void registerServer(UUID uuid, IBluetoothGattServerCallback callback) { 1637 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1638 1639 if (DBG) Log.d(TAG, "registerServer() - UUID=" + uuid); 1640 mServerMap.add(uuid, callback); 1641 gattServerRegisterAppNative(uuid.getLeastSignificantBits(), 1642 uuid.getMostSignificantBits()); 1643 } 1644 1645 void unregisterServer(int serverIf) { 1646 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1647 1648 if (DBG) Log.d(TAG, "unregisterServer() - serverIf=" + serverIf); 1649 1650 deleteServices(serverIf); 1651 1652 mServerMap.remove(serverIf); 1653 gattServerUnregisterAppNative(serverIf); 1654 } 1655 1656 void serverConnect(int serverIf, String address, boolean isDirect, int transport) { 1657 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1658 1659 if (DBG) Log.d(TAG, "serverConnect() - address=" + address); 1660 gattServerConnectNative(serverIf, address, isDirect,transport); 1661 } 1662 1663 void serverDisconnect(int serverIf, String address) { 1664 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1665 1666 Integer connId = mServerMap.connIdByAddress(serverIf, address); 1667 if (DBG) Log.d(TAG, "serverDisconnect() - address=" + address + ", connId=" + connId); 1668 1669 gattServerDisconnectNative(serverIf, address, connId != null ? connId : 0); 1670 } 1671 1672 void beginServiceDeclaration(int serverIf, int srvcType, int srvcInstanceId, 1673 int minHandles, UUID srvcUuid, boolean advertisePreferred) { 1674 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1675 1676 if (DBG) Log.d(TAG, "beginServiceDeclaration() - uuid=" + srvcUuid); 1677 ServiceDeclaration serviceDeclaration = addDeclaration(); 1678 serviceDeclaration.addService(srvcUuid, srvcType, srvcInstanceId, minHandles, 1679 advertisePreferred); 1680 } 1681 1682 void addIncludedService(int serverIf, int srvcType, int srvcInstanceId, 1683 UUID srvcUuid) { 1684 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1685 1686 if (DBG) Log.d(TAG, "addIncludedService() - uuid=" + srvcUuid); 1687 getActiveDeclaration().addIncludedService(srvcUuid, srvcType, srvcInstanceId); 1688 } 1689 1690 void addCharacteristic(int serverIf, UUID charUuid, int properties, 1691 int permissions) { 1692 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1693 1694 if (DBG) Log.d(TAG, "addCharacteristic() - uuid=" + charUuid); 1695 getActiveDeclaration().addCharacteristic(charUuid, properties, permissions); 1696 } 1697 1698 void addDescriptor(int serverIf, UUID descUuid, int permissions) { 1699 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1700 1701 if (DBG) Log.d(TAG, "addDescriptor() - uuid=" + descUuid); 1702 getActiveDeclaration().addDescriptor(descUuid, permissions); 1703 } 1704 1705 void endServiceDeclaration(int serverIf) { 1706 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1707 1708 if (DBG) Log.d(TAG, "endServiceDeclaration()"); 1709 1710 if (getActiveDeclaration() == getPendingDeclaration()) { 1711 try { 1712 continueServiceDeclaration(serverIf, (byte)0, 0); 1713 } catch (RemoteException e) { 1714 Log.e(TAG,""+e); 1715 } 1716 } 1717 } 1718 1719 void removeService(int serverIf, int srvcType, 1720 int srvcInstanceId, UUID srvcUuid) { 1721 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1722 1723 if (DBG) Log.d(TAG, "removeService() - uuid=" + srvcUuid); 1724 1725 int srvcHandle = mHandleMap.getServiceHandle(srvcUuid, srvcType, srvcInstanceId); 1726 if (srvcHandle == 0) return; 1727 gattServerDeleteServiceNative(serverIf, srvcHandle); 1728 } 1729 1730 void clearServices(int serverIf) { 1731 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1732 1733 if (DBG) Log.d(TAG, "clearServices()"); 1734 deleteServices(serverIf); 1735 } 1736 1737 void sendResponse(int serverIf, String address, int requestId, 1738 int status, int offset, byte[] value) { 1739 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1740 1741 if (DBG) Log.d(TAG, "sendResponse() - address=" + address); 1742 1743 int handle = 0; 1744 HandleMap.Entry entry = mHandleMap.getByRequestId(requestId); 1745 if (entry != null) handle = entry.handle; 1746 1747 int connId = mServerMap.connIdByAddress(serverIf, address); 1748 gattServerSendResponseNative(serverIf, connId, requestId, (byte)status, 1749 handle, offset, value, (byte)0); 1750 mHandleMap.deleteRequest(requestId); 1751 } 1752 1753 void sendNotification(int serverIf, String address, int srvcType, 1754 int srvcInstanceId, UUID srvcUuid, 1755 int charInstanceId, UUID charUuid, 1756 boolean confirm, byte[] value) { 1757 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1758 1759 if (DBG) Log.d(TAG, "sendNotification() - address=" + address); 1760 1761 int srvcHandle = mHandleMap.getServiceHandle(srvcUuid, srvcType, srvcInstanceId); 1762 if (srvcHandle == 0) return; 1763 1764 int charHandle = mHandleMap.getCharacteristicHandle(srvcHandle, charUuid, charInstanceId); 1765 if (charHandle == 0) return; 1766 1767 int connId = mServerMap.connIdByAddress(serverIf, address); 1768 if (connId == 0) return; 1769 1770 if (confirm) { 1771 gattServerSendIndicationNative(serverIf, charHandle, connId, value); 1772 } else { 1773 gattServerSendNotificationNative(serverIf, charHandle, connId, value); 1774 } 1775 } 1776 1777 1778 /************************************************************************** 1779 * Private functions 1780 *************************************************************************/ 1781 1782 private int getDeviceType(BluetoothDevice device) { 1783 int type = gattClientGetDeviceTypeNative(device.getAddress()); 1784 if (DBG) Log.d(TAG, "getDeviceType() - device=" + device 1785 + ", type=" + type); 1786 return type; 1787 } 1788 1789 private synchronized int getAvailableSize() { 1790 enforcePrivilegedPermission(); 1791 int availableSize = ADVERTISING_PACKET_MAX_BYTES - ADVERTISING_FLAGS_BYTES; 1792 1793 for (ParcelUuid parcelUuid : getAdvServiceUuids()) { 1794 if (BluetoothUuid.isShortUuid(parcelUuid)) { 1795 availableSize -= FIELD_OVERHEAD_BYTES + SHORT_UUID_BYTES; 1796 } else { 1797 availableSize -= FIELD_OVERHEAD_BYTES + FULL_UUID_BYTES; 1798 } 1799 } 1800 if (mManufacturerCode > 0 && mManufacturerData != null) { 1801 availableSize -= (FIELD_OVERHEAD_BYTES + mManufacturerData.length); 1802 } 1803 if (mServiceData != null) { 1804 availableSize -= (FIELD_OVERHEAD_BYTES + mServiceData.length); 1805 } 1806 return availableSize; 1807 } 1808 1809 // Enforce caller has BLUETOOTH_PRIVILEGED permission. A {@link SecurityException} will be 1810 // thrown if the caller app does not have BLUETOOTH_PRIVILEGED permission. 1811 private void enforcePrivilegedPermission() { 1812 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, 1813 "Need BLUETOOTH_PRIVILEGED permission"); 1814 } 1815 1816 private void continueSearch(int connId, int status) throws RemoteException { 1817 if (status == 0 && !mSearchQueue.isEmpty()) { 1818 SearchQueue.Entry svc = mSearchQueue.pop(); 1819 1820 if (svc.charUuidLsb == 0) { 1821 // Characteristic is up next 1822 gattClientGetCharacteristicNative(svc.connId, svc.srvcType, 1823 svc.srvcInstId, svc.srvcUuidLsb, svc.srvcUuidMsb, 0, 0, 0); 1824 } else { 1825 // Descriptor is up next 1826 gattClientGetDescriptorNative(svc.connId, svc.srvcType, 1827 svc.srvcInstId, svc.srvcUuidLsb, svc.srvcUuidMsb, 1828 svc.charInstId, svc.charUuidLsb, svc.charUuidMsb, 0, 0, 0); 1829 } 1830 } else { 1831 ClientMap.App app = mClientMap.getByConnId(connId); 1832 if (app != null) { 1833 app.callback.onSearchComplete(mClientMap.addressByConnId(connId), status); 1834 } 1835 } 1836 } 1837 1838 private void continueServiceDeclaration(int serverIf, int status, int srvcHandle) throws RemoteException { 1839 if (mServiceDeclarations.size() == 0) return; 1840 if (DBG) Log.d(TAG, "continueServiceDeclaration() - srvcHandle=" + srvcHandle); 1841 1842 boolean finished = false; 1843 1844 ServiceDeclaration.Entry entry = null; 1845 if (status == 0) 1846 entry = getPendingDeclaration().getNext(); 1847 1848 if (entry != null) { 1849 if (DBG) Log.d(TAG, "continueServiceDeclaration() - next entry type=" 1850 + entry.type); 1851 switch(entry.type) { 1852 case ServiceDeclaration.TYPE_SERVICE: 1853 if (entry.advertisePreferred) { 1854 mAdvertisingServiceUuids.add(entry.uuid); 1855 } 1856 gattServerAddServiceNative(serverIf, entry.serviceType, 1857 entry.instance, 1858 entry.uuid.getLeastSignificantBits(), 1859 entry.uuid.getMostSignificantBits(), 1860 getPendingDeclaration().getNumHandles()); 1861 break; 1862 1863 case ServiceDeclaration.TYPE_CHARACTERISTIC: 1864 gattServerAddCharacteristicNative(serverIf, srvcHandle, 1865 entry.uuid.getLeastSignificantBits(), 1866 entry.uuid.getMostSignificantBits(), 1867 entry.properties, entry.permissions); 1868 break; 1869 1870 case ServiceDeclaration.TYPE_DESCRIPTOR: 1871 gattServerAddDescriptorNative(serverIf, srvcHandle, 1872 entry.uuid.getLeastSignificantBits(), 1873 entry.uuid.getMostSignificantBits(), 1874 entry.permissions); 1875 break; 1876 1877 case ServiceDeclaration.TYPE_INCLUDED_SERVICE: 1878 { 1879 int inclSrvc = mHandleMap.getServiceHandle(entry.uuid, 1880 entry.serviceType, entry.instance); 1881 if (inclSrvc != 0) { 1882 gattServerAddIncludedServiceNative(serverIf, srvcHandle, 1883 inclSrvc); 1884 } else { 1885 finished = true; 1886 } 1887 break; 1888 } 1889 } 1890 } else { 1891 gattServerStartServiceNative(serverIf, srvcHandle, 1892 (byte)BluetoothDevice.TRANSPORT_BREDR | BluetoothDevice.TRANSPORT_LE); 1893 finished = true; 1894 } 1895 1896 if (finished) { 1897 if (DBG) Log.d(TAG, "continueServiceDeclaration() - completed."); 1898 ServerMap.App app = mServerMap.getById(serverIf); 1899 if (app != null) { 1900 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(srvcHandle); 1901 1902 if (serviceEntry != null) { 1903 app.callback.onServiceAdded(status, serviceEntry.serviceType, 1904 serviceEntry.instance, new ParcelUuid(serviceEntry.uuid)); 1905 } else { 1906 app.callback.onServiceAdded(status, 0, 0, null); 1907 } 1908 } 1909 removePendingDeclaration(); 1910 1911 if (getPendingDeclaration() != null) { 1912 continueServiceDeclaration(serverIf, (byte)0, 0); 1913 } 1914 } 1915 } 1916 1917 private void stopNextService(int serverIf, int status) throws RemoteException { 1918 if (DBG) Log.d(TAG, "stopNextService() - serverIf=" + serverIf 1919 + ", status=" + status); 1920 1921 if (status == 0) { 1922 List<HandleMap.Entry> entries = mHandleMap.getEntries(); 1923 for(HandleMap.Entry entry : entries) { 1924 if (entry.type != HandleMap.TYPE_SERVICE || 1925 entry.serverIf != serverIf || 1926 entry.started == false) 1927 continue; 1928 1929 gattServerStopServiceNative(serverIf, entry.handle); 1930 return; 1931 } 1932 } 1933 } 1934 1935 private void deleteServices(int serverIf) { 1936 if (DBG) Log.d(TAG, "deleteServices() - serverIf=" + serverIf); 1937 1938 /* 1939 * Figure out which handles to delete. 1940 * The handles are copied into a new list to avoid race conditions. 1941 */ 1942 List<Integer> handleList = new ArrayList<Integer>(); 1943 List<HandleMap.Entry> entries = mHandleMap.getEntries(); 1944 for(HandleMap.Entry entry : entries) { 1945 if (entry.type != HandleMap.TYPE_SERVICE || 1946 entry.serverIf != serverIf) 1947 continue; 1948 handleList.add(entry.handle); 1949 } 1950 1951 /* Now actually delete the services.... */ 1952 for(Integer handle : handleList) { 1953 gattServerDeleteServiceNative(serverIf, handle); 1954 } 1955 } 1956 1957 private List<UUID> parseUuids(byte[] adv_data) { 1958 List<UUID> uuids = new ArrayList<UUID>(); 1959 1960 int offset = 0; 1961 while(offset < (adv_data.length-2)) { 1962 int len = adv_data[offset++]; 1963 if (len == 0) break; 1964 1965 int type = adv_data[offset++]; 1966 switch (type) { 1967 case 0x02: // Partial list of 16-bit UUIDs 1968 case 0x03: // Complete list of 16-bit UUIDs 1969 while (len > 1) { 1970 int uuid16 = adv_data[offset++]; 1971 uuid16 += (adv_data[offset++] << 8); 1972 len -= 2; 1973 uuids.add(UUID.fromString(String.format( 1974 "%08x-0000-1000-8000-00805f9b34fb", uuid16))); 1975 } 1976 break; 1977 1978 default: 1979 offset += (len - 1); 1980 break; 1981 } 1982 } 1983 1984 return uuids; 1985 } 1986 1987 /************************************************************************** 1988 * GATT Test functions 1989 *************************************************************************/ 1990 1991 void gattTestCommand(int command, UUID uuid1, String bda1, 1992 int p1, int p2, int p3, int p4, int p5) { 1993 if (bda1 == null) bda1 = "00:00:00:00:00:00"; 1994 if (uuid1 != null) 1995 gattTestNative(command, uuid1.getLeastSignificantBits(), 1996 uuid1.getMostSignificantBits(), bda1, p1, p2, p3, p4, p5); 1997 else 1998 gattTestNative(command, 0,0, bda1, p1, p2, p3, p4, p5); 1999 } 2000 2001 private native void gattTestNative(int command, 2002 long uuid1_lsb, long uuid1_msb, String bda1, 2003 int p1, int p2, int p3, int p4, int p5); 2004 2005 /************************************************************************** 2006 * Native functions prototypes 2007 *************************************************************************/ 2008 2009 private native static void classInitNative(); 2010 private native void initializeNative(); 2011 private native void cleanupNative(); 2012 2013 private native int gattClientGetDeviceTypeNative(String address); 2014 2015 private native void gattClientRegisterAppNative(long app_uuid_lsb, 2016 long app_uuid_msb); 2017 2018 private native void gattClientUnregisterAppNative(int clientIf); 2019 2020 private native void gattClientScanNative(int clientIf, boolean start); 2021 2022 private native void gattClientConnectNative(int clientIf, String address, 2023 boolean isDirect, int transport); 2024 2025 private native void gattClientDisconnectNative(int clientIf, String address, 2026 int conn_id); 2027 2028 private native void gattClientRefreshNative(int clientIf, String address); 2029 2030 private native void gattClientSearchServiceNative(int conn_id, 2031 boolean search_all, long service_uuid_lsb, long service_uuid_msb); 2032 2033 private native void gattClientGetCharacteristicNative(int conn_id, 2034 int service_type, int service_id_inst_id, long service_id_uuid_lsb, 2035 long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, 2036 long char_id_uuid_msb); 2037 2038 private native void gattClientGetDescriptorNative(int conn_id, int service_type, 2039 int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb, 2040 int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, 2041 int descr_id_inst_id, long descr_id_uuid_lsb, long descr_id_uuid_msb); 2042 2043 private native void gattClientGetIncludedServiceNative(int conn_id, 2044 int service_type, int service_id_inst_id, 2045 long service_id_uuid_lsb, long service_id_uuid_msb, 2046 int incl_service_id_inst_id, int incl_service_type, 2047 long incl_service_id_uuid_lsb, long incl_service_id_uuid_msb); 2048 2049 private native void gattClientReadCharacteristicNative(int conn_id, 2050 int service_type, int service_id_inst_id, long service_id_uuid_lsb, 2051 long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, 2052 long char_id_uuid_msb, int authReq); 2053 2054 private native void gattClientReadDescriptorNative(int conn_id, int service_type, 2055 int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb, 2056 int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, 2057 int descr_id_inst_id, long descr_id_uuid_lsb, long descr_id_uuid_msb, 2058 int authReq); 2059 2060 private native void gattClientWriteCharacteristicNative(int conn_id, 2061 int service_type, int service_id_inst_id, long service_id_uuid_lsb, 2062 long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, 2063 long char_id_uuid_msb, int write_type, int auth_req, byte[] value); 2064 2065 private native void gattClientWriteDescriptorNative(int conn_id, int service_type, 2066 int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb, 2067 int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, 2068 int descr_id_inst_id, long descr_id_uuid_lsb, long descr_id_uuid_msb, 2069 int write_type, int auth_req, byte[] value); 2070 2071 private native void gattClientExecuteWriteNative(int conn_id, boolean execute); 2072 2073 private native void gattClientRegisterForNotificationsNative(int clientIf, 2074 String address, int service_type, int service_id_inst_id, 2075 long service_id_uuid_lsb, long service_id_uuid_msb, 2076 int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, 2077 boolean enable); 2078 2079 private native void gattClientReadRemoteRssiNative(int clientIf, 2080 String address); 2081 2082 private native void gattAdvertiseNative(int client_if, boolean start); 2083 2084 private native void gattClientConfigureMTUNative(int conn_id, int mtu); 2085 2086 private native void gattSetAdvDataNative(int serverIf, boolean setScanRsp, boolean inclName, 2087 boolean inclTxPower, int minInterval, int maxInterval, 2088 int appearance, byte[] manufacturerData, byte[] serviceData, byte[] serviceUuid); 2089 2090 private native void gattServerRegisterAppNative(long app_uuid_lsb, 2091 long app_uuid_msb); 2092 2093 private native void gattServerUnregisterAppNative(int serverIf); 2094 2095 private native void gattServerConnectNative(int server_if, String address, 2096 boolean is_direct, int transport); 2097 2098 private native void gattServerDisconnectNative(int serverIf, String address, 2099 int conn_id); 2100 2101 private native void gattServerAddServiceNative (int server_if, 2102 int service_type, int service_id_inst_id, 2103 long service_id_uuid_lsb, long service_id_uuid_msb, 2104 int num_handles); 2105 2106 private native void gattServerAddIncludedServiceNative (int server_if, 2107 int svc_handle, int included_svc_handle); 2108 2109 private native void gattServerAddCharacteristicNative (int server_if, 2110 int svc_handle, long char_uuid_lsb, long char_uuid_msb, 2111 int properties, int permissions); 2112 2113 private native void gattServerAddDescriptorNative (int server_if, 2114 int svc_handle, long desc_uuid_lsb, long desc_uuid_msb, 2115 int permissions); 2116 2117 private native void gattServerStartServiceNative (int server_if, 2118 int svc_handle, int transport ); 2119 2120 private native void gattServerStopServiceNative (int server_if, 2121 int svc_handle); 2122 2123 private native void gattServerDeleteServiceNative (int server_if, 2124 int svc_handle); 2125 2126 private native void gattServerSendIndicationNative (int server_if, 2127 int attr_handle, int conn_id, byte[] val); 2128 2129 private native void gattServerSendNotificationNative (int server_if, 2130 int attr_handle, int conn_id, byte[] val); 2131 2132 private native void gattServerSendResponseNative (int server_if, 2133 int conn_id, int trans_id, int status, int handle, int offset, 2134 byte[] val, int auth_req); 2135} 2136