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