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