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