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