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