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