1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.bluetooth.gatt; 18 19 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 20 21 import android.app.AppOpsManager; 22 import android.app.PendingIntent; 23 import android.app.Service; 24 import android.bluetooth.BluetoothAdapter; 25 import android.bluetooth.BluetoothDevice; 26 import android.bluetooth.BluetoothGatt; 27 import android.bluetooth.BluetoothGattCharacteristic; 28 import android.bluetooth.BluetoothGattDescriptor; 29 import android.bluetooth.BluetoothGattService; 30 import android.bluetooth.BluetoothProfile; 31 import android.bluetooth.IBluetoothGatt; 32 import android.bluetooth.IBluetoothGattCallback; 33 import android.bluetooth.IBluetoothGattServerCallback; 34 import android.bluetooth.le.AdvertiseData; 35 import android.bluetooth.le.AdvertisingSetParameters; 36 import android.bluetooth.le.BluetoothLeScanner; 37 import android.bluetooth.le.IAdvertisingSetCallback; 38 import android.bluetooth.le.IPeriodicAdvertisingCallback; 39 import android.bluetooth.le.IScannerCallback; 40 import android.bluetooth.le.PeriodicAdvertisingParameters; 41 import android.bluetooth.le.ResultStorageDescriptor; 42 import android.bluetooth.le.ScanCallback; 43 import android.bluetooth.le.ScanFilter; 44 import android.bluetooth.le.ScanRecord; 45 import android.bluetooth.le.ScanResult; 46 import android.bluetooth.le.ScanSettings; 47 import android.content.Intent; 48 import android.os.Binder; 49 import android.os.IBinder; 50 import android.os.ParcelUuid; 51 import android.os.RemoteException; 52 import android.os.SystemClock; 53 import android.os.WorkSource; 54 import android.provider.Settings; 55 import android.util.Log; 56 57 import com.android.bluetooth.BluetoothMetricsProto; 58 import com.android.bluetooth.R; 59 import com.android.bluetooth.Utils; 60 import com.android.bluetooth.btservice.AbstractionLayer; 61 import com.android.bluetooth.btservice.AdapterService; 62 import com.android.bluetooth.btservice.ProfileService; 63 import com.android.bluetooth.util.NumberUtils; 64 import com.android.internal.annotations.VisibleForTesting; 65 66 import java.util.ArrayList; 67 import java.util.Arrays; 68 import java.util.Collections; 69 import java.util.HashMap; 70 import java.util.HashSet; 71 import java.util.List; 72 import java.util.Map; 73 import java.util.Set; 74 import java.util.UUID; 75 import java.util.concurrent.TimeUnit; 76 77 /** 78 * Provides Bluetooth Gatt profile, as a service in 79 * the Bluetooth application. 80 * @hide 81 */ 82 public class GattService extends ProfileService { 83 private static final boolean DBG = GattServiceConfig.DBG; 84 private static final boolean VDBG = GattServiceConfig.VDBG; 85 private static final String TAG = GattServiceConfig.TAG_PREFIX + "GattService"; 86 87 static final int SCAN_FILTER_ENABLED = 1; 88 static final int SCAN_FILTER_MODIFIED = 2; 89 90 private static final int MAC_ADDRESS_LENGTH = 6; 91 // Batch scan related constants. 92 private static final int TRUNCATED_RESULT_SIZE = 11; 93 private static final int TIME_STAMP_LENGTH = 2; 94 95 // onFoundLost related constants 96 private static final int ADVT_STATE_ONFOUND = 0; 97 private static final int ADVT_STATE_ONLOST = 1; 98 99 private static final int ET_LEGACY_MASK = 0x10; 100 101 private static final UUID[] HID_UUIDS = { 102 UUID.fromString("00002A4A-0000-1000-8000-00805F9B34FB"), 103 UUID.fromString("00002A4B-0000-1000-8000-00805F9B34FB"), 104 UUID.fromString("00002A4C-0000-1000-8000-00805F9B34FB"), 105 UUID.fromString("00002A4D-0000-1000-8000-00805F9B34FB") 106 }; 107 108 private static final UUID[] FIDO_UUIDS = { 109 UUID.fromString("0000FFFD-0000-1000-8000-00805F9B34FB") // U2F 110 }; 111 112 /** 113 * Keep the arguments passed in for the PendingIntent. 114 */ 115 class PendingIntentInfo { 116 public PendingIntent intent; 117 public ScanSettings settings; 118 public List<ScanFilter> filters; 119 public String callingPackage; 120 121 @Override 122 public boolean equals(Object other) { 123 if (!(other instanceof PendingIntentInfo)) { 124 return false; 125 } 126 return intent.equals(((PendingIntentInfo) other).intent); 127 } 128 } 129 130 /** 131 * List of our registered scanners. 132 */ 133 class ScannerMap extends ContextMap<IScannerCallback, PendingIntentInfo> {} 134 135 ScannerMap mScannerMap = new ScannerMap(); 136 137 /** 138 * List of our registered clients. 139 */ 140 class ClientMap extends ContextMap<IBluetoothGattCallback, Void> {} 141 142 ClientMap mClientMap = new ClientMap(); 143 144 /** 145 * List of our registered server apps. 146 */ 147 class ServerMap extends ContextMap<IBluetoothGattServerCallback, Void> {} 148 149 ServerMap mServerMap = new ServerMap(); 150 151 /** 152 * Server handle map. 153 */ 154 HandleMap mHandleMap = new HandleMap(); 155 private List<UUID> mAdvertisingServiceUuids = new ArrayList<UUID>(); 156 157 private int mMaxScanFilters; 158 159 private static final int NUM_SCAN_EVENTS_KEPT = 20; 160 /** 161 * Internal list of scan events to use with the proto 162 */ 163 private final ArrayList<BluetoothMetricsProto.ScanEvent> mScanEvents = 164 new ArrayList<>(NUM_SCAN_EVENTS_KEPT); 165 166 private final Map<Integer, List<BluetoothGattService>> mGattClientDatabases = new HashMap<>(); 167 168 private BluetoothAdapter mAdapter; 169 private AdvertiseManager mAdvertiseManager; 170 private PeriodicScanManager mPeriodicScanManager; 171 private ScanManager mScanManager; 172 private AppOpsManager mAppOps; 173 174 private static GattService sGattService; 175 176 /** 177 * Reliable write queue 178 */ 179 private Set<String> mReliableQueue = new HashSet<String>(); 180 181 static { 182 classInitNative(); 183 } 184 185 @Override 186 protected IProfileServiceBinder initBinder() { 187 return new BluetoothGattBinder(this); 188 } 189 190 @Override 191 protected boolean start() { 192 if (DBG) { 193 Log.d(TAG, "start()"); 194 } 195 initializeNative(); 196 mAdapter = BluetoothAdapter.getDefaultAdapter(); 197 mAppOps = getSystemService(AppOpsManager.class); 198 mAdvertiseManager = new AdvertiseManager(this, AdapterService.getAdapterService()); 199 mAdvertiseManager.start(); 200 201 mScanManager = new ScanManager(this); 202 mScanManager.start(); 203 204 mPeriodicScanManager = new PeriodicScanManager(AdapterService.getAdapterService()); 205 mPeriodicScanManager.start(); 206 207 setGattService(this); 208 return true; 209 } 210 211 @Override 212 protected boolean stop() { 213 if (DBG) { 214 Log.d(TAG, "stop()"); 215 } 216 setGattService(null); 217 mScannerMap.clear(); 218 mClientMap.clear(); 219 mServerMap.clear(); 220 mHandleMap.clear(); 221 mReliableQueue.clear(); 222 if (mAdvertiseManager != null) { 223 mAdvertiseManager.cleanup(); 224 } 225 if (mScanManager != null) { 226 mScanManager.cleanup(); 227 } 228 if (mPeriodicScanManager != null) { 229 mPeriodicScanManager.cleanup(); 230 } 231 return true; 232 } 233 234 @Override 235 protected void cleanup() { 236 if (DBG) { 237 Log.d(TAG, "cleanup()"); 238 } 239 cleanupNative(); 240 if (mAdvertiseManager != null) { 241 mAdvertiseManager.cleanup(); 242 } 243 if (mScanManager != null) { 244 mScanManager.cleanup(); 245 } 246 if (mPeriodicScanManager != null) { 247 mPeriodicScanManager.cleanup(); 248 } 249 } 250 251 252 /** 253 * Get the current instance of {@link GattService} 254 * 255 * @return current instance of {@link GattService} 256 */ 257 @VisibleForTesting 258 public static synchronized GattService getGattService() { 259 if (sGattService == null) { 260 Log.w(TAG, "getGattService(): service is null"); 261 return null; 262 } 263 if (!sGattService.isAvailable()) { 264 Log.w(TAG, "getGattService(): service is not available"); 265 return null; 266 } 267 return sGattService; 268 } 269 270 private static synchronized void setGattService(GattService instance) { 271 if (DBG) { 272 Log.d(TAG, "setGattService(): set to: " + instance); 273 } 274 sGattService = instance; 275 } 276 277 boolean permissionCheck(UUID uuid) { 278 return !(isRestrictedCharUuid(uuid) && (0 != checkCallingOrSelfPermission( 279 BLUETOOTH_PRIVILEGED))); 280 } 281 282 boolean permissionCheck(int connId, int handle) { 283 List<BluetoothGattService> db = mGattClientDatabases.get(connId); 284 if (db == null) { 285 return true; 286 } 287 288 for (BluetoothGattService service : db) { 289 for (BluetoothGattCharacteristic characteristic : service.getCharacteristics()) { 290 if (handle == characteristic.getInstanceId()) { 291 return !((isRestrictedCharUuid(characteristic.getUuid()) 292 || isRestrictedSrvcUuid(service.getUuid())) 293 && (0 != checkCallingOrSelfPermission(BLUETOOTH_PRIVILEGED))); 294 } 295 296 for (BluetoothGattDescriptor descriptor : characteristic.getDescriptors()) { 297 if (handle == descriptor.getInstanceId()) { 298 return !((isRestrictedCharUuid(characteristic.getUuid()) 299 || isRestrictedSrvcUuid(service.getUuid())) && (0 300 != checkCallingOrSelfPermission(BLUETOOTH_PRIVILEGED))); 301 } 302 } 303 } 304 } 305 306 return true; 307 } 308 309 @Override 310 public int onStartCommand(Intent intent, int flags, int startId) { 311 if (GattDebugUtils.handleDebugAction(this, intent)) { 312 return Service.START_NOT_STICKY; 313 } 314 return super.onStartCommand(intent, flags, startId); 315 } 316 317 /** 318 * DeathReceipient handlers used to unregister applications that 319 * disconnect ungracefully (ie. crash or forced close). 320 */ 321 322 class ScannerDeathRecipient implements IBinder.DeathRecipient { 323 int mScannerId; 324 325 ScannerDeathRecipient(int scannerId) { 326 mScannerId = scannerId; 327 } 328 329 @Override 330 public void binderDied() { 331 if (DBG) { 332 Log.d(TAG, "Binder is dead - unregistering scanner (" + mScannerId + ")!"); 333 } 334 335 if (isScanClient(mScannerId)) { 336 ScanClient client = new ScanClient(mScannerId); 337 client.appDied = true; 338 stopScan(client); 339 } 340 } 341 342 private boolean isScanClient(int clientIf) { 343 for (ScanClient client : mScanManager.getRegularScanQueue()) { 344 if (client.scannerId == clientIf) { 345 return true; 346 } 347 } 348 for (ScanClient client : mScanManager.getBatchScanQueue()) { 349 if (client.scannerId == clientIf) { 350 return true; 351 } 352 } 353 return false; 354 } 355 } 356 357 class ServerDeathRecipient implements IBinder.DeathRecipient { 358 int mAppIf; 359 360 ServerDeathRecipient(int appIf) { 361 mAppIf = appIf; 362 } 363 364 @Override 365 public void binderDied() { 366 if (DBG) { 367 Log.d(TAG, "Binder is dead - unregistering server (" + mAppIf + ")!"); 368 } 369 unregisterServer(mAppIf); 370 } 371 } 372 373 class ClientDeathRecipient implements IBinder.DeathRecipient { 374 int mAppIf; 375 376 ClientDeathRecipient(int appIf) { 377 mAppIf = appIf; 378 } 379 380 @Override 381 public void binderDied() { 382 if (DBG) { 383 Log.d(TAG, "Binder is dead - unregistering client (" + mAppIf + ")!"); 384 } 385 unregisterClient(mAppIf); 386 } 387 } 388 389 /** 390 * Handlers for incoming service calls 391 */ 392 private static class BluetoothGattBinder extends IBluetoothGatt.Stub 393 implements IProfileServiceBinder { 394 private GattService mService; 395 396 BluetoothGattBinder(GattService svc) { 397 mService = svc; 398 } 399 400 @Override 401 public void cleanup() { 402 mService = null; 403 } 404 405 private GattService getService() { 406 if (mService != null && mService.isAvailable()) { 407 return mService; 408 } 409 Log.e(TAG, "getService() - Service requested, but not available!"); 410 return null; 411 } 412 413 @Override 414 public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 415 GattService service = getService(); 416 if (service == null) { 417 return new ArrayList<BluetoothDevice>(); 418 } 419 return service.getDevicesMatchingConnectionStates(states); 420 } 421 422 @Override 423 public void registerClient(ParcelUuid uuid, IBluetoothGattCallback callback) { 424 GattService service = getService(); 425 if (service == null) { 426 return; 427 } 428 service.registerClient(uuid.getUuid(), callback); 429 } 430 431 @Override 432 public void unregisterClient(int clientIf) { 433 GattService service = getService(); 434 if (service == null) { 435 return; 436 } 437 service.unregisterClient(clientIf); 438 } 439 440 @Override 441 public void registerScanner(IScannerCallback callback, WorkSource workSource) 442 throws RemoteException { 443 GattService service = getService(); 444 if (service == null) { 445 return; 446 } 447 service.registerScanner(callback, workSource); 448 } 449 450 @Override 451 public void unregisterScanner(int scannerId) { 452 GattService service = getService(); 453 if (service == null) { 454 return; 455 } 456 service.unregisterScanner(scannerId); 457 } 458 459 @Override 460 public void startScan(int scannerId, ScanSettings settings, List<ScanFilter> filters, 461 List storages, String callingPackage) { 462 GattService service = getService(); 463 if (service == null) { 464 return; 465 } 466 service.startScan(scannerId, settings, filters, storages, callingPackage); 467 } 468 469 @Override 470 public void startScanForIntent(PendingIntent intent, ScanSettings settings, 471 List<ScanFilter> filters, String callingPackage) throws RemoteException { 472 GattService service = getService(); 473 if (service == null) { 474 return; 475 } 476 service.registerPiAndStartScan(intent, settings, filters, callingPackage); 477 } 478 479 @Override 480 public void stopScanForIntent(PendingIntent intent, String callingPackage) 481 throws RemoteException { 482 GattService service = getService(); 483 if (service == null) { 484 return; 485 } 486 service.stopScan(intent, callingPackage); 487 } 488 489 @Override 490 public void stopScan(int scannerId) { 491 GattService service = getService(); 492 if (service == null) { 493 return; 494 } 495 service.stopScan(new ScanClient(scannerId)); 496 } 497 498 @Override 499 public void flushPendingBatchResults(int scannerId) { 500 GattService service = getService(); 501 if (service == null) { 502 return; 503 } 504 service.flushPendingBatchResults(scannerId); 505 } 506 507 @Override 508 public void clientConnect(int clientIf, String address, boolean isDirect, int transport, 509 boolean opportunistic, int phy) { 510 GattService service = getService(); 511 if (service == null) { 512 return; 513 } 514 service.clientConnect(clientIf, address, isDirect, transport, opportunistic, phy); 515 } 516 517 @Override 518 public void clientDisconnect(int clientIf, String address) { 519 GattService service = getService(); 520 if (service == null) { 521 return; 522 } 523 service.clientDisconnect(clientIf, address); 524 } 525 526 @Override 527 public void clientSetPreferredPhy(int clientIf, String address, int txPhy, int rxPhy, 528 int phyOptions) { 529 GattService service = getService(); 530 if (service == null) { 531 return; 532 } 533 service.clientSetPreferredPhy(clientIf, address, txPhy, rxPhy, phyOptions); 534 } 535 536 @Override 537 public void clientReadPhy(int clientIf, String address) { 538 GattService service = getService(); 539 if (service == null) { 540 return; 541 } 542 service.clientReadPhy(clientIf, address); 543 } 544 545 @Override 546 public void refreshDevice(int clientIf, String address) { 547 GattService service = getService(); 548 if (service == null) { 549 return; 550 } 551 service.refreshDevice(clientIf, address); 552 } 553 554 @Override 555 public void discoverServices(int clientIf, String address) { 556 GattService service = getService(); 557 if (service == null) { 558 return; 559 } 560 service.discoverServices(clientIf, address); 561 } 562 563 @Override 564 public void discoverServiceByUuid(int clientIf, String address, ParcelUuid uuid) { 565 GattService service = getService(); 566 if (service == null) { 567 return; 568 } 569 service.discoverServiceByUuid(clientIf, address, uuid.getUuid()); 570 } 571 572 @Override 573 public void readCharacteristic(int clientIf, String address, int handle, int authReq) { 574 GattService service = getService(); 575 if (service == null) { 576 return; 577 } 578 service.readCharacteristic(clientIf, address, handle, authReq); 579 } 580 581 @Override 582 public void readUsingCharacteristicUuid(int clientIf, String address, ParcelUuid uuid, 583 int startHandle, int endHandle, int authReq) { 584 GattService service = getService(); 585 if (service == null) { 586 return; 587 } 588 service.readUsingCharacteristicUuid(clientIf, address, uuid.getUuid(), startHandle, 589 endHandle, authReq); 590 } 591 592 @Override 593 public void writeCharacteristic(int clientIf, String address, int handle, int writeType, 594 int authReq, byte[] value) { 595 GattService service = getService(); 596 if (service == null) { 597 return; 598 } 599 service.writeCharacteristic(clientIf, address, handle, writeType, authReq, value); 600 } 601 602 @Override 603 public void readDescriptor(int clientIf, String address, int handle, int authReq) { 604 GattService service = getService(); 605 if (service == null) { 606 return; 607 } 608 service.readDescriptor(clientIf, address, handle, authReq); 609 } 610 611 @Override 612 public void writeDescriptor(int clientIf, String address, int handle, int authReq, 613 byte[] value) { 614 GattService service = getService(); 615 if (service == null) { 616 return; 617 } 618 service.writeDescriptor(clientIf, address, handle, authReq, value); 619 } 620 621 @Override 622 public void beginReliableWrite(int clientIf, String address) { 623 GattService service = getService(); 624 if (service == null) { 625 return; 626 } 627 service.beginReliableWrite(clientIf, address); 628 } 629 630 @Override 631 public void endReliableWrite(int clientIf, String address, boolean execute) { 632 GattService service = getService(); 633 if (service == null) { 634 return; 635 } 636 service.endReliableWrite(clientIf, address, execute); 637 } 638 639 @Override 640 public void registerForNotification(int clientIf, String address, int handle, 641 boolean enable) { 642 GattService service = getService(); 643 if (service == null) { 644 return; 645 } 646 service.registerForNotification(clientIf, address, handle, enable); 647 } 648 649 @Override 650 public void readRemoteRssi(int clientIf, String address) { 651 GattService service = getService(); 652 if (service == null) { 653 return; 654 } 655 service.readRemoteRssi(clientIf, address); 656 } 657 658 @Override 659 public void configureMTU(int clientIf, String address, int mtu) { 660 GattService service = getService(); 661 if (service == null) { 662 return; 663 } 664 service.configureMTU(clientIf, address, mtu); 665 } 666 667 @Override 668 public void connectionParameterUpdate(int clientIf, String address, 669 int connectionPriority) { 670 GattService service = getService(); 671 if (service == null) { 672 return; 673 } 674 service.connectionParameterUpdate(clientIf, address, connectionPriority); 675 } 676 677 @Override 678 public void leConnectionUpdate(int clientIf, String address, 679 int minConnectionInterval, int maxConnectionInterval, 680 int slaveLatency, int supervisionTimeout, 681 int minConnectionEventLen, int maxConnectionEventLen) { 682 GattService service = getService(); 683 if (service == null) { 684 return; 685 } 686 service.leConnectionUpdate(clientIf, address, minConnectionInterval, 687 maxConnectionInterval, slaveLatency, 688 supervisionTimeout, minConnectionEventLen, 689 maxConnectionEventLen); 690 } 691 692 @Override 693 public void registerServer(ParcelUuid uuid, IBluetoothGattServerCallback callback) { 694 GattService service = getService(); 695 if (service == null) { 696 return; 697 } 698 service.registerServer(uuid.getUuid(), callback); 699 } 700 701 @Override 702 public void unregisterServer(int serverIf) { 703 GattService service = getService(); 704 if (service == null) { 705 return; 706 } 707 service.unregisterServer(serverIf); 708 } 709 710 @Override 711 public void serverConnect(int serverIf, String address, boolean isDirect, int transport) { 712 GattService service = getService(); 713 if (service == null) { 714 return; 715 } 716 service.serverConnect(serverIf, address, isDirect, transport); 717 } 718 719 @Override 720 public void serverDisconnect(int serverIf, String address) { 721 GattService service = getService(); 722 if (service == null) { 723 return; 724 } 725 service.serverDisconnect(serverIf, address); 726 } 727 728 @Override 729 public void serverSetPreferredPhy(int serverIf, String address, int txPhy, int rxPhy, 730 int phyOptions) { 731 GattService service = getService(); 732 if (service == null) { 733 return; 734 } 735 service.serverSetPreferredPhy(serverIf, address, txPhy, rxPhy, phyOptions); 736 } 737 738 @Override 739 public void serverReadPhy(int clientIf, String address) { 740 GattService service = getService(); 741 if (service == null) { 742 return; 743 } 744 service.serverReadPhy(clientIf, address); 745 } 746 747 @Override 748 public void addService(int serverIf, BluetoothGattService svc) { 749 GattService service = getService(); 750 if (service == null) { 751 return; 752 } 753 754 service.addService(serverIf, svc); 755 } 756 757 @Override 758 public void removeService(int serverIf, int handle) { 759 GattService service = getService(); 760 if (service == null) { 761 return; 762 } 763 service.removeService(serverIf, handle); 764 } 765 766 @Override 767 public void clearServices(int serverIf) { 768 GattService service = getService(); 769 if (service == null) { 770 return; 771 } 772 service.clearServices(serverIf); 773 } 774 775 @Override 776 public void sendResponse(int serverIf, String address, int requestId, int status, 777 int offset, byte[] value) { 778 GattService service = getService(); 779 if (service == null) { 780 return; 781 } 782 service.sendResponse(serverIf, address, requestId, status, offset, value); 783 } 784 785 @Override 786 public void sendNotification(int serverIf, String address, int handle, boolean confirm, 787 byte[] value) { 788 GattService service = getService(); 789 if (service == null) { 790 return; 791 } 792 service.sendNotification(serverIf, address, handle, confirm, value); 793 } 794 795 @Override 796 public void startAdvertisingSet(AdvertisingSetParameters parameters, 797 AdvertiseData advertiseData, AdvertiseData scanResponse, 798 PeriodicAdvertisingParameters periodicParameters, AdvertiseData periodicData, 799 int duration, int maxExtAdvEvents, IAdvertisingSetCallback callback) { 800 GattService service = getService(); 801 if (service == null) { 802 return; 803 } 804 service.startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters, 805 periodicData, duration, maxExtAdvEvents, callback); 806 } 807 808 @Override 809 public void stopAdvertisingSet(IAdvertisingSetCallback callback) { 810 GattService service = getService(); 811 if (service == null) { 812 return; 813 } 814 service.stopAdvertisingSet(callback); 815 } 816 817 @Override 818 public void getOwnAddress(int advertiserId) { 819 GattService service = getService(); 820 if (service == null) { 821 return; 822 } 823 service.getOwnAddress(advertiserId); 824 } 825 826 @Override 827 public void enableAdvertisingSet(int advertiserId, boolean enable, int duration, 828 int maxExtAdvEvents) { 829 GattService service = getService(); 830 if (service == null) { 831 return; 832 } 833 service.enableAdvertisingSet(advertiserId, enable, duration, maxExtAdvEvents); 834 } 835 836 @Override 837 public void setAdvertisingData(int advertiserId, AdvertiseData data) { 838 GattService service = getService(); 839 if (service == null) { 840 return; 841 } 842 service.setAdvertisingData(advertiserId, data); 843 } 844 845 @Override 846 public void setScanResponseData(int advertiserId, AdvertiseData data) { 847 GattService service = getService(); 848 if (service == null) { 849 return; 850 } 851 service.setScanResponseData(advertiserId, data); 852 } 853 854 @Override 855 public void setAdvertisingParameters(int advertiserId, 856 AdvertisingSetParameters parameters) { 857 GattService service = getService(); 858 if (service == null) { 859 return; 860 } 861 service.setAdvertisingParameters(advertiserId, parameters); 862 } 863 864 @Override 865 public void setPeriodicAdvertisingParameters(int advertiserId, 866 PeriodicAdvertisingParameters parameters) { 867 GattService service = getService(); 868 if (service == null) { 869 return; 870 } 871 service.setPeriodicAdvertisingParameters(advertiserId, parameters); 872 } 873 874 @Override 875 public void setPeriodicAdvertisingData(int advertiserId, AdvertiseData data) { 876 GattService service = getService(); 877 if (service == null) { 878 return; 879 } 880 service.setPeriodicAdvertisingData(advertiserId, data); 881 } 882 883 @Override 884 public void setPeriodicAdvertisingEnable(int advertiserId, boolean enable) { 885 GattService service = getService(); 886 if (service == null) { 887 return; 888 } 889 service.setPeriodicAdvertisingEnable(advertiserId, enable); 890 } 891 892 @Override 893 public void registerSync(ScanResult scanResult, int skip, int timeout, 894 IPeriodicAdvertisingCallback callback) { 895 GattService service = getService(); 896 if (service == null) { 897 return; 898 } 899 service.registerSync(scanResult, skip, timeout, callback); 900 } 901 902 @Override 903 public void unregisterSync(IPeriodicAdvertisingCallback callback) { 904 GattService service = getService(); 905 if (service == null) { 906 return; 907 } 908 service.unregisterSync(callback); 909 } 910 911 @Override 912 public void disconnectAll() { 913 GattService service = getService(); 914 if (service == null) { 915 return; 916 } 917 service.disconnectAll(); 918 } 919 920 @Override 921 public void unregAll() { 922 GattService service = getService(); 923 if (service == null) { 924 return; 925 } 926 service.unregAll(); 927 } 928 929 @Override 930 public int numHwTrackFiltersAvailable() { 931 GattService service = getService(); 932 if (service == null) { 933 return 0; 934 } 935 return service.numHwTrackFiltersAvailable(); 936 } 937 } 938 939 ; 940 941 /************************************************************************** 942 * Callback functions - CLIENT 943 *************************************************************************/ 944 945 void onScanResult(int eventType, int addressType, String address, int primaryPhy, 946 int secondaryPhy, int advertisingSid, int txPower, int rssi, int periodicAdvInt, 947 byte[] advData) { 948 if (VDBG) { 949 Log.d(TAG, "onScanResult() - eventType=0x" + Integer.toHexString(eventType) 950 + ", addressType=" + addressType + ", address=" + address + ", primaryPhy=" 951 + primaryPhy + ", secondaryPhy=" + secondaryPhy + ", advertisingSid=0x" 952 + Integer.toHexString(advertisingSid) + ", txPower=" + txPower + ", rssi=" 953 + rssi + ", periodicAdvInt=0x" + Integer.toHexString(periodicAdvInt)); 954 } 955 List<UUID> remoteUuids = parseUuids(advData); 956 957 byte[] legacyAdvData = Arrays.copyOfRange(advData, 0, 62); 958 959 for (ScanClient client : mScanManager.getRegularScanQueue()) { 960 if (client.uuids.length > 0) { 961 int matches = 0; 962 for (UUID search : client.uuids) { 963 for (UUID remote : remoteUuids) { 964 if (remote.equals(search)) { 965 ++matches; 966 break; // Only count 1st match in case of duplicates 967 } 968 } 969 } 970 971 if (matches < client.uuids.length) { 972 continue; 973 } 974 } 975 976 ScannerMap.App app = mScannerMap.getById(client.scannerId); 977 if (app == null) { 978 continue; 979 } 980 981 BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address); 982 983 ScanSettings settings = client.settings; 984 byte[] scanRecordData; 985 // This is for compability with applications that assume fixed size scan data. 986 if (settings.getLegacy()) { 987 if ((eventType & ET_LEGACY_MASK) == 0) { 988 // If this is legacy scan, but nonlegacy result - skip. 989 continue; 990 } else { 991 // Some apps are used to fixed-size advertise data. 992 scanRecordData = legacyAdvData; 993 } 994 } else { 995 scanRecordData = advData; 996 } 997 998 ScanResult result = 999 new ScanResult(device, eventType, primaryPhy, secondaryPhy, advertisingSid, 1000 txPower, rssi, periodicAdvInt, 1001 ScanRecord.parseFromBytes(scanRecordData), 1002 SystemClock.elapsedRealtimeNanos()); 1003 // Do no report if location mode is OFF or the client has no location permission 1004 // PEERS_MAC_ADDRESS permission holders always get results 1005 if (!hasScanResultPermission(client) || !matchesFilters(client, result)) { 1006 continue; 1007 } 1008 1009 if ((settings.getCallbackType() & ScanSettings.CALLBACK_TYPE_ALL_MATCHES) == 0) { 1010 continue; 1011 } 1012 1013 try { 1014 app.appScanStats.addResult(client.scannerId); 1015 if (app.callback != null) { 1016 app.callback.onScanResult(result); 1017 } else { 1018 // Send the PendingIntent 1019 ArrayList<ScanResult> results = new ArrayList<>(); 1020 results.add(result); 1021 sendResultsByPendingIntent(app.info, results, 1022 ScanSettings.CALLBACK_TYPE_ALL_MATCHES); 1023 } 1024 } catch (RemoteException | PendingIntent.CanceledException e) { 1025 Log.e(TAG, "Exception: " + e); 1026 mScannerMap.remove(client.scannerId); 1027 mScanManager.stopScan(client); 1028 } 1029 } 1030 } 1031 1032 private void sendResultByPendingIntent(PendingIntentInfo pii, ScanResult result, 1033 int callbackType, ScanClient client) { 1034 ArrayList<ScanResult> results = new ArrayList<>(); 1035 results.add(result); 1036 try { 1037 sendResultsByPendingIntent(pii, results, callbackType); 1038 } catch (PendingIntent.CanceledException e) { 1039 stopScan(client); 1040 unregisterScanner(client.scannerId); 1041 } 1042 } 1043 1044 private void sendResultsByPendingIntent(PendingIntentInfo pii, ArrayList<ScanResult> results, 1045 int callbackType) throws PendingIntent.CanceledException { 1046 Intent extrasIntent = new Intent(); 1047 extrasIntent.putParcelableArrayListExtra(BluetoothLeScanner.EXTRA_LIST_SCAN_RESULT, 1048 results); 1049 extrasIntent.putExtra(BluetoothLeScanner.EXTRA_CALLBACK_TYPE, callbackType); 1050 pii.intent.send(this, 0, extrasIntent); 1051 } 1052 1053 private void sendErrorByPendingIntent(PendingIntentInfo pii, int errorCode) 1054 throws PendingIntent.CanceledException { 1055 Intent extrasIntent = new Intent(); 1056 extrasIntent.putExtra(BluetoothLeScanner.EXTRA_ERROR_CODE, errorCode); 1057 pii.intent.send(this, 0, extrasIntent); 1058 } 1059 1060 void onScannerRegistered(int status, int scannerId, long uuidLsb, long uuidMsb) 1061 throws RemoteException { 1062 UUID uuid = new UUID(uuidMsb, uuidLsb); 1063 if (DBG) { 1064 Log.d(TAG, "onScannerRegistered() - UUID=" + uuid + ", scannerId=" + scannerId 1065 + ", status=" + status); 1066 } 1067 1068 // First check the callback map 1069 ScannerMap.App cbApp = mScannerMap.getByUuid(uuid); 1070 if (cbApp != null) { 1071 if (status == 0) { 1072 cbApp.id = scannerId; 1073 // If app is callback based, setup a death recipient. App will initiate the start. 1074 // Otherwise, if PendingIntent based, start the scan directly. 1075 if (cbApp.callback != null) { 1076 cbApp.linkToDeath(new ScannerDeathRecipient(scannerId)); 1077 } else { 1078 continuePiStartScan(scannerId, cbApp); 1079 } 1080 } else { 1081 mScannerMap.remove(scannerId); 1082 } 1083 if (cbApp.callback != null) { 1084 cbApp.callback.onScannerRegistered(status, scannerId); 1085 } 1086 } 1087 } 1088 1089 /** Determines if the given scan client has the appropriate permissions to receive callbacks. */ 1090 private boolean hasScanResultPermission(final ScanClient client) { 1091 final boolean requiresLocationEnabled = 1092 getResources().getBoolean(R.bool.strict_location_check); 1093 final boolean locationEnabledSetting = 1094 Settings.Secure.getInt(getContentResolver(), Settings.Secure.LOCATION_MODE, 1095 Settings.Secure.LOCATION_MODE_OFF) != Settings.Secure.LOCATION_MODE_OFF; 1096 final boolean locationEnabled = 1097 !requiresLocationEnabled || locationEnabledSetting || client.legacyForegroundApp; 1098 return (client.hasPeersMacAddressPermission || (client.hasLocationPermission 1099 && locationEnabled)); 1100 } 1101 1102 // Check if a scan record matches a specific filters. 1103 private boolean matchesFilters(ScanClient client, ScanResult scanResult) { 1104 if (client.filters == null || client.filters.isEmpty()) { 1105 return true; 1106 } 1107 for (ScanFilter filter : client.filters) { 1108 if (filter.matches(scanResult)) { 1109 return true; 1110 } 1111 } 1112 return false; 1113 } 1114 1115 void onClientRegistered(int status, int clientIf, long uuidLsb, long uuidMsb) 1116 throws RemoteException { 1117 UUID uuid = new UUID(uuidMsb, uuidLsb); 1118 if (DBG) { 1119 Log.d(TAG, "onClientRegistered() - UUID=" + uuid + ", clientIf=" + clientIf); 1120 } 1121 ClientMap.App app = mClientMap.getByUuid(uuid); 1122 if (app != null) { 1123 if (status == 0) { 1124 app.id = clientIf; 1125 app.linkToDeath(new ClientDeathRecipient(clientIf)); 1126 } else { 1127 mClientMap.remove(uuid); 1128 } 1129 app.callback.onClientRegistered(status, clientIf); 1130 } 1131 } 1132 1133 void onConnected(int clientIf, int connId, int status, String address) throws RemoteException { 1134 if (DBG) { 1135 Log.d(TAG, "onConnected() - clientIf=" + clientIf + ", connId=" + connId + ", address=" 1136 + address); 1137 } 1138 1139 if (status == 0) { 1140 mClientMap.addConnection(clientIf, connId, address); 1141 } 1142 ClientMap.App app = mClientMap.getById(clientIf); 1143 if (app != null) { 1144 app.callback.onClientConnectionState(status, clientIf, 1145 (status == BluetoothGatt.GATT_SUCCESS), address); 1146 } 1147 } 1148 1149 void onDisconnected(int clientIf, int connId, int status, String address) 1150 throws RemoteException { 1151 if (DBG) { 1152 Log.d(TAG, 1153 "onDisconnected() - clientIf=" + clientIf + ", connId=" + connId + ", address=" 1154 + address); 1155 } 1156 1157 mClientMap.removeConnection(clientIf, connId); 1158 ClientMap.App app = mClientMap.getById(clientIf); 1159 if (app != null) { 1160 app.callback.onClientConnectionState(status, clientIf, false, address); 1161 } 1162 } 1163 1164 void onClientPhyUpdate(int connId, int txPhy, int rxPhy, int status) throws RemoteException { 1165 if (DBG) { 1166 Log.d(TAG, "onClientPhyUpdate() - connId=" + connId + ", status=" + status); 1167 } 1168 1169 String address = mClientMap.addressByConnId(connId); 1170 if (address == null) { 1171 return; 1172 } 1173 1174 ClientMap.App app = mClientMap.getByConnId(connId); 1175 if (app == null) { 1176 return; 1177 } 1178 1179 app.callback.onPhyUpdate(address, txPhy, rxPhy, status); 1180 } 1181 1182 void onClientPhyRead(int clientIf, String address, int txPhy, int rxPhy, int status) 1183 throws RemoteException { 1184 if (DBG) { 1185 Log.d(TAG, 1186 "onClientPhyRead() - address=" + address + ", status=" + status + ", clientIf=" 1187 + clientIf); 1188 } 1189 1190 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1191 if (connId == null) { 1192 Log.d(TAG, "onClientPhyRead() - no connection to " + address); 1193 return; 1194 } 1195 1196 ClientMap.App app = mClientMap.getByConnId(connId); 1197 if (app == null) { 1198 return; 1199 } 1200 1201 app.callback.onPhyRead(address, txPhy, rxPhy, status); 1202 } 1203 1204 void onClientConnUpdate(int connId, int interval, int latency, int timeout, int status) 1205 throws RemoteException { 1206 if (DBG) { 1207 Log.d(TAG, "onClientConnUpdate() - connId=" + connId + ", status=" + status); 1208 } 1209 1210 String address = mClientMap.addressByConnId(connId); 1211 if (address == null) { 1212 return; 1213 } 1214 1215 ClientMap.App app = mClientMap.getByConnId(connId); 1216 if (app == null) { 1217 return; 1218 } 1219 1220 app.callback.onConnectionUpdated(address, interval, latency, timeout, status); 1221 } 1222 1223 void onServerPhyUpdate(int connId, int txPhy, int rxPhy, int status) throws RemoteException { 1224 if (DBG) { 1225 Log.d(TAG, "onServerPhyUpdate() - connId=" + connId + ", status=" + status); 1226 } 1227 1228 String address = mServerMap.addressByConnId(connId); 1229 if (address == null) { 1230 return; 1231 } 1232 1233 ServerMap.App app = mServerMap.getByConnId(connId); 1234 if (app == null) { 1235 return; 1236 } 1237 1238 app.callback.onPhyUpdate(address, txPhy, rxPhy, status); 1239 } 1240 1241 void onServerPhyRead(int serverIf, String address, int txPhy, int rxPhy, int status) 1242 throws RemoteException { 1243 if (DBG) { 1244 Log.d(TAG, "onServerPhyRead() - address=" + address + ", status=" + status); 1245 } 1246 1247 Integer connId = mServerMap.connIdByAddress(serverIf, address); 1248 if (connId == null) { 1249 Log.d(TAG, "onServerPhyRead() - no connection to " + address); 1250 return; 1251 } 1252 1253 ServerMap.App app = mServerMap.getByConnId(connId); 1254 if (app == null) { 1255 return; 1256 } 1257 1258 app.callback.onPhyRead(address, txPhy, rxPhy, status); 1259 } 1260 1261 void onServerConnUpdate(int connId, int interval, int latency, int timeout, int status) 1262 throws RemoteException { 1263 if (DBG) { 1264 Log.d(TAG, "onServerConnUpdate() - connId=" + connId + ", status=" + status); 1265 } 1266 1267 String address = mServerMap.addressByConnId(connId); 1268 if (address == null) { 1269 return; 1270 } 1271 1272 ServerMap.App app = mServerMap.getByConnId(connId); 1273 if (app == null) { 1274 return; 1275 } 1276 1277 app.callback.onConnectionUpdated(address, interval, latency, timeout, status); 1278 } 1279 1280 void onSearchCompleted(int connId, int status) throws RemoteException { 1281 if (DBG) { 1282 Log.d(TAG, "onSearchCompleted() - connId=" + connId + ", status=" + status); 1283 } 1284 // Gatt DB is ready! 1285 1286 // This callback was called from the jni_workqueue thread. If we make request to the stack 1287 // on the same thread, it might cause deadlock. Schedule request on a new thread instead. 1288 Thread t = new Thread(new Runnable() { 1289 @Override 1290 public void run() { 1291 gattClientGetGattDbNative(connId); 1292 } 1293 }); 1294 t.start(); 1295 } 1296 1297 GattDbElement getSampleGattDbElement() { 1298 return new GattDbElement(); 1299 } 1300 1301 void onGetGattDb(int connId, ArrayList<GattDbElement> db) throws RemoteException { 1302 String address = mClientMap.addressByConnId(connId); 1303 1304 if (DBG) { 1305 Log.d(TAG, "onGetGattDb() - address=" + address); 1306 } 1307 1308 ClientMap.App app = mClientMap.getByConnId(connId); 1309 if (app == null || app.callback == null) { 1310 Log.e(TAG, "app or callback is null"); 1311 return; 1312 } 1313 1314 List<BluetoothGattService> dbOut = new ArrayList<BluetoothGattService>(); 1315 1316 BluetoothGattService currSrvc = null; 1317 BluetoothGattCharacteristic currChar = null; 1318 1319 for (GattDbElement el : db) { 1320 switch (el.type) { 1321 case GattDbElement.TYPE_PRIMARY_SERVICE: 1322 case GattDbElement.TYPE_SECONDARY_SERVICE: 1323 if (DBG) { 1324 Log.d(TAG, "got service with UUID=" + el.uuid + " id: " + el.id); 1325 } 1326 1327 currSrvc = new BluetoothGattService(el.uuid, el.id, el.type); 1328 dbOut.add(currSrvc); 1329 break; 1330 1331 case GattDbElement.TYPE_CHARACTERISTIC: 1332 if (DBG) { 1333 Log.d(TAG, "got characteristic with UUID=" + el.uuid + " id: " + el.id); 1334 } 1335 1336 currChar = new BluetoothGattCharacteristic(el.uuid, el.id, el.properties, 0); 1337 currSrvc.addCharacteristic(currChar); 1338 break; 1339 1340 case GattDbElement.TYPE_DESCRIPTOR: 1341 if (DBG) { 1342 Log.d(TAG, "got descriptor with UUID=" + el.uuid + " id: " + el.id); 1343 } 1344 1345 currChar.addDescriptor(new BluetoothGattDescriptor(el.uuid, el.id, 0)); 1346 break; 1347 1348 case GattDbElement.TYPE_INCLUDED_SERVICE: 1349 if (DBG) { 1350 Log.d(TAG, "got included service with UUID=" + el.uuid + " id: " + el.id 1351 + " startHandle: " + el.startHandle); 1352 } 1353 1354 currSrvc.addIncludedService( 1355 new BluetoothGattService(el.uuid, el.startHandle, el.type)); 1356 break; 1357 1358 default: 1359 Log.e(TAG, "got unknown element with type=" + el.type + " and UUID=" + el.uuid 1360 + " id: " + el.id); 1361 } 1362 } 1363 1364 // Search is complete when there was error, or nothing more to process 1365 mGattClientDatabases.put(connId, dbOut); 1366 app.callback.onSearchComplete(address, dbOut, 0 /* status */); 1367 } 1368 1369 void onRegisterForNotifications(int connId, int status, int registered, int handle) { 1370 String address = mClientMap.addressByConnId(connId); 1371 1372 if (DBG) { 1373 Log.d(TAG, "onRegisterForNotifications() - address=" + address + ", status=" + status 1374 + ", registered=" + registered + ", handle=" + handle); 1375 } 1376 } 1377 1378 void onNotify(int connId, String address, int handle, boolean isNotify, byte[] data) 1379 throws RemoteException { 1380 1381 if (VDBG) { 1382 Log.d(TAG, "onNotify() - address=" + address + ", handle=" + handle + ", length=" 1383 + data.length); 1384 } 1385 1386 if (!permissionCheck(connId, handle)) { 1387 Log.w(TAG, "onNotify() - permission check failed!"); 1388 return; 1389 } 1390 1391 ClientMap.App app = mClientMap.getByConnId(connId); 1392 if (app != null) { 1393 app.callback.onNotify(address, handle, data); 1394 } 1395 } 1396 1397 void onReadCharacteristic(int connId, int status, int handle, byte[] data) 1398 throws RemoteException { 1399 String address = mClientMap.addressByConnId(connId); 1400 1401 if (VDBG) { 1402 Log.d(TAG, "onReadCharacteristic() - address=" + address + ", status=" + status 1403 + ", length=" + data.length); 1404 } 1405 1406 ClientMap.App app = mClientMap.getByConnId(connId); 1407 if (app != null) { 1408 app.callback.onCharacteristicRead(address, status, handle, data); 1409 } 1410 } 1411 1412 void onWriteCharacteristic(int connId, int status, int handle) throws RemoteException { 1413 String address = mClientMap.addressByConnId(connId); 1414 1415 if (VDBG) { 1416 Log.d(TAG, "onWriteCharacteristic() - address=" + address + ", status=" + status); 1417 } 1418 1419 ClientMap.App app = mClientMap.getByConnId(connId); 1420 if (app == null) { 1421 return; 1422 } 1423 1424 if (!app.isCongested) { 1425 app.callback.onCharacteristicWrite(address, status, handle); 1426 } else { 1427 if (status == BluetoothGatt.GATT_CONNECTION_CONGESTED) { 1428 status = BluetoothGatt.GATT_SUCCESS; 1429 } 1430 CallbackInfo callbackInfo = new CallbackInfo(address, status, handle); 1431 app.queueCallback(callbackInfo); 1432 } 1433 } 1434 1435 void onExecuteCompleted(int connId, int status) throws RemoteException { 1436 String address = mClientMap.addressByConnId(connId); 1437 if (VDBG) { 1438 Log.d(TAG, "onExecuteCompleted() - address=" + address + ", status=" + status); 1439 } 1440 1441 ClientMap.App app = mClientMap.getByConnId(connId); 1442 if (app != null) { 1443 app.callback.onExecuteWrite(address, status); 1444 } 1445 } 1446 1447 void onReadDescriptor(int connId, int status, int handle, byte[] data) throws RemoteException { 1448 String address = mClientMap.addressByConnId(connId); 1449 1450 if (VDBG) { 1451 Log.d(TAG, 1452 "onReadDescriptor() - address=" + address + ", status=" + status + ", length=" 1453 + data.length); 1454 } 1455 1456 ClientMap.App app = mClientMap.getByConnId(connId); 1457 if (app != null) { 1458 app.callback.onDescriptorRead(address, status, handle, data); 1459 } 1460 } 1461 1462 void onWriteDescriptor(int connId, int status, int handle) throws RemoteException { 1463 String address = mClientMap.addressByConnId(connId); 1464 1465 if (VDBG) { 1466 Log.d(TAG, "onWriteDescriptor() - address=" + address + ", status=" + status); 1467 } 1468 1469 ClientMap.App app = mClientMap.getByConnId(connId); 1470 if (app != null) { 1471 app.callback.onDescriptorWrite(address, status, handle); 1472 } 1473 } 1474 1475 void onReadRemoteRssi(int clientIf, String address, int rssi, int status) 1476 throws RemoteException { 1477 if (DBG) { 1478 Log.d(TAG, 1479 "onReadRemoteRssi() - clientIf=" + clientIf + " address=" + address + ", rssi=" 1480 + rssi + ", status=" + status); 1481 } 1482 1483 ClientMap.App app = mClientMap.getById(clientIf); 1484 if (app != null) { 1485 app.callback.onReadRemoteRssi(address, rssi, status); 1486 } 1487 } 1488 1489 void onScanFilterEnableDisabled(int action, int status, int clientIf) { 1490 if (DBG) { 1491 Log.d(TAG, "onScanFilterEnableDisabled() - clientIf=" + clientIf + ", status=" + status 1492 + ", action=" + action); 1493 } 1494 mScanManager.callbackDone(clientIf, status); 1495 } 1496 1497 void onScanFilterParamsConfigured(int action, int status, int clientIf, int availableSpace) { 1498 if (DBG) { 1499 Log.d(TAG, 1500 "onScanFilterParamsConfigured() - clientIf=" + clientIf + ", status=" + status 1501 + ", action=" + action + ", availableSpace=" + availableSpace); 1502 } 1503 mScanManager.callbackDone(clientIf, status); 1504 } 1505 1506 void onScanFilterConfig(int action, int status, int clientIf, int filterType, 1507 int availableSpace) { 1508 if (DBG) { 1509 Log.d(TAG, "onScanFilterConfig() - clientIf=" + clientIf + ", action = " + action 1510 + " status = " + status + ", filterType=" + filterType + ", availableSpace=" 1511 + availableSpace); 1512 } 1513 1514 mScanManager.callbackDone(clientIf, status); 1515 } 1516 1517 void onBatchScanStorageConfigured(int status, int clientIf) { 1518 if (DBG) { 1519 Log.d(TAG, 1520 "onBatchScanStorageConfigured() - clientIf=" + clientIf + ", status=" + status); 1521 } 1522 mScanManager.callbackDone(clientIf, status); 1523 } 1524 1525 // TODO: split into two different callbacks : onBatchScanStarted and onBatchScanStopped. 1526 void onBatchScanStartStopped(int startStopAction, int status, int clientIf) { 1527 if (DBG) { 1528 Log.d(TAG, "onBatchScanStartStopped() - clientIf=" + clientIf + ", status=" + status 1529 + ", startStopAction=" + startStopAction); 1530 } 1531 mScanManager.callbackDone(clientIf, status); 1532 } 1533 1534 void onBatchScanReports(int status, int scannerId, int reportType, int numRecords, 1535 byte[] recordData) throws RemoteException { 1536 if (DBG) { 1537 Log.d(TAG, "onBatchScanReports() - scannerId=" + scannerId + ", status=" + status 1538 + ", reportType=" + reportType + ", numRecords=" + numRecords); 1539 } 1540 mScanManager.callbackDone(scannerId, status); 1541 Set<ScanResult> results = parseBatchScanResults(numRecords, reportType, recordData); 1542 if (reportType == ScanManager.SCAN_RESULT_TYPE_TRUNCATED) { 1543 // We only support single client for truncated mode. 1544 ScannerMap.App app = mScannerMap.getById(scannerId); 1545 if (app == null) { 1546 return; 1547 } 1548 if (app.callback != null) { 1549 app.callback.onBatchScanResults(new ArrayList<ScanResult>(results)); 1550 } else { 1551 // PendingIntent based 1552 try { 1553 sendResultsByPendingIntent(app.info, new ArrayList<ScanResult>(results), 1554 ScanSettings.CALLBACK_TYPE_ALL_MATCHES); 1555 } catch (PendingIntent.CanceledException e) { 1556 } 1557 } 1558 } else { 1559 for (ScanClient client : mScanManager.getFullBatchScanQueue()) { 1560 // Deliver results for each client. 1561 deliverBatchScan(client, results); 1562 } 1563 } 1564 } 1565 1566 private void sendBatchScanResults(ScannerMap.App app, ScanClient client, 1567 ArrayList<ScanResult> results) { 1568 try { 1569 if (app.callback != null) { 1570 app.callback.onBatchScanResults(results); 1571 } else { 1572 sendResultsByPendingIntent(app.info, results, 1573 ScanSettings.CALLBACK_TYPE_ALL_MATCHES); 1574 } 1575 } catch (RemoteException | PendingIntent.CanceledException e) { 1576 Log.e(TAG, "Exception: " + e); 1577 mScannerMap.remove(client.scannerId); 1578 mScanManager.stopScan(client); 1579 } 1580 } 1581 1582 // Check and deliver scan results for different scan clients. 1583 private void deliverBatchScan(ScanClient client, Set<ScanResult> allResults) 1584 throws RemoteException { 1585 ScannerMap.App app = mScannerMap.getById(client.scannerId); 1586 if (app == null) { 1587 return; 1588 } 1589 if (client.filters == null || client.filters.isEmpty()) { 1590 sendBatchScanResults(app, client, new ArrayList<ScanResult>(allResults)); 1591 // TODO: Question to reviewer: Shouldn't there be a return here? 1592 } 1593 // Reconstruct the scan results. 1594 ArrayList<ScanResult> results = new ArrayList<ScanResult>(); 1595 for (ScanResult scanResult : allResults) { 1596 if (matchesFilters(client, scanResult)) { 1597 results.add(scanResult); 1598 } 1599 } 1600 sendBatchScanResults(app, client, results); 1601 } 1602 1603 private Set<ScanResult> parseBatchScanResults(int numRecords, int reportType, 1604 byte[] batchRecord) { 1605 if (numRecords == 0) { 1606 return Collections.emptySet(); 1607 } 1608 if (DBG) { 1609 Log.d(TAG, "current time is " + SystemClock.elapsedRealtimeNanos()); 1610 } 1611 if (reportType == ScanManager.SCAN_RESULT_TYPE_TRUNCATED) { 1612 return parseTruncatedResults(numRecords, batchRecord); 1613 } else { 1614 return parseFullResults(numRecords, batchRecord); 1615 } 1616 } 1617 1618 private Set<ScanResult> parseTruncatedResults(int numRecords, byte[] batchRecord) { 1619 if (DBG) { 1620 Log.d(TAG, "batch record " + Arrays.toString(batchRecord)); 1621 } 1622 Set<ScanResult> results = new HashSet<ScanResult>(numRecords); 1623 long now = SystemClock.elapsedRealtimeNanos(); 1624 for (int i = 0; i < numRecords; ++i) { 1625 byte[] record = 1626 extractBytes(batchRecord, i * TRUNCATED_RESULT_SIZE, TRUNCATED_RESULT_SIZE); 1627 byte[] address = extractBytes(record, 0, 6); 1628 reverse(address); 1629 BluetoothDevice device = mAdapter.getRemoteDevice(address); 1630 int rssi = record[8]; 1631 long timestampNanos = now - parseTimestampNanos(extractBytes(record, 9, 2)); 1632 results.add(new ScanResult(device, ScanRecord.parseFromBytes(new byte[0]), rssi, 1633 timestampNanos)); 1634 } 1635 return results; 1636 } 1637 1638 @VisibleForTesting 1639 long parseTimestampNanos(byte[] data) { 1640 long timestampUnit = NumberUtils.littleEndianByteArrayToInt(data); 1641 // Timestamp is in every 50 ms. 1642 return TimeUnit.MILLISECONDS.toNanos(timestampUnit * 50); 1643 } 1644 1645 private Set<ScanResult> parseFullResults(int numRecords, byte[] batchRecord) { 1646 if (DBG) { 1647 Log.d(TAG, "Batch record : " + Arrays.toString(batchRecord)); 1648 } 1649 Set<ScanResult> results = new HashSet<ScanResult>(numRecords); 1650 int position = 0; 1651 long now = SystemClock.elapsedRealtimeNanos(); 1652 while (position < batchRecord.length) { 1653 byte[] address = extractBytes(batchRecord, position, 6); 1654 // TODO: remove temp hack. 1655 reverse(address); 1656 BluetoothDevice device = mAdapter.getRemoteDevice(address); 1657 position += 6; 1658 // Skip address type. 1659 position++; 1660 // Skip tx power level. 1661 position++; 1662 int rssi = batchRecord[position++]; 1663 long timestampNanos = now - parseTimestampNanos(extractBytes(batchRecord, position, 2)); 1664 position += 2; 1665 1666 // Combine advertise packet and scan response packet. 1667 int advertisePacketLen = batchRecord[position++]; 1668 byte[] advertiseBytes = extractBytes(batchRecord, position, advertisePacketLen); 1669 position += advertisePacketLen; 1670 int scanResponsePacketLen = batchRecord[position++]; 1671 byte[] scanResponseBytes = extractBytes(batchRecord, position, scanResponsePacketLen); 1672 position += scanResponsePacketLen; 1673 byte[] scanRecord = new byte[advertisePacketLen + scanResponsePacketLen]; 1674 System.arraycopy(advertiseBytes, 0, scanRecord, 0, advertisePacketLen); 1675 System.arraycopy(scanResponseBytes, 0, scanRecord, advertisePacketLen, 1676 scanResponsePacketLen); 1677 if (DBG) { 1678 Log.d(TAG, "ScanRecord : " + Arrays.toString(scanRecord)); 1679 } 1680 results.add(new ScanResult(device, ScanRecord.parseFromBytes(scanRecord), rssi, 1681 timestampNanos)); 1682 } 1683 return results; 1684 } 1685 1686 // Reverse byte array. 1687 private void reverse(byte[] address) { 1688 int len = address.length; 1689 for (int i = 0; i < len / 2; ++i) { 1690 byte b = address[i]; 1691 address[i] = address[len - 1 - i]; 1692 address[len - 1 - i] = b; 1693 } 1694 } 1695 1696 // Helper method to extract bytes from byte array. 1697 private static byte[] extractBytes(byte[] scanRecord, int start, int length) { 1698 byte[] bytes = new byte[length]; 1699 System.arraycopy(scanRecord, start, bytes, 0, length); 1700 return bytes; 1701 } 1702 1703 void onBatchScanThresholdCrossed(int clientIf) { 1704 if (DBG) { 1705 Log.d(TAG, "onBatchScanThresholdCrossed() - clientIf=" + clientIf); 1706 } 1707 flushPendingBatchResults(clientIf); 1708 } 1709 1710 AdvtFilterOnFoundOnLostInfo createOnTrackAdvFoundLostObject(int clientIf, int advPktLen, 1711 byte[] advPkt, int scanRspLen, byte[] scanRsp, int filtIndex, int advState, 1712 int advInfoPresent, String address, int addrType, int txPower, int rssiValue, 1713 int timeStamp) { 1714 1715 return new AdvtFilterOnFoundOnLostInfo(clientIf, advPktLen, advPkt, scanRspLen, scanRsp, 1716 filtIndex, advState, advInfoPresent, address, addrType, txPower, rssiValue, 1717 timeStamp); 1718 } 1719 1720 void onTrackAdvFoundLost(AdvtFilterOnFoundOnLostInfo trackingInfo) throws RemoteException { 1721 if (DBG) { 1722 Log.d(TAG, "onTrackAdvFoundLost() - scannerId= " + trackingInfo.getClientIf() 1723 + " address = " + trackingInfo.getAddress() + " adv_state = " 1724 + trackingInfo.getAdvState()); 1725 } 1726 1727 ScannerMap.App app = mScannerMap.getById(trackingInfo.getClientIf()); 1728 if (app == null || (app.callback == null && app.info == null)) { 1729 Log.e(TAG, "app or callback is null"); 1730 return; 1731 } 1732 1733 BluetoothDevice device = 1734 BluetoothAdapter.getDefaultAdapter().getRemoteDevice(trackingInfo.getAddress()); 1735 int advertiserState = trackingInfo.getAdvState(); 1736 ScanResult result = 1737 new ScanResult(device, ScanRecord.parseFromBytes(trackingInfo.getResult()), 1738 trackingInfo.getRSSIValue(), SystemClock.elapsedRealtimeNanos()); 1739 1740 for (ScanClient client : mScanManager.getRegularScanQueue()) { 1741 if (client.scannerId == trackingInfo.getClientIf()) { 1742 ScanSettings settings = client.settings; 1743 if ((advertiserState == ADVT_STATE_ONFOUND) && ( 1744 (settings.getCallbackType() & ScanSettings.CALLBACK_TYPE_FIRST_MATCH) 1745 != 0)) { 1746 if (app.callback != null) { 1747 app.callback.onFoundOrLost(true, result); 1748 } else { 1749 sendResultByPendingIntent(app.info, result, 1750 ScanSettings.CALLBACK_TYPE_FIRST_MATCH, client); 1751 } 1752 } else if ((advertiserState == ADVT_STATE_ONLOST) && ( 1753 (settings.getCallbackType() & ScanSettings.CALLBACK_TYPE_MATCH_LOST) 1754 != 0)) { 1755 if (app.callback != null) { 1756 app.callback.onFoundOrLost(false, result); 1757 } else { 1758 sendResultByPendingIntent(app.info, result, 1759 ScanSettings.CALLBACK_TYPE_MATCH_LOST, client); 1760 } 1761 } else { 1762 if (DBG) { 1763 Log.d(TAG, "Not reporting onlost/onfound : " + advertiserState 1764 + " scannerId = " + client.scannerId + " callbackType " 1765 + settings.getCallbackType()); 1766 } 1767 } 1768 } 1769 } 1770 } 1771 1772 void onScanParamSetupCompleted(int status, int scannerId) throws RemoteException { 1773 ScannerMap.App app = mScannerMap.getById(scannerId); 1774 if (app == null || app.callback == null) { 1775 Log.e(TAG, "Advertise app or callback is null"); 1776 return; 1777 } 1778 if (DBG) { 1779 Log.d(TAG, "onScanParamSetupCompleted : " + status); 1780 } 1781 } 1782 1783 // callback from ScanManager for dispatch of errors apps. 1784 void onScanManagerErrorCallback(int scannerId, int errorCode) throws RemoteException { 1785 ScannerMap.App app = mScannerMap.getById(scannerId); 1786 if (app == null || (app.callback == null && app.info == null)) { 1787 Log.e(TAG, "App or callback is null"); 1788 return; 1789 } 1790 if (app.callback != null) { 1791 app.callback.onScanManagerErrorCallback(errorCode); 1792 } else { 1793 try { 1794 sendErrorByPendingIntent(app.info, errorCode); 1795 } catch (PendingIntent.CanceledException e) { 1796 Log.e(TAG, "Error sending error code via PendingIntent:" + e); 1797 } 1798 } 1799 } 1800 1801 void onConfigureMTU(int connId, int status, int mtu) throws RemoteException { 1802 String address = mClientMap.addressByConnId(connId); 1803 1804 if (DBG) { 1805 Log.d(TAG, 1806 "onConfigureMTU() address=" + address + ", status=" + status + ", mtu=" + mtu); 1807 } 1808 1809 ClientMap.App app = mClientMap.getByConnId(connId); 1810 if (app != null) { 1811 app.callback.onConfigureMTU(address, mtu, status); 1812 } 1813 } 1814 1815 void onClientCongestion(int connId, boolean congested) throws RemoteException { 1816 if (VDBG) { 1817 Log.d(TAG, "onClientCongestion() - connId=" + connId + ", congested=" + congested); 1818 } 1819 1820 ClientMap.App app = mClientMap.getByConnId(connId); 1821 1822 if (app != null) { 1823 app.isCongested = congested; 1824 while (!app.isCongested) { 1825 CallbackInfo callbackInfo = app.popQueuedCallback(); 1826 if (callbackInfo == null) { 1827 return; 1828 } 1829 app.callback.onCharacteristicWrite(callbackInfo.address, callbackInfo.status, 1830 callbackInfo.handle); 1831 } 1832 } 1833 } 1834 1835 /************************************************************************** 1836 * GATT Service functions - Shared CLIENT/SERVER 1837 *************************************************************************/ 1838 1839 List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 1840 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1841 1842 Map<BluetoothDevice, Integer> deviceStates = new HashMap<BluetoothDevice, Integer>(); 1843 1844 // Add paired LE devices 1845 1846 Set<BluetoothDevice> bondedDevices = mAdapter.getBondedDevices(); 1847 for (BluetoothDevice device : bondedDevices) { 1848 if (getDeviceType(device) != AbstractionLayer.BT_DEVICE_TYPE_BREDR) { 1849 deviceStates.put(device, BluetoothProfile.STATE_DISCONNECTED); 1850 } 1851 } 1852 1853 // Add connected deviceStates 1854 1855 Set<String> connectedDevices = new HashSet<String>(); 1856 connectedDevices.addAll(mClientMap.getConnectedDevices()); 1857 connectedDevices.addAll(mServerMap.getConnectedDevices()); 1858 1859 for (String address : connectedDevices) { 1860 BluetoothDevice device = mAdapter.getRemoteDevice(address); 1861 if (device != null) { 1862 deviceStates.put(device, BluetoothProfile.STATE_CONNECTED); 1863 } 1864 } 1865 1866 // Create matching device sub-set 1867 1868 List<BluetoothDevice> deviceList = new ArrayList<BluetoothDevice>(); 1869 1870 for (Map.Entry<BluetoothDevice, Integer> entry : deviceStates.entrySet()) { 1871 for (int state : states) { 1872 if (entry.getValue() == state) { 1873 deviceList.add(entry.getKey()); 1874 } 1875 } 1876 } 1877 1878 return deviceList; 1879 } 1880 1881 void registerScanner(IScannerCallback callback, WorkSource workSource) throws RemoteException { 1882 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1883 1884 UUID uuid = UUID.randomUUID(); 1885 if (DBG) { 1886 Log.d(TAG, "registerScanner() - UUID=" + uuid); 1887 } 1888 1889 if (workSource != null) { 1890 enforceImpersonatationPermission(); 1891 } 1892 1893 AppScanStats app = mScannerMap.getAppScanStatsByUid(Binder.getCallingUid()); 1894 if (app != null && app.isScanningTooFrequently() 1895 && checkCallingOrSelfPermission(BLUETOOTH_PRIVILEGED) != PERMISSION_GRANTED) { 1896 Log.e(TAG, "App '" + app.appName + "' is scanning too frequently"); 1897 callback.onScannerRegistered(ScanCallback.SCAN_FAILED_SCANNING_TOO_FREQUENTLY, -1); 1898 return; 1899 } 1900 1901 mScannerMap.add(uuid, workSource, callback, null, this); 1902 mScanManager.registerScanner(uuid); 1903 } 1904 1905 void unregisterScanner(int scannerId) { 1906 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1907 1908 if (DBG) { 1909 Log.d(TAG, "unregisterScanner() - scannerId=" + scannerId); 1910 } 1911 mScannerMap.remove(scannerId); 1912 mScanManager.unregisterScanner(scannerId); 1913 } 1914 1915 void startScan(int scannerId, ScanSettings settings, List<ScanFilter> filters, 1916 List<List<ResultStorageDescriptor>> storages, String callingPackage) { 1917 if (DBG) { 1918 Log.d(TAG, "start scan with filters"); 1919 } 1920 enforceAdminPermission(); 1921 if (needsPrivilegedPermissionForScan(settings)) { 1922 enforcePrivilegedPermission(); 1923 } 1924 final ScanClient scanClient = new ScanClient(scannerId, settings, filters, storages); 1925 scanClient.hasLocationPermission = 1926 Utils.checkCallerHasLocationPermission(this, mAppOps, callingPackage); 1927 scanClient.hasPeersMacAddressPermission = 1928 Utils.checkCallerHasPeersMacAddressPermission(this); 1929 scanClient.legacyForegroundApp = Utils.isLegacyForegroundApp(this, callingPackage); 1930 1931 AppScanStats app = mScannerMap.getAppScanStatsById(scannerId); 1932 if (app != null) { 1933 scanClient.stats = app; 1934 boolean isFilteredScan = (filters != null) && !filters.isEmpty(); 1935 app.recordScanStart(settings, isFilteredScan, scannerId); 1936 } 1937 1938 mScanManager.startScan(scanClient); 1939 } 1940 1941 void registerPiAndStartScan(PendingIntent pendingIntent, ScanSettings settings, 1942 List<ScanFilter> filters, String callingPackage) { 1943 if (DBG) { 1944 Log.d(TAG, "start scan with filters, for PendingIntent"); 1945 } 1946 enforceAdminPermission(); 1947 if (needsPrivilegedPermissionForScan(settings)) { 1948 enforcePrivilegedPermission(); 1949 } 1950 1951 UUID uuid = UUID.randomUUID(); 1952 if (DBG) { 1953 Log.d(TAG, "startScan(PI) - UUID=" + uuid); 1954 } 1955 PendingIntentInfo piInfo = new PendingIntentInfo(); 1956 piInfo.intent = pendingIntent; 1957 piInfo.settings = settings; 1958 piInfo.filters = filters; 1959 piInfo.callingPackage = callingPackage; 1960 ScannerMap.App app = mScannerMap.add(uuid, null, null, piInfo, this); 1961 try { 1962 app.hasLocationPermisson = 1963 Utils.checkCallerHasLocationPermission(this, mAppOps, callingPackage); 1964 } catch (SecurityException se) { 1965 // No need to throw here. Just mark as not granted. 1966 app.hasLocationPermisson = false; 1967 } 1968 try { 1969 app.hasPeersMacAddressPermission = Utils.checkCallerHasPeersMacAddressPermission(this); 1970 } catch (SecurityException se) { 1971 // No need to throw here. Just mark as not granted. 1972 app.hasPeersMacAddressPermission = false; 1973 } 1974 mScanManager.registerScanner(uuid); 1975 } 1976 1977 void continuePiStartScan(int scannerId, ScannerMap.App app) { 1978 final PendingIntentInfo piInfo = app.info; 1979 final ScanClient scanClient = 1980 new ScanClient(scannerId, piInfo.settings, piInfo.filters, null); 1981 scanClient.hasLocationPermission = app.hasLocationPermisson; 1982 scanClient.hasPeersMacAddressPermission = app.hasPeersMacAddressPermission; 1983 scanClient.legacyForegroundApp = Utils.isLegacyForegroundApp(this, piInfo.callingPackage); 1984 1985 AppScanStats scanStats = mScannerMap.getAppScanStatsById(scannerId); 1986 if (scanStats != null) { 1987 scanClient.stats = scanStats; 1988 boolean isFilteredScan = (piInfo.filters != null) && !piInfo.filters.isEmpty(); 1989 scanStats.recordScanStart(piInfo.settings, isFilteredScan, scannerId); 1990 } 1991 1992 mScanManager.startScan(scanClient); 1993 } 1994 1995 void flushPendingBatchResults(int scannerId) { 1996 if (DBG) { 1997 Log.d(TAG, "flushPendingBatchResults - scannerId=" + scannerId); 1998 } 1999 mScanManager.flushBatchScanResults(new ScanClient(scannerId)); 2000 } 2001 2002 void stopScan(ScanClient client) { 2003 enforceAdminPermission(); 2004 int scanQueueSize = 2005 mScanManager.getBatchScanQueue().size() + mScanManager.getRegularScanQueue().size(); 2006 if (DBG) { 2007 Log.d(TAG, "stopScan() - queue size =" + scanQueueSize); 2008 } 2009 2010 AppScanStats app = null; 2011 app = mScannerMap.getAppScanStatsById(client.scannerId); 2012 if (app != null) { 2013 app.recordScanStop(client.scannerId); 2014 } 2015 2016 mScanManager.stopScan(client); 2017 } 2018 2019 void stopScan(PendingIntent intent, String callingPackage) { 2020 enforceAdminPermission(); 2021 PendingIntentInfo pii = new PendingIntentInfo(); 2022 pii.intent = intent; 2023 ScannerMap.App app = mScannerMap.getByContextInfo(pii); 2024 if (VDBG) { 2025 Log.d(TAG, "stopScan(PendingIntent): app found = " + app); 2026 } 2027 if (app != null) { 2028 final int scannerId = app.id; 2029 stopScan(new ScanClient(scannerId)); 2030 // Also unregister the scanner 2031 unregisterScanner(scannerId); 2032 } 2033 } 2034 2035 void disconnectAll() { 2036 if (DBG) { 2037 Log.d(TAG, "disconnectAll()"); 2038 } 2039 Map<Integer, String> connMap = mClientMap.getConnectedMap(); 2040 for (Map.Entry<Integer, String> entry : connMap.entrySet()) { 2041 if (DBG) { 2042 Log.d(TAG, "disconnecting addr:" + entry.getValue()); 2043 } 2044 clientDisconnect(entry.getKey(), entry.getValue()); 2045 //clientDisconnect(int clientIf, String address) 2046 } 2047 } 2048 2049 void unregAll() { 2050 for (Integer appId : mClientMap.getAllAppsIds()) { 2051 if (DBG) { 2052 Log.d(TAG, "unreg:" + appId); 2053 } 2054 unregisterClient(appId); 2055 } 2056 } 2057 2058 /************************************************************************** 2059 * PERIODIC SCANNING 2060 *************************************************************************/ 2061 void registerSync(ScanResult scanResult, int skip, int timeout, 2062 IPeriodicAdvertisingCallback callback) { 2063 enforceAdminPermission(); 2064 mPeriodicScanManager.startSync(scanResult, skip, timeout, callback); 2065 } 2066 2067 void unregisterSync(IPeriodicAdvertisingCallback callback) { 2068 enforceAdminPermission(); 2069 mPeriodicScanManager.stopSync(callback); 2070 } 2071 2072 /************************************************************************** 2073 * ADVERTISING SET 2074 *************************************************************************/ 2075 void startAdvertisingSet(AdvertisingSetParameters parameters, AdvertiseData advertiseData, 2076 AdvertiseData scanResponse, PeriodicAdvertisingParameters periodicParameters, 2077 AdvertiseData periodicData, int duration, int maxExtAdvEvents, 2078 IAdvertisingSetCallback callback) { 2079 enforceAdminPermission(); 2080 mAdvertiseManager.startAdvertisingSet(parameters, advertiseData, scanResponse, 2081 periodicParameters, periodicData, duration, maxExtAdvEvents, callback); 2082 } 2083 2084 void stopAdvertisingSet(IAdvertisingSetCallback callback) { 2085 enforceAdminPermission(); 2086 mAdvertiseManager.stopAdvertisingSet(callback); 2087 } 2088 2089 void getOwnAddress(int advertiserId) { 2090 enforcePrivilegedPermission(); 2091 mAdvertiseManager.getOwnAddress(advertiserId); 2092 } 2093 2094 void enableAdvertisingSet(int advertiserId, boolean enable, int duration, int maxExtAdvEvents) { 2095 enforceAdminPermission(); 2096 mAdvertiseManager.enableAdvertisingSet(advertiserId, enable, duration, maxExtAdvEvents); 2097 } 2098 2099 void setAdvertisingData(int advertiserId, AdvertiseData data) { 2100 enforceAdminPermission(); 2101 mAdvertiseManager.setAdvertisingData(advertiserId, data); 2102 } 2103 2104 void setScanResponseData(int advertiserId, AdvertiseData data) { 2105 enforceAdminPermission(); 2106 mAdvertiseManager.setScanResponseData(advertiserId, data); 2107 } 2108 2109 void setAdvertisingParameters(int advertiserId, AdvertisingSetParameters parameters) { 2110 enforceAdminPermission(); 2111 mAdvertiseManager.setAdvertisingParameters(advertiserId, parameters); 2112 } 2113 2114 void setPeriodicAdvertisingParameters(int advertiserId, 2115 PeriodicAdvertisingParameters parameters) { 2116 enforceAdminPermission(); 2117 mAdvertiseManager.setPeriodicAdvertisingParameters(advertiserId, parameters); 2118 } 2119 2120 void setPeriodicAdvertisingData(int advertiserId, AdvertiseData data) { 2121 enforceAdminPermission(); 2122 mAdvertiseManager.setPeriodicAdvertisingData(advertiserId, data); 2123 } 2124 2125 void setPeriodicAdvertisingEnable(int advertiserId, boolean enable) { 2126 enforceAdminPermission(); 2127 mAdvertiseManager.setPeriodicAdvertisingEnable(advertiserId, enable); 2128 } 2129 2130 /************************************************************************** 2131 * GATT Service functions - CLIENT 2132 *************************************************************************/ 2133 2134 void registerClient(UUID uuid, IBluetoothGattCallback callback) { 2135 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2136 2137 if (DBG) { 2138 Log.d(TAG, "registerClient() - UUID=" + uuid); 2139 } 2140 mClientMap.add(uuid, null, callback, null, this); 2141 gattClientRegisterAppNative(uuid.getLeastSignificantBits(), uuid.getMostSignificantBits()); 2142 } 2143 2144 void unregisterClient(int clientIf) { 2145 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2146 2147 if (DBG) { 2148 Log.d(TAG, "unregisterClient() - clientIf=" + clientIf); 2149 } 2150 mClientMap.remove(clientIf); 2151 gattClientUnregisterAppNative(clientIf); 2152 } 2153 2154 void clientConnect(int clientIf, String address, boolean isDirect, int transport, 2155 boolean opportunistic, int phy) { 2156 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2157 2158 if (DBG) { 2159 Log.d(TAG, "clientConnect() - address=" + address + ", isDirect=" + isDirect 2160 + ", opportunistic=" + opportunistic + ", phy=" + phy); 2161 } 2162 gattClientConnectNative(clientIf, address, isDirect, transport, opportunistic, phy); 2163 } 2164 2165 void clientDisconnect(int clientIf, String address) { 2166 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2167 2168 Integer connId = mClientMap.connIdByAddress(clientIf, address); 2169 if (DBG) { 2170 Log.d(TAG, "clientDisconnect() - address=" + address + ", connId=" + connId); 2171 } 2172 2173 gattClientDisconnectNative(clientIf, address, connId != null ? connId : 0); 2174 } 2175 2176 void clientSetPreferredPhy(int clientIf, String address, int txPhy, int rxPhy, int phyOptions) { 2177 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2178 2179 Integer connId = mClientMap.connIdByAddress(clientIf, address); 2180 if (connId == null) { 2181 if (DBG) { 2182 Log.d(TAG, "clientSetPreferredPhy() - no connection to " + address); 2183 } 2184 return; 2185 } 2186 2187 if (DBG) { 2188 Log.d(TAG, "clientSetPreferredPhy() - address=" + address + ", connId=" + connId); 2189 } 2190 gattClientSetPreferredPhyNative(clientIf, address, txPhy, rxPhy, phyOptions); 2191 } 2192 2193 void clientReadPhy(int clientIf, String address) { 2194 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2195 2196 Integer connId = mClientMap.connIdByAddress(clientIf, address); 2197 if (connId == null) { 2198 if (DBG) { 2199 Log.d(TAG, "clientReadPhy() - no connection to " + address); 2200 } 2201 return; 2202 } 2203 2204 if (DBG) { 2205 Log.d(TAG, "clientReadPhy() - address=" + address + ", connId=" + connId); 2206 } 2207 gattClientReadPhyNative(clientIf, address); 2208 } 2209 2210 int numHwTrackFiltersAvailable() { 2211 return (AdapterService.getAdapterService().getTotalNumOfTrackableAdvertisements() 2212 - mScanManager.getCurrentUsedTrackingAdvertisement()); 2213 } 2214 2215 synchronized List<ParcelUuid> getRegisteredServiceUuids() { 2216 Utils.enforceAdminPermission(this); 2217 List<ParcelUuid> serviceUuids = new ArrayList<ParcelUuid>(); 2218 for (HandleMap.Entry entry : mHandleMap.mEntries) { 2219 serviceUuids.add(new ParcelUuid(entry.uuid)); 2220 } 2221 return serviceUuids; 2222 } 2223 2224 List<String> getConnectedDevices() { 2225 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2226 2227 Set<String> connectedDevAddress = new HashSet<String>(); 2228 connectedDevAddress.addAll(mClientMap.getConnectedDevices()); 2229 connectedDevAddress.addAll(mServerMap.getConnectedDevices()); 2230 List<String> connectedDeviceList = new ArrayList<String>(connectedDevAddress); 2231 return connectedDeviceList; 2232 } 2233 2234 void refreshDevice(int clientIf, String address) { 2235 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2236 2237 if (DBG) { 2238 Log.d(TAG, "refreshDevice() - address=" + address); 2239 } 2240 gattClientRefreshNative(clientIf, address); 2241 } 2242 2243 void discoverServices(int clientIf, String address) { 2244 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2245 2246 Integer connId = mClientMap.connIdByAddress(clientIf, address); 2247 if (DBG) { 2248 Log.d(TAG, "discoverServices() - address=" + address + ", connId=" + connId); 2249 } 2250 2251 if (connId != null) { 2252 gattClientSearchServiceNative(connId, true, 0, 0); 2253 } else { 2254 Log.e(TAG, "discoverServices() - No connection for " + address + "..."); 2255 } 2256 } 2257 2258 void discoverServiceByUuid(int clientIf, String address, UUID uuid) { 2259 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2260 2261 Integer connId = mClientMap.connIdByAddress(clientIf, address); 2262 if (connId != null) { 2263 gattClientDiscoverServiceByUuidNative(connId, uuid.getLeastSignificantBits(), 2264 uuid.getMostSignificantBits()); 2265 } else { 2266 Log.e(TAG, "discoverServiceByUuid() - No connection for " + address + "..."); 2267 } 2268 } 2269 2270 void readCharacteristic(int clientIf, String address, int handle, int authReq) { 2271 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2272 2273 if (VDBG) { 2274 Log.d(TAG, "readCharacteristic() - address=" + address); 2275 } 2276 2277 Integer connId = mClientMap.connIdByAddress(clientIf, address); 2278 if (connId == null) { 2279 Log.e(TAG, "readCharacteristic() - No connection for " + address + "..."); 2280 return; 2281 } 2282 2283 if (!permissionCheck(connId, handle)) { 2284 Log.w(TAG, "readCharacteristic() - permission check failed!"); 2285 return; 2286 } 2287 2288 gattClientReadCharacteristicNative(connId, handle, authReq); 2289 } 2290 2291 void readUsingCharacteristicUuid(int clientIf, String address, UUID uuid, int startHandle, 2292 int endHandle, int authReq) { 2293 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2294 2295 if (VDBG) { 2296 Log.d(TAG, "readUsingCharacteristicUuid() - address=" + address); 2297 } 2298 2299 Integer connId = mClientMap.connIdByAddress(clientIf, address); 2300 if (connId == null) { 2301 Log.e(TAG, "readUsingCharacteristicUuid() - No connection for " + address + "..."); 2302 return; 2303 } 2304 2305 if (!permissionCheck(uuid)) { 2306 Log.w(TAG, "readUsingCharacteristicUuid() - permission check failed!"); 2307 return; 2308 } 2309 2310 gattClientReadUsingCharacteristicUuidNative(connId, uuid.getLeastSignificantBits(), 2311 uuid.getMostSignificantBits(), startHandle, endHandle, authReq); 2312 } 2313 2314 void writeCharacteristic(int clientIf, String address, int handle, int writeType, int authReq, 2315 byte[] value) { 2316 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2317 2318 if (VDBG) { 2319 Log.d(TAG, "writeCharacteristic() - address=" + address); 2320 } 2321 2322 if (mReliableQueue.contains(address)) { 2323 writeType = 3; // Prepared write 2324 } 2325 2326 Integer connId = mClientMap.connIdByAddress(clientIf, address); 2327 if (connId == null) { 2328 Log.e(TAG, "writeCharacteristic() - No connection for " + address + "..."); 2329 return; 2330 } 2331 2332 if (!permissionCheck(connId, handle)) { 2333 Log.w(TAG, "writeCharacteristic() - permission check failed!"); 2334 return; 2335 } 2336 2337 gattClientWriteCharacteristicNative(connId, handle, writeType, authReq, value); 2338 } 2339 2340 void readDescriptor(int clientIf, String address, int handle, int authReq) { 2341 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2342 2343 if (VDBG) { 2344 Log.d(TAG, "readDescriptor() - address=" + address); 2345 } 2346 2347 Integer connId = mClientMap.connIdByAddress(clientIf, address); 2348 if (connId == null) { 2349 Log.e(TAG, "readDescriptor() - No connection for " + address + "..."); 2350 return; 2351 } 2352 2353 if (!permissionCheck(connId, handle)) { 2354 Log.w(TAG, "readDescriptor() - permission check failed!"); 2355 return; 2356 } 2357 2358 gattClientReadDescriptorNative(connId, handle, authReq); 2359 } 2360 2361 ; 2362 2363 void writeDescriptor(int clientIf, String address, int handle, int authReq, byte[] value) { 2364 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2365 if (VDBG) { 2366 Log.d(TAG, "writeDescriptor() - address=" + address); 2367 } 2368 2369 Integer connId = mClientMap.connIdByAddress(clientIf, address); 2370 if (connId == null) { 2371 Log.e(TAG, "writeDescriptor() - No connection for " + address + "..."); 2372 return; 2373 } 2374 2375 if (!permissionCheck(connId, handle)) { 2376 Log.w(TAG, "writeDescriptor() - permission check failed!"); 2377 return; 2378 } 2379 2380 gattClientWriteDescriptorNative(connId, handle, authReq, value); 2381 } 2382 2383 void beginReliableWrite(int clientIf, String address) { 2384 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2385 2386 if (DBG) { 2387 Log.d(TAG, "beginReliableWrite() - address=" + address); 2388 } 2389 mReliableQueue.add(address); 2390 } 2391 2392 void endReliableWrite(int clientIf, String address, boolean execute) { 2393 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2394 2395 if (DBG) { 2396 Log.d(TAG, "endReliableWrite() - address=" + address + " execute: " + execute); 2397 } 2398 mReliableQueue.remove(address); 2399 2400 Integer connId = mClientMap.connIdByAddress(clientIf, address); 2401 if (connId != null) { 2402 gattClientExecuteWriteNative(connId, execute); 2403 } 2404 } 2405 2406 void registerForNotification(int clientIf, String address, int handle, boolean enable) { 2407 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2408 2409 if (DBG) { 2410 Log.d(TAG, "registerForNotification() - address=" + address + " enable: " + enable); 2411 } 2412 2413 Integer connId = mClientMap.connIdByAddress(clientIf, address); 2414 if (connId == null) { 2415 Log.e(TAG, "registerForNotification() - No connection for " + address + "..."); 2416 return; 2417 } 2418 2419 if (!permissionCheck(connId, handle)) { 2420 Log.w(TAG, "registerForNotification() - permission check failed!"); 2421 return; 2422 } 2423 2424 gattClientRegisterForNotificationsNative(clientIf, address, handle, enable); 2425 } 2426 2427 void readRemoteRssi(int clientIf, String address) { 2428 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2429 2430 if (DBG) { 2431 Log.d(TAG, "readRemoteRssi() - address=" + address); 2432 } 2433 gattClientReadRemoteRssiNative(clientIf, address); 2434 } 2435 2436 void configureMTU(int clientIf, String address, int mtu) { 2437 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2438 2439 if (DBG) { 2440 Log.d(TAG, "configureMTU() - address=" + address + " mtu=" + mtu); 2441 } 2442 Integer connId = mClientMap.connIdByAddress(clientIf, address); 2443 if (connId != null) { 2444 gattClientConfigureMTUNative(connId, mtu); 2445 } else { 2446 Log.e(TAG, "configureMTU() - No connection for " + address + "..."); 2447 } 2448 } 2449 2450 void connectionParameterUpdate(int clientIf, String address, int connectionPriority) { 2451 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2452 2453 int minInterval; 2454 int maxInterval; 2455 2456 // Slave latency 2457 int latency; 2458 2459 // Link supervision timeout is measured in N * 10ms 2460 int timeout = 2000; // 20s 2461 2462 switch (connectionPriority) { 2463 case BluetoothGatt.CONNECTION_PRIORITY_HIGH: 2464 minInterval = getResources().getInteger(R.integer.gatt_high_priority_min_interval); 2465 maxInterval = getResources().getInteger(R.integer.gatt_high_priority_max_interval); 2466 latency = getResources().getInteger(R.integer.gatt_high_priority_latency); 2467 break; 2468 2469 case BluetoothGatt.CONNECTION_PRIORITY_LOW_POWER: 2470 minInterval = getResources().getInteger(R.integer.gatt_low_power_min_interval); 2471 maxInterval = getResources().getInteger(R.integer.gatt_low_power_max_interval); 2472 latency = getResources().getInteger(R.integer.gatt_low_power_latency); 2473 break; 2474 2475 default: 2476 // Using the values for CONNECTION_PRIORITY_BALANCED. 2477 minInterval = 2478 getResources().getInteger(R.integer.gatt_balanced_priority_min_interval); 2479 maxInterval = 2480 getResources().getInteger(R.integer.gatt_balanced_priority_max_interval); 2481 latency = getResources().getInteger(R.integer.gatt_balanced_priority_latency); 2482 break; 2483 } 2484 2485 if (DBG) { 2486 Log.d(TAG, "connectionParameterUpdate() - address=" + address + "params=" 2487 + connectionPriority + " interval=" + minInterval + "/" + maxInterval); 2488 } 2489 gattConnectionParameterUpdateNative(clientIf, address, minInterval, maxInterval, latency, 2490 timeout, 0, 0); 2491 } 2492 2493 void leConnectionUpdate(int clientIf, String address, int minInterval, 2494 int maxInterval, int slaveLatency, 2495 int supervisionTimeout, int minConnectionEventLen, 2496 int maxConnectionEventLen) { 2497 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2498 2499 if (DBG) { 2500 Log.d(TAG, "leConnectionUpdate() - address=" + address + ", intervals=" 2501 + minInterval + "/" + maxInterval + ", latency=" + slaveLatency 2502 + ", timeout=" + supervisionTimeout + "msec" + ", min_ce=" 2503 + minConnectionEventLen + ", max_ce=" + maxConnectionEventLen); 2504 2505 2506 } 2507 gattConnectionParameterUpdateNative(clientIf, address, minInterval, maxInterval, 2508 slaveLatency, supervisionTimeout, 2509 minConnectionEventLen, maxConnectionEventLen); 2510 } 2511 2512 /************************************************************************** 2513 * Callback functions - SERVER 2514 *************************************************************************/ 2515 2516 void onServerRegistered(int status, int serverIf, long uuidLsb, long uuidMsb) 2517 throws RemoteException { 2518 2519 UUID uuid = new UUID(uuidMsb, uuidLsb); 2520 if (DBG) { 2521 Log.d(TAG, "onServerRegistered() - UUID=" + uuid + ", serverIf=" + serverIf); 2522 } 2523 ServerMap.App app = mServerMap.getByUuid(uuid); 2524 if (app != null) { 2525 app.id = serverIf; 2526 app.linkToDeath(new ServerDeathRecipient(serverIf)); 2527 app.callback.onServerRegistered(status, serverIf); 2528 } 2529 } 2530 2531 void onServiceAdded(int status, int serverIf, List<GattDbElement> service) 2532 throws RemoteException { 2533 if (DBG) { 2534 Log.d(TAG, "onServiceAdded(), status=" + status); 2535 } 2536 2537 if (status != 0) { 2538 return; 2539 } 2540 2541 GattDbElement svcEl = service.get(0); 2542 int srvcHandle = svcEl.attributeHandle; 2543 2544 BluetoothGattService svc = null; 2545 2546 for (GattDbElement el : service) { 2547 if (el.type == GattDbElement.TYPE_PRIMARY_SERVICE) { 2548 mHandleMap.addService(serverIf, el.attributeHandle, el.uuid, 2549 BluetoothGattService.SERVICE_TYPE_PRIMARY, 0, false); 2550 svc = new BluetoothGattService(svcEl.uuid, svcEl.attributeHandle, 2551 BluetoothGattService.SERVICE_TYPE_PRIMARY); 2552 } else if (el.type == GattDbElement.TYPE_SECONDARY_SERVICE) { 2553 mHandleMap.addService(serverIf, el.attributeHandle, el.uuid, 2554 BluetoothGattService.SERVICE_TYPE_SECONDARY, 0, false); 2555 svc = new BluetoothGattService(svcEl.uuid, svcEl.attributeHandle, 2556 BluetoothGattService.SERVICE_TYPE_SECONDARY); 2557 } else if (el.type == GattDbElement.TYPE_CHARACTERISTIC) { 2558 mHandleMap.addCharacteristic(serverIf, el.attributeHandle, el.uuid, srvcHandle); 2559 svc.addCharacteristic( 2560 new BluetoothGattCharacteristic(el.uuid, el.attributeHandle, el.properties, 2561 el.permissions)); 2562 } else if (el.type == GattDbElement.TYPE_DESCRIPTOR) { 2563 mHandleMap.addDescriptor(serverIf, el.attributeHandle, el.uuid, srvcHandle); 2564 List<BluetoothGattCharacteristic> chars = svc.getCharacteristics(); 2565 chars.get(chars.size() - 1) 2566 .addDescriptor(new BluetoothGattDescriptor(el.uuid, el.attributeHandle, 2567 el.permissions)); 2568 } 2569 } 2570 mHandleMap.setStarted(serverIf, srvcHandle, true); 2571 2572 ServerMap.App app = mServerMap.getById(serverIf); 2573 if (app != null) { 2574 app.callback.onServiceAdded(status, svc); 2575 } 2576 } 2577 2578 void onServiceStopped(int status, int serverIf, int srvcHandle) throws RemoteException { 2579 if (DBG) { 2580 Log.d(TAG, "onServiceStopped() srvcHandle=" + srvcHandle + ", status=" + status); 2581 } 2582 if (status == 0) { 2583 mHandleMap.setStarted(serverIf, srvcHandle, false); 2584 } 2585 stopNextService(serverIf, status); 2586 } 2587 2588 void onServiceDeleted(int status, int serverIf, int srvcHandle) { 2589 if (DBG) { 2590 Log.d(TAG, "onServiceDeleted() srvcHandle=" + srvcHandle + ", status=" + status); 2591 } 2592 mHandleMap.deleteService(serverIf, srvcHandle); 2593 } 2594 2595 void onClientConnected(String address, boolean connected, int connId, int serverIf) 2596 throws RemoteException { 2597 2598 if (DBG) { 2599 Log.d(TAG, 2600 "onClientConnected() connId=" + connId + ", address=" + address + ", connected=" 2601 + connected); 2602 } 2603 2604 ServerMap.App app = mServerMap.getById(serverIf); 2605 if (app == null) { 2606 return; 2607 } 2608 2609 if (connected) { 2610 mServerMap.addConnection(serverIf, connId, address); 2611 } else { 2612 mServerMap.removeConnection(serverIf, connId); 2613 } 2614 2615 app.callback.onServerConnectionState((byte) 0, serverIf, connected, address); 2616 } 2617 2618 void onServerReadCharacteristic(String address, int connId, int transId, int handle, int offset, 2619 boolean isLong) throws RemoteException { 2620 if (VDBG) { 2621 Log.d(TAG, "onServerReadCharacteristic() connId=" + connId + ", address=" + address 2622 + ", handle=" + handle + ", requestId=" + transId + ", offset=" + offset); 2623 } 2624 2625 HandleMap.Entry entry = mHandleMap.getByHandle(handle); 2626 if (entry == null) { 2627 return; 2628 } 2629 2630 mHandleMap.addRequest(transId, handle); 2631 2632 ServerMap.App app = mServerMap.getById(entry.serverIf); 2633 if (app == null) { 2634 return; 2635 } 2636 2637 app.callback.onCharacteristicReadRequest(address, transId, offset, isLong, handle); 2638 } 2639 2640 void onServerReadDescriptor(String address, int connId, int transId, int handle, int offset, 2641 boolean isLong) throws RemoteException { 2642 if (VDBG) { 2643 Log.d(TAG, "onServerReadDescriptor() connId=" + connId + ", address=" + address 2644 + ", handle=" + handle + ", requestId=" + transId + ", offset=" + offset); 2645 } 2646 2647 HandleMap.Entry entry = mHandleMap.getByHandle(handle); 2648 if (entry == null) { 2649 return; 2650 } 2651 2652 mHandleMap.addRequest(transId, handle); 2653 2654 ServerMap.App app = mServerMap.getById(entry.serverIf); 2655 if (app == null) { 2656 return; 2657 } 2658 2659 app.callback.onDescriptorReadRequest(address, transId, offset, isLong, handle); 2660 } 2661 2662 void onServerWriteCharacteristic(String address, int connId, int transId, int handle, 2663 int offset, int length, boolean needRsp, boolean isPrep, byte[] data) 2664 throws RemoteException { 2665 if (VDBG) { 2666 Log.d(TAG, "onServerWriteCharacteristic() connId=" + connId + ", address=" + address 2667 + ", handle=" + handle + ", requestId=" + transId + ", isPrep=" + isPrep 2668 + ", offset=" + offset); 2669 } 2670 2671 HandleMap.Entry entry = mHandleMap.getByHandle(handle); 2672 if (entry == null) { 2673 return; 2674 } 2675 2676 mHandleMap.addRequest(transId, handle); 2677 2678 ServerMap.App app = mServerMap.getById(entry.serverIf); 2679 if (app == null) { 2680 return; 2681 } 2682 2683 app.callback.onCharacteristicWriteRequest(address, transId, offset, length, isPrep, needRsp, 2684 handle, data); 2685 } 2686 2687 void onServerWriteDescriptor(String address, int connId, int transId, int handle, int offset, 2688 int length, boolean needRsp, boolean isPrep, byte[] data) throws RemoteException { 2689 if (VDBG) { 2690 Log.d(TAG, "onAttributeWrite() connId=" + connId + ", address=" + address + ", handle=" 2691 + handle + ", requestId=" + transId + ", isPrep=" + isPrep + ", offset=" 2692 + offset); 2693 } 2694 2695 HandleMap.Entry entry = mHandleMap.getByHandle(handle); 2696 if (entry == null) { 2697 return; 2698 } 2699 2700 mHandleMap.addRequest(transId, handle); 2701 2702 ServerMap.App app = mServerMap.getById(entry.serverIf); 2703 if (app == null) { 2704 return; 2705 } 2706 2707 app.callback.onDescriptorWriteRequest(address, transId, offset, length, isPrep, needRsp, 2708 handle, data); 2709 } 2710 2711 void onExecuteWrite(String address, int connId, int transId, int execWrite) 2712 throws RemoteException { 2713 if (DBG) { 2714 Log.d(TAG, "onExecuteWrite() connId=" + connId + ", address=" + address + ", transId=" 2715 + transId); 2716 } 2717 2718 ServerMap.App app = mServerMap.getByConnId(connId); 2719 if (app == null) { 2720 return; 2721 } 2722 2723 app.callback.onExecuteWrite(address, transId, execWrite == 1); 2724 } 2725 2726 void onResponseSendCompleted(int status, int attrHandle) { 2727 if (DBG) { 2728 Log.d(TAG, "onResponseSendCompleted() handle=" + attrHandle); 2729 } 2730 } 2731 2732 void onNotificationSent(int connId, int status) throws RemoteException { 2733 if (VDBG) { 2734 Log.d(TAG, "onNotificationSent() connId=" + connId + ", status=" + status); 2735 } 2736 2737 String address = mServerMap.addressByConnId(connId); 2738 if (address == null) { 2739 return; 2740 } 2741 2742 ServerMap.App app = mServerMap.getByConnId(connId); 2743 if (app == null) { 2744 return; 2745 } 2746 2747 if (!app.isCongested) { 2748 app.callback.onNotificationSent(address, status); 2749 } else { 2750 if (status == BluetoothGatt.GATT_CONNECTION_CONGESTED) { 2751 status = BluetoothGatt.GATT_SUCCESS; 2752 } 2753 app.queueCallback(new CallbackInfo(address, status)); 2754 } 2755 } 2756 2757 void onServerCongestion(int connId, boolean congested) throws RemoteException { 2758 if (DBG) { 2759 Log.d(TAG, "onServerCongestion() - connId=" + connId + ", congested=" + congested); 2760 } 2761 2762 ServerMap.App app = mServerMap.getByConnId(connId); 2763 if (app == null) { 2764 return; 2765 } 2766 2767 app.isCongested = congested; 2768 while (!app.isCongested) { 2769 CallbackInfo callbackInfo = app.popQueuedCallback(); 2770 if (callbackInfo == null) { 2771 return; 2772 } 2773 app.callback.onNotificationSent(callbackInfo.address, callbackInfo.status); 2774 } 2775 } 2776 2777 void onMtuChanged(int connId, int mtu) throws RemoteException { 2778 if (DBG) { 2779 Log.d(TAG, "onMtuChanged() - connId=" + connId + ", mtu=" + mtu); 2780 } 2781 2782 String address = mServerMap.addressByConnId(connId); 2783 if (address == null) { 2784 return; 2785 } 2786 2787 ServerMap.App app = mServerMap.getByConnId(connId); 2788 if (app == null) { 2789 return; 2790 } 2791 2792 app.callback.onMtuChanged(address, mtu); 2793 } 2794 2795 /************************************************************************** 2796 * GATT Service functions - SERVER 2797 *************************************************************************/ 2798 2799 void registerServer(UUID uuid, IBluetoothGattServerCallback callback) { 2800 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2801 2802 if (DBG) { 2803 Log.d(TAG, "registerServer() - UUID=" + uuid); 2804 } 2805 mServerMap.add(uuid, null, callback, null, this); 2806 gattServerRegisterAppNative(uuid.getLeastSignificantBits(), uuid.getMostSignificantBits()); 2807 } 2808 2809 void unregisterServer(int serverIf) { 2810 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2811 2812 if (DBG) { 2813 Log.d(TAG, "unregisterServer() - serverIf=" + serverIf); 2814 } 2815 2816 deleteServices(serverIf); 2817 2818 mServerMap.remove(serverIf); 2819 gattServerUnregisterAppNative(serverIf); 2820 } 2821 2822 void serverConnect(int serverIf, String address, boolean isDirect, int transport) { 2823 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2824 2825 if (DBG) { 2826 Log.d(TAG, "serverConnect() - address=" + address); 2827 } 2828 gattServerConnectNative(serverIf, address, isDirect, transport); 2829 } 2830 2831 void serverDisconnect(int serverIf, String address) { 2832 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2833 2834 Integer connId = mServerMap.connIdByAddress(serverIf, address); 2835 if (DBG) { 2836 Log.d(TAG, "serverDisconnect() - address=" + address + ", connId=" + connId); 2837 } 2838 2839 gattServerDisconnectNative(serverIf, address, connId != null ? connId : 0); 2840 } 2841 2842 void serverSetPreferredPhy(int serverIf, String address, int txPhy, int rxPhy, int phyOptions) { 2843 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2844 2845 Integer connId = mServerMap.connIdByAddress(serverIf, address); 2846 if (connId == null) { 2847 if (DBG) { 2848 Log.d(TAG, "serverSetPreferredPhy() - no connection to " + address); 2849 } 2850 return; 2851 } 2852 2853 if (DBG) { 2854 Log.d(TAG, "serverSetPreferredPhy() - address=" + address + ", connId=" + connId); 2855 } 2856 gattServerSetPreferredPhyNative(serverIf, address, txPhy, rxPhy, phyOptions); 2857 } 2858 2859 void serverReadPhy(int serverIf, String address) { 2860 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2861 2862 Integer connId = mServerMap.connIdByAddress(serverIf, address); 2863 if (connId == null) { 2864 if (DBG) { 2865 Log.d(TAG, "serverReadPhy() - no connection to " + address); 2866 } 2867 return; 2868 } 2869 2870 if (DBG) { 2871 Log.d(TAG, "serverReadPhy() - address=" + address + ", connId=" + connId); 2872 } 2873 gattServerReadPhyNative(serverIf, address); 2874 } 2875 2876 void addService(int serverIf, BluetoothGattService service) { 2877 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2878 2879 if (DBG) { 2880 Log.d(TAG, "addService() - uuid=" + service.getUuid()); 2881 } 2882 2883 List<GattDbElement> db = new ArrayList<GattDbElement>(); 2884 2885 if (service.getType() == BluetoothGattService.SERVICE_TYPE_PRIMARY) { 2886 db.add(GattDbElement.createPrimaryService(service.getUuid())); 2887 } else { 2888 db.add(GattDbElement.createSecondaryService(service.getUuid())); 2889 } 2890 2891 for (BluetoothGattService includedService : service.getIncludedServices()) { 2892 int inclSrvcHandle = includedService.getInstanceId(); 2893 2894 if (mHandleMap.checkServiceExists(includedService.getUuid(), inclSrvcHandle)) { 2895 db.add(GattDbElement.createIncludedService(inclSrvcHandle)); 2896 } else { 2897 Log.e(TAG, 2898 "included service with UUID " + includedService.getUuid() + " not found!"); 2899 } 2900 } 2901 2902 for (BluetoothGattCharacteristic characteristic : service.getCharacteristics()) { 2903 int permission = 2904 ((characteristic.getKeySize() - 7) << 12) + characteristic.getPermissions(); 2905 db.add(GattDbElement.createCharacteristic(characteristic.getUuid(), 2906 characteristic.getProperties(), permission)); 2907 2908 for (BluetoothGattDescriptor descriptor : characteristic.getDescriptors()) { 2909 permission = 2910 ((characteristic.getKeySize() - 7) << 12) + descriptor.getPermissions(); 2911 db.add(GattDbElement.createDescriptor(descriptor.getUuid(), permission)); 2912 } 2913 } 2914 2915 gattServerAddServiceNative(serverIf, db); 2916 } 2917 2918 void removeService(int serverIf, int handle) { 2919 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2920 2921 if (DBG) { 2922 Log.d(TAG, "removeService() - handle=" + handle); 2923 } 2924 2925 gattServerDeleteServiceNative(serverIf, handle); 2926 } 2927 2928 void clearServices(int serverIf) { 2929 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2930 2931 if (DBG) { 2932 Log.d(TAG, "clearServices()"); 2933 } 2934 deleteServices(serverIf); 2935 } 2936 2937 void sendResponse(int serverIf, String address, int requestId, int status, int offset, 2938 byte[] value) { 2939 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2940 2941 if (VDBG) { 2942 Log.d(TAG, "sendResponse() - address=" + address); 2943 } 2944 2945 int handle = 0; 2946 HandleMap.Entry entry = mHandleMap.getByRequestId(requestId); 2947 if (entry != null) { 2948 handle = entry.handle; 2949 } 2950 2951 Integer connId = mServerMap.connIdByAddress(serverIf, address); 2952 gattServerSendResponseNative(serverIf, connId != null ? connId : 0, requestId, 2953 (byte) status, handle, offset, value, (byte) 0); 2954 mHandleMap.deleteRequest(requestId); 2955 } 2956 2957 void sendNotification(int serverIf, String address, int handle, boolean confirm, byte[] value) { 2958 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2959 2960 if (VDBG) { 2961 Log.d(TAG, "sendNotification() - address=" + address + " handle=" + handle); 2962 } 2963 2964 Integer connId = mServerMap.connIdByAddress(serverIf, address); 2965 if (connId == null || connId == 0) { 2966 return; 2967 } 2968 2969 if (confirm) { 2970 gattServerSendIndicationNative(serverIf, handle, connId, value); 2971 } else { 2972 gattServerSendNotificationNative(serverIf, handle, connId, value); 2973 } 2974 } 2975 2976 2977 /************************************************************************** 2978 * Private functions 2979 *************************************************************************/ 2980 2981 private boolean isRestrictedCharUuid(final UUID charUuid) { 2982 return isHidUuid(charUuid); 2983 } 2984 2985 private boolean isRestrictedSrvcUuid(final UUID srvcUuid) { 2986 return isFidoUUID(srvcUuid); 2987 } 2988 2989 private boolean isHidUuid(final UUID uuid) { 2990 for (UUID hidUuid : HID_UUIDS) { 2991 if (hidUuid.equals(uuid)) { 2992 return true; 2993 } 2994 } 2995 return false; 2996 } 2997 2998 private boolean isFidoUUID(final UUID uuid) { 2999 for (UUID fidoUuid : FIDO_UUIDS) { 3000 if (fidoUuid.equals(uuid)) { 3001 return true; 3002 } 3003 } 3004 return false; 3005 } 3006 3007 private int getDeviceType(BluetoothDevice device) { 3008 int type = gattClientGetDeviceTypeNative(device.getAddress()); 3009 if (DBG) { 3010 Log.d(TAG, "getDeviceType() - device=" + device + ", type=" + type); 3011 } 3012 return type; 3013 } 3014 3015 private void enforceAdminPermission() { 3016 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); 3017 } 3018 3019 private boolean needsPrivilegedPermissionForScan(ScanSettings settings) { 3020 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 3021 // BLE scan only mode needs special permission. 3022 if (adapter.getState() != BluetoothAdapter.STATE_ON) { 3023 return true; 3024 } 3025 3026 // Regular scan, no special permission. 3027 if (settings == null) { 3028 return false; 3029 } 3030 3031 // Regular scan, no special permission. 3032 if (settings.getReportDelayMillis() == 0) { 3033 return false; 3034 } 3035 3036 // Batch scan, truncated mode needs permission. 3037 return settings.getScanResultType() == ScanSettings.SCAN_RESULT_TYPE_ABBREVIATED; 3038 } 3039 3040 // Enforce caller has BLUETOOTH_PRIVILEGED permission. A {@link SecurityException} will be 3041 // thrown if the caller app does not have BLUETOOTH_PRIVILEGED permission. 3042 private void enforcePrivilegedPermission() { 3043 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, 3044 "Need BLUETOOTH_PRIVILEGED permission"); 3045 } 3046 3047 // Enforce caller has UPDATE_DEVICE_STATS permission, which allows the caller to blame other 3048 // apps for Bluetooth usage. A {@link SecurityException} will be thrown if the caller app does 3049 // not have UPDATE_DEVICE_STATS permission. 3050 private void enforceImpersonatationPermission() { 3051 enforceCallingOrSelfPermission(android.Manifest.permission.UPDATE_DEVICE_STATS, 3052 "Need UPDATE_DEVICE_STATS permission"); 3053 } 3054 3055 private void stopNextService(int serverIf, int status) throws RemoteException { 3056 if (DBG) { 3057 Log.d(TAG, "stopNextService() - serverIf=" + serverIf + ", status=" + status); 3058 } 3059 3060 if (status == 0) { 3061 List<HandleMap.Entry> entries = mHandleMap.getEntries(); 3062 for (HandleMap.Entry entry : entries) { 3063 if (entry.type != HandleMap.TYPE_SERVICE || entry.serverIf != serverIf 3064 || !entry.started) { 3065 continue; 3066 } 3067 3068 gattServerStopServiceNative(serverIf, entry.handle); 3069 return; 3070 } 3071 } 3072 } 3073 3074 private void deleteServices(int serverIf) { 3075 if (DBG) { 3076 Log.d(TAG, "deleteServices() - serverIf=" + serverIf); 3077 } 3078 3079 /* 3080 * Figure out which handles to delete. 3081 * The handles are copied into a new list to avoid race conditions. 3082 */ 3083 List<Integer> handleList = new ArrayList<Integer>(); 3084 List<HandleMap.Entry> entries = mHandleMap.getEntries(); 3085 for (HandleMap.Entry entry : entries) { 3086 if (entry.type != HandleMap.TYPE_SERVICE || entry.serverIf != serverIf) { 3087 continue; 3088 } 3089 handleList.add(entry.handle); 3090 } 3091 3092 /* Now actually delete the services.... */ 3093 for (Integer handle : handleList) { 3094 gattServerDeleteServiceNative(serverIf, handle); 3095 } 3096 } 3097 3098 private List<UUID> parseUuids(byte[] advData) { 3099 List<UUID> uuids = new ArrayList<UUID>(); 3100 3101 int offset = 0; 3102 while (offset < (advData.length - 2)) { 3103 int len = Byte.toUnsignedInt(advData[offset++]); 3104 if (len == 0) { 3105 break; 3106 } 3107 3108 int type = advData[offset++]; 3109 switch (type) { 3110 case 0x02: // Partial list of 16-bit UUIDs 3111 case 0x03: // Complete list of 16-bit UUIDs 3112 while (len > 1) { 3113 int uuid16 = advData[offset++]; 3114 uuid16 += (advData[offset++] << 8); 3115 len -= 2; 3116 uuids.add(UUID.fromString( 3117 String.format("%08x-0000-1000-8000-00805f9b34fb", uuid16))); 3118 } 3119 break; 3120 3121 default: 3122 offset += (len - 1); 3123 break; 3124 } 3125 } 3126 3127 return uuids; 3128 } 3129 3130 @Override 3131 public void dump(StringBuilder sb) { 3132 super.dump(sb); 3133 println(sb, "mAdvertisingServiceUuids:"); 3134 for (UUID uuid : mAdvertisingServiceUuids) { 3135 println(sb, " " + uuid); 3136 } 3137 3138 println(sb, "mMaxScanFilters: " + mMaxScanFilters); 3139 3140 sb.append("\nGATT Scanner Map\n"); 3141 mScannerMap.dump(sb); 3142 3143 sb.append("GATT Client Map\n"); 3144 mClientMap.dump(sb); 3145 3146 sb.append("GATT Server Map\n"); 3147 mServerMap.dump(sb); 3148 3149 sb.append("GATT Handle Map\n"); 3150 mHandleMap.dump(sb); 3151 } 3152 3153 void addScanEvent(BluetoothMetricsProto.ScanEvent event) { 3154 synchronized (mScanEvents) { 3155 if (mScanEvents.size() == NUM_SCAN_EVENTS_KEPT) { 3156 mScanEvents.remove(0); 3157 } 3158 mScanEvents.add(event); 3159 } 3160 } 3161 3162 @Override 3163 public void dumpProto(BluetoothMetricsProto.BluetoothLog.Builder builder) { 3164 synchronized (mScanEvents) { 3165 builder.addAllScanEvent(mScanEvents); 3166 } 3167 } 3168 3169 /************************************************************************** 3170 * GATT Test functions 3171 *************************************************************************/ 3172 3173 void gattTestCommand(int command, UUID uuid1, String bda1, int p1, int p2, int p3, int p4, 3174 int p5) { 3175 if (bda1 == null) { 3176 bda1 = "00:00:00:00:00:00"; 3177 } 3178 if (uuid1 != null) { 3179 gattTestNative(command, uuid1.getLeastSignificantBits(), uuid1.getMostSignificantBits(), 3180 bda1, p1, p2, p3, p4, p5); 3181 } else { 3182 gattTestNative(command, 0, 0, bda1, p1, p2, p3, p4, p5); 3183 } 3184 } 3185 3186 private native void gattTestNative(int command, long uuid1Lsb, long uuid1Msb, String bda1, 3187 int p1, int p2, int p3, int p4, int p5); 3188 3189 /************************************************************************** 3190 * Native functions prototypes 3191 *************************************************************************/ 3192 3193 private static native void classInitNative(); 3194 3195 private native void initializeNative(); 3196 3197 private native void cleanupNative(); 3198 3199 private native int gattClientGetDeviceTypeNative(String address); 3200 3201 private native void gattClientRegisterAppNative(long appUuidLsb, long appUuidMsb); 3202 3203 private native void gattClientUnregisterAppNative(int clientIf); 3204 3205 private native void gattClientConnectNative(int clientIf, String address, boolean isDirect, 3206 int transport, boolean opportunistic, int initiatingPhys); 3207 3208 private native void gattClientDisconnectNative(int clientIf, String address, int connId); 3209 3210 private native void gattClientSetPreferredPhyNative(int clientIf, String address, int txPhy, 3211 int rxPhy, int phyOptions); 3212 3213 private native void gattClientReadPhyNative(int clientIf, String address); 3214 3215 private native void gattClientRefreshNative(int clientIf, String address); 3216 3217 private native void gattClientSearchServiceNative(int connId, boolean searchAll, 3218 long serviceUuidLsb, long serviceUuidMsb); 3219 3220 private native void gattClientDiscoverServiceByUuidNative(int connId, long serviceUuidLsb, 3221 long serviceUuidMsb); 3222 3223 private native void gattClientGetGattDbNative(int connId); 3224 3225 private native void gattClientReadCharacteristicNative(int connId, int handle, int authReq); 3226 3227 private native void gattClientReadUsingCharacteristicUuidNative(int connId, long uuidMsb, 3228 long uuidLsb, int sHandle, int eHandle, int authReq); 3229 3230 private native void gattClientReadDescriptorNative(int connId, int handle, int authReq); 3231 3232 private native void gattClientWriteCharacteristicNative(int connId, int handle, int writeType, 3233 int authReq, byte[] value); 3234 3235 private native void gattClientWriteDescriptorNative(int connId, int handle, int authReq, 3236 byte[] value); 3237 3238 private native void gattClientExecuteWriteNative(int connId, boolean execute); 3239 3240 private native void gattClientRegisterForNotificationsNative(int clientIf, String address, 3241 int handle, boolean enable); 3242 3243 private native void gattClientReadRemoteRssiNative(int clientIf, String address); 3244 3245 private native void gattClientConfigureMTUNative(int connId, int mtu); 3246 3247 private native void gattConnectionParameterUpdateNative(int clientIf, String address, 3248 int minInterval, int maxInterval, int latency, int timeout, int minConnectionEventLen, 3249 int maxConnectionEventLen); 3250 3251 private native void gattServerRegisterAppNative(long appUuidLsb, long appUuidMsb); 3252 3253 private native void gattServerUnregisterAppNative(int serverIf); 3254 3255 private native void gattServerConnectNative(int serverIf, String address, boolean isDirect, 3256 int transport); 3257 3258 private native void gattServerDisconnectNative(int serverIf, String address, int connId); 3259 3260 private native void gattServerSetPreferredPhyNative(int clientIf, String address, int txPhy, 3261 int rxPhy, int phyOptions); 3262 3263 private native void gattServerReadPhyNative(int clientIf, String address); 3264 3265 private native void gattServerAddServiceNative(int serverIf, List<GattDbElement> service); 3266 3267 private native void gattServerStopServiceNative(int serverIf, int svcHandle); 3268 3269 private native void gattServerDeleteServiceNative(int serverIf, int svcHandle); 3270 3271 private native void gattServerSendIndicationNative(int serverIf, int attrHandle, int connId, 3272 byte[] val); 3273 3274 private native void gattServerSendNotificationNative(int serverIf, int attrHandle, int connId, 3275 byte[] val); 3276 3277 private native void gattServerSendResponseNative(int serverIf, int connId, int transId, 3278 int status, int handle, int offset, byte[] val, int authReq); 3279 } 3280