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