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