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 com.android.bluetooth.Utils.callerIsSystemOrActiveOrManagedUser; 20 import static com.android.bluetooth.Utils.checkCallerTargetSdk; 21 import static com.android.bluetooth.Utils.enforceBluetoothPrivilegedPermission; 22 23 import android.annotation.RequiresPermission; 24 import android.annotation.SuppressLint; 25 import android.app.AppOpsManager; 26 import android.app.PendingIntent; 27 import android.app.Service; 28 import android.bluetooth.BluetoothAdapter; 29 import android.bluetooth.BluetoothDevice; 30 import android.bluetooth.BluetoothGatt; 31 import android.bluetooth.BluetoothGattCharacteristic; 32 import android.bluetooth.BluetoothGattDescriptor; 33 import android.bluetooth.BluetoothGattService; 34 import android.bluetooth.BluetoothProfile; 35 import android.bluetooth.BluetoothProtoEnums; 36 import android.bluetooth.BluetoothStatusCodes; 37 import android.bluetooth.BluetoothUtils; 38 import android.bluetooth.IBluetoothGatt; 39 import android.bluetooth.IBluetoothGattCallback; 40 import android.bluetooth.IBluetoothGattServerCallback; 41 import android.bluetooth.le.AdvertiseData; 42 import android.bluetooth.le.AdvertisingSetParameters; 43 import android.bluetooth.le.BluetoothLeScanner; 44 import android.bluetooth.le.DistanceMeasurementMethod; 45 import android.bluetooth.le.DistanceMeasurementParams; 46 import android.bluetooth.le.IAdvertisingSetCallback; 47 import android.bluetooth.le.IDistanceMeasurementCallback; 48 import android.bluetooth.le.IPeriodicAdvertisingCallback; 49 import android.bluetooth.le.IScannerCallback; 50 import android.bluetooth.le.PeriodicAdvertisingParameters; 51 import android.bluetooth.le.ScanCallback; 52 import android.bluetooth.le.ScanFilter; 53 import android.bluetooth.le.ScanRecord; 54 import android.bluetooth.le.ScanResult; 55 import android.bluetooth.le.ScanSettings; 56 import android.companion.AssociationInfo; 57 import android.companion.CompanionDeviceManager; 58 import android.content.AttributionSource; 59 import android.content.Intent; 60 import android.content.pm.PackageManager.NameNotFoundException; 61 import android.content.pm.PackageManager.PackageInfoFlags; 62 import android.content.res.Resources; 63 import android.net.MacAddress; 64 import android.os.Binder; 65 import android.os.Build; 66 import android.os.Handler; 67 import android.os.IBinder; 68 import android.os.Message; 69 import android.os.ParcelUuid; 70 import android.os.RemoteException; 71 import android.os.SystemClock; 72 import android.os.UserHandle; 73 import android.os.WorkSource; 74 import android.provider.DeviceConfig; 75 import android.provider.Settings; 76 import android.sysprop.BluetoothProperties; 77 import android.text.format.DateUtils; 78 import android.util.Log; 79 80 import com.android.bluetooth.BluetoothMetricsProto; 81 import com.android.bluetooth.BluetoothStatsLog; 82 import com.android.bluetooth.R; 83 import com.android.bluetooth.Utils; 84 import com.android.bluetooth.btservice.AbstractionLayer; 85 import com.android.bluetooth.btservice.AdapterService; 86 import com.android.bluetooth.btservice.BluetoothAdapterProxy; 87 import com.android.bluetooth.btservice.MetricsLogger; 88 import com.android.bluetooth.btservice.CompanionManager; 89 import com.android.bluetooth.btservice.ProfileService; 90 import com.android.bluetooth.util.NumberUtils; 91 import com.android.internal.annotations.VisibleForTesting; 92 import com.android.modules.utils.SynchronousResultReceiver; 93 94 import libcore.util.HexEncoding; 95 96 import java.util.ArrayDeque; 97 import java.util.ArrayList; 98 import java.util.Arrays; 99 import java.util.Collections; 100 import java.util.HashMap; 101 import java.util.HashSet; 102 import java.util.List; 103 import java.util.Map; 104 import java.util.Set; 105 import java.util.UUID; 106 import java.util.concurrent.TimeUnit; 107 import java.util.function.Predicate; 108 109 /** 110 * Provides Bluetooth Gatt profile, as a service in 111 * the Bluetooth application. 112 * @hide 113 */ 114 public class GattService extends ProfileService { 115 private static final boolean DBG = GattServiceConfig.DBG; 116 private static final boolean VDBG = GattServiceConfig.VDBG; 117 private static final String TAG = GattServiceConfig.TAG_PREFIX + "GattService"; 118 private static final String UUID_SUFFIX = "-0000-1000-8000-00805f9b34fb"; 119 private static final String UUID_ZERO_PAD = "00000000"; 120 121 static final int SCAN_FILTER_ENABLED = 1; 122 static final int SCAN_FILTER_MODIFIED = 2; 123 124 private static final int MAC_ADDRESS_LENGTH = 6; 125 // Batch scan related constants. 126 private static final int TRUNCATED_RESULT_SIZE = 11; 127 private static final int TIME_STAMP_LENGTH = 2; 128 129 private enum MatchOrigin { 130 PSEUDO_ADDRESS, 131 ORIGINAL_ADDRESS 132 } 133 134 private static class MatchResult { 135 private final boolean mMatches; 136 private final MatchOrigin mOrigin; MatchResult(boolean matches, MatchOrigin origin)137 private MatchResult(boolean matches, MatchOrigin origin) { 138 this.mMatches = matches; 139 this.mOrigin = origin; 140 } 141 getMatches()142 public boolean getMatches() { 143 return mMatches; 144 } 145 getMatchOrigin()146 public MatchOrigin getMatchOrigin() { 147 return mOrigin; 148 } 149 } 150 151 /** 152 * The default floor value for LE batch scan report delays greater than 0 153 */ 154 @VisibleForTesting 155 static final long DEFAULT_REPORT_DELAY_FLOOR = 5000; 156 157 // onFoundLost related constants 158 private static final int ADVT_STATE_ONFOUND = 0; 159 private static final int ADVT_STATE_ONLOST = 1; 160 161 private static final int ET_LEGACY_MASK = 0x10; 162 163 private static final UUID HID_SERVICE_UUID = 164 UUID.fromString("00001812-0000-1000-8000-00805F9B34FB"); 165 166 private static final UUID[] HID_UUIDS = { 167 UUID.fromString("00002A4A-0000-1000-8000-00805F9B34FB"), 168 UUID.fromString("00002A4B-0000-1000-8000-00805F9B34FB"), 169 UUID.fromString("00002A4C-0000-1000-8000-00805F9B34FB"), 170 UUID.fromString("00002A4D-0000-1000-8000-00805F9B34FB") 171 }; 172 173 private static final UUID ANDROID_TV_REMOTE_SERVICE_UUID = 174 UUID.fromString("AB5E0001-5A21-4F05-BC7D-AF01F617B664"); 175 176 private static final UUID FIDO_SERVICE_UUID = 177 UUID.fromString("0000FFFD-0000-1000-8000-00805F9B34FB"); // U2F 178 179 private static final UUID[] LE_AUDIO_SERVICE_UUIDS = { 180 UUID.fromString("00001844-0000-1000-8000-00805F9B34FB"), // VCS 181 UUID.fromString("00001845-0000-1000-8000-00805F9B34FB"), // VOCS 182 UUID.fromString("00001843-0000-1000-8000-00805F9B34FB"), // AICS 183 UUID.fromString("00001850-0000-1000-8000-00805F9B34FB"), // PACS 184 UUID.fromString("0000184E-0000-1000-8000-00805F9B34FB"), // ASCS 185 UUID.fromString("0000184F-0000-1000-8000-00805F9B34FB"), // BASS 186 UUID.fromString("00001854-0000-1000-8000-00805F9B34FB"), // HAP 187 UUID.fromString("00001846-0000-1000-8000-00805F9B34FB"), // CSIS 188 }; 189 190 /** 191 * Example raw beacons captured from a Blue Charm BC011 192 */ 193 private static final String[] TEST_MODE_BEACONS = new String[] { 194 "020106", 195 "0201060303AAFE1716AAFE10EE01626C7565636861726D626561636F6E730009168020691E0EFE13551109426C7565436861726D5F313639363835000000", 196 "0201060303AAFE1716AAFE00EE626C7565636861726D31000000000001000009168020691E0EFE13551109426C7565436861726D5F313639363835000000", 197 "0201060303AAFE1116AAFE20000BF017000008874803FB93540916802069080EFE13551109426C7565436861726D5F313639363835000000000000000000", 198 "0201061AFF4C000215426C7565436861726D426561636F6E730EFE1355C509168020691E0EFE13551109426C7565436861726D5F31363936383500000000", 199 }; 200 201 /** 202 * Keep the arguments passed in for the PendingIntent. 203 */ 204 class PendingIntentInfo { 205 public PendingIntent intent; 206 public ScanSettings settings; 207 public List<ScanFilter> filters; 208 public String callingPackage; 209 210 @Override equals(Object other)211 public boolean equals(Object other) { 212 if (!(other instanceof PendingIntentInfo)) { 213 return false; 214 } 215 return intent.equals(((PendingIntentInfo) other).intent); 216 } 217 } 218 219 private final PendingIntent.CancelListener mScanIntentCancelListener = 220 new PendingIntent.CancelListener(){ 221 public void onCanceled(PendingIntent intent) { 222 Log.d(TAG, "scanning PendingIntent canceled"); 223 stopScan(intent, getAttributionSource()); 224 } 225 }; 226 227 /** 228 * List of our registered scanners. 229 */ 230 class ScannerMap extends ContextMap<IScannerCallback, PendingIntentInfo> {} 231 232 ScannerMap mScannerMap = new ScannerMap(); 233 234 /** 235 * List of our registered advertisers. 236 */ 237 static class AdvertiserMap extends ContextMap<IAdvertisingSetCallback, Void> {} 238 239 private AdvertiserMap mAdvertiserMap = new AdvertiserMap(); 240 241 /** 242 * List of our registered clients. 243 */ 244 class ClientMap extends ContextMap<IBluetoothGattCallback, Void> {} 245 246 ClientMap mClientMap = new ClientMap(); 247 248 /** 249 * List of our registered server apps. 250 */ 251 class ServerMap extends ContextMap<IBluetoothGattServerCallback, Void> {} 252 253 ServerMap mServerMap = new ServerMap(); 254 255 /** 256 * Server handle map. 257 */ 258 HandleMap mHandleMap = new HandleMap(); 259 private List<UUID> mAdvertisingServiceUuids = new ArrayList<UUID>(); 260 261 private int mMaxScanFilters; 262 263 private static final int NUM_SCAN_EVENTS_KEPT = 20; 264 265 /** 266 * Internal list of scan events to use with the proto 267 */ 268 private final ArrayDeque<BluetoothMetricsProto.ScanEvent> mScanEvents = 269 new ArrayDeque<>(NUM_SCAN_EVENTS_KEPT); 270 271 /** 272 * Set of restricted (which require a BLUETOOTH_PRIVILEGED permission) handles per connectionId. 273 */ 274 private final Map<Integer, Set<Integer>> mRestrictedHandles = new HashMap<>(); 275 276 /** 277 * HashMap used to synchronize writeCharacteristic calls mapping remote device address to 278 * available permit (connectId or -1). 279 */ 280 private final HashMap<String, Integer> mPermits = new HashMap<>(); 281 282 private AdapterService mAdapterService; 283 private BluetoothAdapterProxy mBluetoothAdapterProxy; 284 @VisibleForTesting 285 AdvertiseManager mAdvertiseManager; 286 @VisibleForTesting 287 PeriodicScanManager mPeriodicScanManager; 288 @VisibleForTesting 289 DistanceMeasurementManager mDistanceMeasurementManager; 290 @VisibleForTesting 291 ScanManager mScanManager; 292 private AppOpsManager mAppOps; 293 private CompanionDeviceManager mCompanionManager; 294 private String mExposureNotificationPackage; 295 private Handler mTestModeHandler; 296 private final Object mTestModeLock = new Object(); 297 isEnabled()298 public static boolean isEnabled() { 299 return BluetoothProperties.isProfileGattEnabled().orElse(true); 300 } 301 302 /** 303 */ 304 private final Predicate<ScanResult> mLocationDenylistPredicate = (scanResult) -> { 305 final MacAddress parsedAddress = MacAddress 306 .fromString(scanResult.getDevice().getAddress()); 307 if (mAdapterService.getLocationDenylistMac().test(parsedAddress.toByteArray())) { 308 Log.v(TAG, "Skipping device matching denylist: " + scanResult.getDevice()); 309 return true; 310 } 311 final ScanRecord scanRecord = scanResult.getScanRecord(); 312 if (scanRecord.matchesAnyField(mAdapterService.getLocationDenylistAdvertisingData())) { 313 Log.v(TAG, "Skipping data matching denylist: " + scanRecord); 314 return true; 315 } 316 return false; 317 }; 318 319 private static GattService sGattService; 320 321 /** 322 * Reliable write queue 323 */ 324 @VisibleForTesting 325 Set<String> mReliableQueue = new HashSet<String>(); 326 327 private GattNativeInterface mNativeInterface; 328 329 @Override initBinder()330 protected IProfileServiceBinder initBinder() { 331 return new BluetoothGattBinder(this); 332 } 333 334 @Override start()335 protected boolean start() { 336 if (DBG) { 337 Log.d(TAG, "start()"); 338 } 339 mExposureNotificationPackage = getString(R.string.exposure_notification_package); 340 Settings.Global.putInt( 341 getContentResolver(), "bluetooth_sanitized_exposure_notification_supported", 1); 342 343 mNativeInterface = GattObjectsFactory.getInstance().getNativeInterface(); 344 mNativeInterface.init(this); 345 mAdapterService = AdapterService.getAdapterService(); 346 mBluetoothAdapterProxy = BluetoothAdapterProxy.getInstance(); 347 mCompanionManager = getSystemService(CompanionDeviceManager.class); 348 mAppOps = getSystemService(AppOpsManager.class); 349 mAdvertiseManager = new AdvertiseManager(this, mAdapterService, mAdvertiserMap); 350 mAdvertiseManager.start(); 351 352 mScanManager = new ScanManager(this, mAdapterService, mBluetoothAdapterProxy); 353 mScanManager.start(); 354 355 mPeriodicScanManager = new PeriodicScanManager(mAdapterService); 356 mPeriodicScanManager.start(); 357 358 mDistanceMeasurementManager = new DistanceMeasurementManager(mAdapterService); 359 mDistanceMeasurementManager.start(); 360 361 setGattService(this); 362 return true; 363 } 364 365 @Override stop()366 protected boolean stop() { 367 if (DBG) { 368 Log.d(TAG, "stop()"); 369 } 370 setGattService(null); 371 mScannerMap.clear(); 372 mAdvertiserMap.clear(); 373 mClientMap.clear(); 374 mServerMap.clear(); 375 mHandleMap.clear(); 376 mReliableQueue.clear(); 377 cleanup(); 378 379 return true; 380 } 381 382 @Override cleanup()383 protected void cleanup() { 384 if (DBG) { 385 Log.d(TAG, "cleanup()"); 386 } 387 if (mNativeInterface != null) { 388 mNativeInterface.cleanup(); 389 mNativeInterface = null; 390 } 391 if (mAdvertiseManager != null) { 392 mAdvertiseManager.cleanup(); 393 } 394 if (mScanManager != null) { 395 mScanManager.cleanup(); 396 } 397 if (mPeriodicScanManager != null) { 398 mPeriodicScanManager.cleanup(); 399 } 400 if (mDistanceMeasurementManager != null) { 401 mDistanceMeasurementManager.cleanup(); 402 } 403 } 404 405 // While test mode is enabled, pretend as if the underlying stack 406 // discovered a specific set of well-known beacons every second 407 @Override setTestModeEnabled(boolean enableTestMode)408 protected void setTestModeEnabled(boolean enableTestMode) { 409 synchronized (mTestModeLock) { 410 if (mTestModeHandler == null) { 411 mTestModeHandler = new Handler(getMainLooper()) { 412 public void handleMessage(Message msg) { 413 synchronized (mTestModeLock) { 414 if (!GattService.this.isTestModeEnabled()) { 415 return; 416 } 417 for (String test : TEST_MODE_BEACONS) { 418 onScanResultInternal(0x1b, 0x1, "DD:34:02:05:5C:4D", 1, 0, 0xff, 419 127, -54, 0x0, HexEncoding.decode(test), 420 "DD:34:02:05:5C:4E"); 421 } 422 sendEmptyMessageDelayed(0, DateUtils.SECOND_IN_MILLIS); 423 } 424 } 425 }; 426 } 427 if (enableTestMode && !isTestModeEnabled()) { 428 super.setTestModeEnabled(true); 429 mTestModeHandler.removeMessages(0); 430 mTestModeHandler.sendEmptyMessageDelayed(0, DateUtils.SECOND_IN_MILLIS); 431 } else if (!enableTestMode && isTestModeEnabled()) { 432 super.setTestModeEnabled(false); 433 mTestModeHandler.removeMessages(0); 434 mTestModeHandler.sendEmptyMessage(0); 435 } 436 } 437 } 438 439 /** 440 * Get the current instance of {@link GattService} 441 * 442 * @return current instance of {@link GattService} 443 */ 444 @VisibleForTesting getGattService()445 public static synchronized GattService getGattService() { 446 if (sGattService == null) { 447 Log.w(TAG, "getGattService(): service is null"); 448 return null; 449 } 450 if (!sGattService.isAvailable()) { 451 Log.w(TAG, "getGattService(): service is not available"); 452 return null; 453 } 454 return sGattService; 455 } 456 457 @VisibleForTesting getScanManager()458 ScanManager getScanManager() { 459 if (mScanManager == null) { 460 Log.w(TAG, "getScanManager(): scan manager is null"); 461 return null; 462 } 463 return mScanManager; 464 } 465 setGattService(GattService instance)466 private static synchronized void setGattService(GattService instance) { 467 if (DBG) { 468 Log.d(TAG, "setGattService(): set to: " + instance); 469 } 470 sGattService = instance; 471 } 472 473 // Suppressed because we are conditionally enforcing 474 @SuppressLint("AndroidFrameworkRequiresPermission") permissionCheck(UUID characteristicUuid)475 private void permissionCheck(UUID characteristicUuid) { 476 if (!isHidCharUuid(characteristicUuid)) { 477 return; 478 } 479 enforceBluetoothPrivilegedPermission(this); 480 } 481 482 // Suppressed because we are conditionally enforcing 483 @SuppressLint("AndroidFrameworkRequiresPermission") permissionCheck(int connId, int handle)484 private void permissionCheck(int connId, int handle) { 485 if (!isHandleRestricted(connId, handle)) { 486 return; 487 } 488 enforceBluetoothPrivilegedPermission(this); 489 } 490 491 // Suppressed because we are conditionally enforcing 492 @SuppressLint("AndroidFrameworkRequiresPermission") permissionCheck(ClientMap.App app, int connId, int handle)493 private void permissionCheck(ClientMap.App app, int connId, int handle) { 494 if (!isHandleRestricted(connId, handle) || app.hasBluetoothPrivilegedPermission) { 495 return; 496 } 497 enforceBluetoothPrivilegedPermission(this); 498 app.hasBluetoothPrivilegedPermission = true; 499 } 500 isHandleRestricted(int connId, int handle)501 private boolean isHandleRestricted(int connId, int handle) { 502 Set<Integer> restrictedHandles = mRestrictedHandles.get(connId); 503 return restrictedHandles != null && restrictedHandles.contains(handle); 504 } 505 506 @Override onStartCommand(Intent intent, int flags, int startId)507 public int onStartCommand(Intent intent, int flags, int startId) { 508 if (GattDebugUtils.handleDebugAction(this, intent)) { 509 return Service.START_NOT_STICKY; 510 } 511 return super.onStartCommand(intent, flags, startId); 512 } 513 514 /** 515 * DeathReceipient handlers used to unregister applications that 516 * disconnect ungracefully (ie. crash or forced close). 517 */ 518 519 class ScannerDeathRecipient implements IBinder.DeathRecipient { 520 int mScannerId; 521 ScannerDeathRecipient(int scannerId)522 ScannerDeathRecipient(int scannerId) { 523 mScannerId = scannerId; 524 } 525 526 @Override binderDied()527 public void binderDied() { 528 if (DBG) { 529 Log.d(TAG, "Binder is dead - unregistering scanner (" + mScannerId + ")!"); 530 } 531 532 ScanClient client = getScanClient(mScannerId); 533 if (client != null) { 534 client.appDied = true; 535 stopScan(client.scannerId, getAttributionSource()); 536 } 537 } 538 getScanClient(int clientIf)539 private ScanClient getScanClient(int clientIf) { 540 for (ScanClient client : mScanManager.getRegularScanQueue()) { 541 if (client.scannerId == clientIf) { 542 return client; 543 } 544 } 545 for (ScanClient client : mScanManager.getBatchScanQueue()) { 546 if (client.scannerId == clientIf) { 547 return client; 548 } 549 } 550 return null; 551 } 552 } 553 554 class ServerDeathRecipient implements IBinder.DeathRecipient { 555 int mAppIf; 556 ServerDeathRecipient(int appIf)557 ServerDeathRecipient(int appIf) { 558 mAppIf = appIf; 559 } 560 561 @Override binderDied()562 public void binderDied() { 563 if (DBG) { 564 Log.d(TAG, "Binder is dead - unregistering server (" + mAppIf + ")!"); 565 } 566 unregisterServer(mAppIf, getAttributionSource()); 567 } 568 } 569 570 class ClientDeathRecipient implements IBinder.DeathRecipient { 571 int mAppIf; 572 ClientDeathRecipient(int appIf)573 ClientDeathRecipient(int appIf) { 574 mAppIf = appIf; 575 } 576 577 @Override binderDied()578 public void binderDied() { 579 if (DBG) { 580 Log.d(TAG, "Binder is dead - unregistering client (" + mAppIf + ")!"); 581 } 582 unregisterClient(mAppIf, getAttributionSource()); 583 } 584 } 585 586 /** 587 * Handlers for incoming service calls 588 */ 589 @VisibleForTesting 590 static class BluetoothGattBinder extends IBluetoothGatt.Stub 591 implements IProfileServiceBinder { 592 private GattService mService; 593 BluetoothGattBinder(GattService svc)594 BluetoothGattBinder(GattService svc) { 595 mService = svc; 596 } 597 598 @Override cleanup()599 public void cleanup() { 600 mService = null; 601 } 602 getService()603 private GattService getService() { 604 if (mService != null && mService.isAvailable()) { 605 return mService; 606 } 607 Log.e(TAG, "getService() - Service requested, but not available!"); 608 return null; 609 } 610 611 @Override getDevicesMatchingConnectionStates(int[] states, AttributionSource attributionSource, SynchronousResultReceiver receiver)612 public void getDevicesMatchingConnectionStates(int[] states, 613 AttributionSource attributionSource, SynchronousResultReceiver receiver) { 614 try { 615 receiver.send(getDevicesMatchingConnectionStates(states, attributionSource)); 616 } catch (RuntimeException e) { 617 receiver.propagateException(e); 618 } 619 } getDevicesMatchingConnectionStates(int[] states, AttributionSource attributionSource)620 private List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states, 621 AttributionSource attributionSource) { 622 GattService service = getService(); 623 if (service == null) { 624 return new ArrayList<BluetoothDevice>(); 625 } 626 return service.getDevicesMatchingConnectionStates(states, attributionSource); 627 } 628 629 @Override registerClient(ParcelUuid uuid, IBluetoothGattCallback callback, boolean eattSupport, AttributionSource attributionSource, SynchronousResultReceiver receiver)630 public void registerClient(ParcelUuid uuid, IBluetoothGattCallback callback, 631 boolean eattSupport, AttributionSource attributionSource, 632 SynchronousResultReceiver receiver) { 633 try { 634 registerClient(uuid, callback, eattSupport, attributionSource); 635 receiver.send(null); 636 } catch (RuntimeException e) { 637 receiver.propagateException(e); 638 } 639 } registerClient(ParcelUuid uuid, IBluetoothGattCallback callback, boolean eatt_support, AttributionSource attributionSource)640 private void registerClient(ParcelUuid uuid, IBluetoothGattCallback callback, 641 boolean eatt_support, AttributionSource attributionSource) { 642 GattService service = getService(); 643 if (service == null) { 644 return; 645 } 646 service.registerClient(uuid.getUuid(), callback, eatt_support, attributionSource); 647 } 648 649 @Override unregisterClient(int clientIf, AttributionSource attributionSource, SynchronousResultReceiver receiver)650 public void unregisterClient(int clientIf, AttributionSource attributionSource, 651 SynchronousResultReceiver receiver) { 652 try { 653 unregisterClient(clientIf, attributionSource); 654 receiver.send(null); 655 } catch (RuntimeException e) { 656 receiver.propagateException(e); 657 } 658 } unregisterClient(int clientIf, AttributionSource attributionSource)659 private void unregisterClient(int clientIf, AttributionSource attributionSource) { 660 GattService service = getService(); 661 if (service == null) { 662 return; 663 } 664 service.unregisterClient(clientIf, attributionSource); 665 } 666 667 @Override registerScanner(IScannerCallback callback, WorkSource workSource, AttributionSource attributionSource, SynchronousResultReceiver receiver)668 public void registerScanner(IScannerCallback callback, WorkSource workSource, 669 AttributionSource attributionSource, SynchronousResultReceiver receiver) 670 throws RemoteException { 671 try { 672 registerScanner(callback, workSource, attributionSource); 673 receiver.send(null); 674 } catch (RuntimeException e) { 675 receiver.propagateException(e); 676 } 677 } registerScanner(IScannerCallback callback, WorkSource workSource, AttributionSource attributionSource)678 private void registerScanner(IScannerCallback callback, WorkSource workSource, 679 AttributionSource attributionSource) throws RemoteException { 680 GattService service = getService(); 681 if (service == null) { 682 return; 683 } 684 service.registerScanner(callback, workSource, attributionSource); 685 } 686 687 @Override unregisterScanner(int scannerId, AttributionSource attributionSource, SynchronousResultReceiver receiver)688 public void unregisterScanner(int scannerId, AttributionSource attributionSource, 689 SynchronousResultReceiver receiver) { 690 try { 691 unregisterScanner(scannerId, attributionSource); 692 receiver.send(null); 693 } catch (RuntimeException e) { 694 receiver.propagateException(e); 695 } 696 } unregisterScanner(int scannerId, AttributionSource attributionSource)697 private void unregisterScanner(int scannerId, AttributionSource attributionSource) { 698 GattService service = getService(); 699 if (service == null) { 700 return; 701 } 702 service.unregisterScanner(scannerId, attributionSource); 703 } 704 705 @Override startScan(int scannerId, ScanSettings settings, List<ScanFilter> filters, AttributionSource attributionSource, SynchronousResultReceiver receiver)706 public void startScan(int scannerId, ScanSettings settings, List<ScanFilter> filters, 707 AttributionSource attributionSource, SynchronousResultReceiver receiver) { 708 try { 709 startScan(scannerId, settings, filters, 710 attributionSource); 711 receiver.send(null); 712 } catch (RuntimeException e) { 713 receiver.propagateException(e); 714 } 715 } startScan(int scannerId, ScanSettings settings, List<ScanFilter> filters, AttributionSource attributionSource)716 private void startScan(int scannerId, ScanSettings settings, List<ScanFilter> filters, 717 AttributionSource attributionSource) { 718 GattService service = getService(); 719 if (service == null) { 720 return; 721 } 722 service.startScan(scannerId, settings, filters, attributionSource); 723 } 724 725 @Override startScanForIntent(PendingIntent intent, ScanSettings settings, List<ScanFilter> filters, AttributionSource attributionSource, SynchronousResultReceiver receiver)726 public void startScanForIntent(PendingIntent intent, ScanSettings settings, 727 List<ScanFilter> filters, AttributionSource attributionSource, 728 SynchronousResultReceiver receiver) 729 throws RemoteException { 730 try { 731 startScanForIntent(intent, settings, 732 filters, attributionSource); 733 receiver.send(null); 734 } catch (RuntimeException e) { 735 receiver.propagateException(e); 736 } 737 } startScanForIntent(PendingIntent intent, ScanSettings settings, List<ScanFilter> filters, AttributionSource attributionSource)738 private void startScanForIntent(PendingIntent intent, ScanSettings settings, 739 List<ScanFilter> filters, AttributionSource attributionSource) 740 throws RemoteException { 741 GattService service = getService(); 742 if (service == null) { 743 return; 744 } 745 service.registerPiAndStartScan(intent, settings, filters, attributionSource); 746 } 747 748 @Override stopScanForIntent(PendingIntent intent, AttributionSource attributionSource, SynchronousResultReceiver receiver)749 public void stopScanForIntent(PendingIntent intent, AttributionSource attributionSource, 750 SynchronousResultReceiver receiver) throws RemoteException { 751 try { 752 stopScanForIntent(intent, attributionSource); 753 receiver.send(null); 754 } catch (RuntimeException e) { 755 receiver.propagateException(e); 756 } 757 } stopScanForIntent(PendingIntent intent, AttributionSource attributionSource)758 private void stopScanForIntent(PendingIntent intent, AttributionSource attributionSource) 759 throws RemoteException { 760 GattService service = getService(); 761 if (service == null) { 762 return; 763 } 764 service.stopScan(intent, attributionSource); 765 } 766 767 @Override stopScan(int scannerId, AttributionSource attributionSource, SynchronousResultReceiver receiver)768 public void stopScan(int scannerId, AttributionSource attributionSource, 769 SynchronousResultReceiver receiver) { 770 try { 771 stopScan(scannerId, attributionSource); 772 receiver.send(null); 773 } catch (RuntimeException e) { 774 receiver.propagateException(e); 775 } 776 } stopScan(int scannerId, AttributionSource attributionSource)777 private void stopScan(int scannerId, AttributionSource attributionSource) { 778 GattService service = getService(); 779 if (service == null) { 780 return; 781 } 782 service.stopScan(scannerId, attributionSource); 783 } 784 785 @Override flushPendingBatchResults(int scannerId, AttributionSource attributionSource, SynchronousResultReceiver receiver)786 public void flushPendingBatchResults(int scannerId, AttributionSource attributionSource, 787 SynchronousResultReceiver receiver) { 788 try { 789 flushPendingBatchResults(scannerId, attributionSource); 790 receiver.send(null); 791 } catch (RuntimeException e) { 792 receiver.propagateException(e); 793 } 794 } flushPendingBatchResults(int scannerId, AttributionSource attributionSource)795 private void flushPendingBatchResults(int scannerId, AttributionSource attributionSource) { 796 GattService service = getService(); 797 if (service == null) { 798 return; 799 } 800 service.flushPendingBatchResults(scannerId, attributionSource); 801 } 802 803 @Override clientConnect(int clientIf, String address, int addressType, boolean isDirect, int transport, boolean opportunistic, int phy, AttributionSource attributionSource, SynchronousResultReceiver receiver)804 public void clientConnect(int clientIf, String address, int addressType, boolean isDirect, 805 int transport, boolean opportunistic, int phy, AttributionSource attributionSource, 806 SynchronousResultReceiver receiver) { 807 try { 808 clientConnect(clientIf, address, addressType, isDirect, transport, opportunistic, 809 phy, attributionSource); 810 receiver.send(null); 811 } catch (RuntimeException e) { 812 receiver.propagateException(e); 813 } 814 } clientConnect(int clientIf, String address, int addressType, boolean isDirect, int transport, boolean opportunistic, int phy, AttributionSource attributionSource)815 private void clientConnect(int clientIf, String address, int addressType, boolean isDirect, 816 int transport, boolean opportunistic, int phy, 817 AttributionSource attributionSource) { 818 GattService service = getService(); 819 if (service == null) { 820 return; 821 } 822 service.clientConnect(clientIf, address, addressType, isDirect, transport, 823 opportunistic, phy, attributionSource); 824 } 825 826 @Override clientDisconnect(int clientIf, String address, AttributionSource attributionSource, SynchronousResultReceiver receiver)827 public void clientDisconnect(int clientIf, String address, 828 AttributionSource attributionSource, SynchronousResultReceiver receiver) { 829 try { 830 clientDisconnect(clientIf, address, attributionSource); 831 receiver.send(null); 832 } catch (RuntimeException e) { 833 receiver.propagateException(e); 834 } 835 } clientDisconnect(int clientIf, String address, AttributionSource attributionSource)836 private void clientDisconnect(int clientIf, String address, 837 AttributionSource attributionSource) { 838 GattService service = getService(); 839 if (service == null) { 840 return; 841 } 842 service.clientDisconnect(clientIf, address, attributionSource); 843 } 844 845 @Override clientSetPreferredPhy(int clientIf, String address, int txPhy, int rxPhy, int phyOptions, AttributionSource attributionSource, SynchronousResultReceiver receiver)846 public void clientSetPreferredPhy(int clientIf, String address, int txPhy, int rxPhy, 847 int phyOptions, AttributionSource attributionSource, 848 SynchronousResultReceiver receiver) { 849 try { 850 clientSetPreferredPhy(clientIf, address, txPhy, rxPhy, phyOptions, 851 attributionSource); 852 receiver.send(null); 853 } catch (RuntimeException e) { 854 receiver.propagateException(e); 855 } 856 } clientSetPreferredPhy(int clientIf, String address, int txPhy, int rxPhy, int phyOptions, AttributionSource attributionSource)857 private void clientSetPreferredPhy(int clientIf, String address, int txPhy, int rxPhy, 858 int phyOptions, AttributionSource attributionSource) { 859 GattService service = getService(); 860 if (service == null) { 861 return; 862 } 863 service.clientSetPreferredPhy(clientIf, address, txPhy, rxPhy, phyOptions, 864 attributionSource); 865 } 866 867 @Override clientReadPhy(int clientIf, String address, AttributionSource attributionSource, SynchronousResultReceiver receiver)868 public void clientReadPhy(int clientIf, String address, 869 AttributionSource attributionSource, SynchronousResultReceiver receiver) { 870 try { 871 clientReadPhy(clientIf, address, attributionSource); 872 receiver.send(null); 873 } catch (RuntimeException e) { 874 receiver.propagateException(e); 875 } 876 } clientReadPhy(int clientIf, String address, AttributionSource attributionSource)877 private void clientReadPhy(int clientIf, String address, 878 AttributionSource attributionSource) { 879 GattService service = getService(); 880 if (service == null) { 881 return; 882 } 883 service.clientReadPhy(clientIf, address, attributionSource); 884 } 885 886 @Override refreshDevice(int clientIf, String address, AttributionSource attributionSource, SynchronousResultReceiver receiver)887 public void refreshDevice(int clientIf, String address, 888 AttributionSource attributionSource, SynchronousResultReceiver receiver) { 889 try { 890 refreshDevice(clientIf, address, attributionSource); 891 receiver.send(null); 892 } catch (RuntimeException e) { 893 receiver.propagateException(e); 894 } 895 } refreshDevice(int clientIf, String address, AttributionSource attributionSource)896 private void refreshDevice(int clientIf, String address, 897 AttributionSource attributionSource) { 898 GattService service = getService(); 899 if (service == null) { 900 return; 901 } 902 service.refreshDevice(clientIf, address, attributionSource); 903 } 904 905 @Override discoverServices(int clientIf, String address, AttributionSource attributionSource, SynchronousResultReceiver receiver)906 public void discoverServices(int clientIf, String address, 907 AttributionSource attributionSource, SynchronousResultReceiver receiver) { 908 try { 909 discoverServices(clientIf, address, attributionSource); 910 receiver.send(null); 911 } catch (RuntimeException e) { 912 receiver.propagateException(e); 913 } 914 } discoverServices(int clientIf, String address, AttributionSource attributionSource)915 private void discoverServices(int clientIf, String address, 916 AttributionSource attributionSource) { 917 GattService service = getService(); 918 if (service == null) { 919 return; 920 } 921 service.discoverServices(clientIf, address, attributionSource); 922 } 923 924 @Override discoverServiceByUuid(int clientIf, String address, ParcelUuid uuid, AttributionSource attributionSource, SynchronousResultReceiver receiver)925 public void discoverServiceByUuid(int clientIf, String address, ParcelUuid uuid, 926 AttributionSource attributionSource, SynchronousResultReceiver receiver) { 927 try { 928 discoverServiceByUuid(clientIf, address, uuid, attributionSource); 929 receiver.send(null); 930 } catch (RuntimeException e) { 931 receiver.propagateException(e); 932 } 933 } discoverServiceByUuid(int clientIf, String address, ParcelUuid uuid, AttributionSource attributionSource)934 private void discoverServiceByUuid(int clientIf, String address, ParcelUuid uuid, 935 AttributionSource attributionSource) { 936 GattService service = getService(); 937 if (service == null) { 938 return; 939 } 940 service.discoverServiceByUuid(clientIf, address, uuid.getUuid(), attributionSource); 941 } 942 943 @Override readCharacteristic(int clientIf, String address, int handle, int authReq, AttributionSource attributionSource, SynchronousResultReceiver receiver)944 public void readCharacteristic(int clientIf, String address, int handle, int authReq, 945 AttributionSource attributionSource, SynchronousResultReceiver receiver) { 946 try { 947 readCharacteristic(clientIf, address, handle, authReq, attributionSource); 948 receiver.send(null); 949 } catch (RuntimeException e) { 950 receiver.propagateException(e); 951 } 952 } readCharacteristic(int clientIf, String address, int handle, int authReq, AttributionSource attributionSource)953 private void readCharacteristic(int clientIf, String address, int handle, int authReq, 954 AttributionSource attributionSource) { 955 GattService service = getService(); 956 if (service == null) { 957 return; 958 } 959 service.readCharacteristic(clientIf, address, handle, authReq, attributionSource); 960 } 961 962 @Override readUsingCharacteristicUuid(int clientIf, String address, ParcelUuid uuid, int startHandle, int endHandle, int authReq, AttributionSource attributionSource, SynchronousResultReceiver receiver)963 public void readUsingCharacteristicUuid(int clientIf, String address, ParcelUuid uuid, 964 int startHandle, int endHandle, int authReq, AttributionSource attributionSource, 965 SynchronousResultReceiver receiver) { 966 try { 967 readUsingCharacteristicUuid(clientIf, address, uuid, startHandle, endHandle, 968 authReq, attributionSource); 969 receiver.send(null); 970 } catch (RuntimeException e) { 971 receiver.propagateException(e); 972 } 973 } readUsingCharacteristicUuid(int clientIf, String address, ParcelUuid uuid, int startHandle, int endHandle, int authReq, AttributionSource attributionSource)974 private void readUsingCharacteristicUuid(int clientIf, String address, ParcelUuid uuid, 975 int startHandle, int endHandle, int authReq, AttributionSource attributionSource) { 976 GattService service = getService(); 977 if (service == null) { 978 return; 979 } 980 service.readUsingCharacteristicUuid(clientIf, address, uuid.getUuid(), startHandle, 981 endHandle, authReq, attributionSource); 982 } 983 984 @Override writeCharacteristic(int clientIf, String address, int handle, int writeType, int authReq, byte[] value, AttributionSource attributionSource, SynchronousResultReceiver receiver)985 public void writeCharacteristic(int clientIf, String address, int handle, int writeType, 986 int authReq, byte[] value, AttributionSource attributionSource, 987 SynchronousResultReceiver receiver) { 988 try { 989 receiver.send(writeCharacteristic(clientIf, address, handle, writeType, authReq, 990 value, attributionSource)); 991 } catch (RuntimeException e) { 992 receiver.propagateException(e); 993 } 994 } writeCharacteristic(int clientIf, String address, int handle, int writeType, int authReq, byte[] value, AttributionSource attributionSource)995 private int writeCharacteristic(int clientIf, String address, int handle, int writeType, 996 int authReq, byte[] value, AttributionSource attributionSource) { 997 GattService service = getService(); 998 if (service == null) { 999 return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND; 1000 } 1001 return service.writeCharacteristic(clientIf, address, handle, writeType, authReq, value, 1002 attributionSource); 1003 } 1004 1005 @Override readDescriptor(int clientIf, String address, int handle, int authReq, AttributionSource attributionSource, SynchronousResultReceiver receiver)1006 public void readDescriptor(int clientIf, String address, int handle, int authReq, 1007 AttributionSource attributionSource, SynchronousResultReceiver receiver) { 1008 try { 1009 readDescriptor(clientIf, address, handle, authReq, attributionSource); 1010 receiver.send(null); 1011 } catch (RuntimeException e) { 1012 receiver.propagateException(e); 1013 } 1014 } readDescriptor(int clientIf, String address, int handle, int authReq, AttributionSource attributionSource)1015 private void readDescriptor(int clientIf, String address, int handle, int authReq, 1016 AttributionSource attributionSource) { 1017 GattService service = getService(); 1018 if (service == null) { 1019 return; 1020 } 1021 service.readDescriptor(clientIf, address, handle, authReq, attributionSource); 1022 } 1023 1024 @Override writeDescriptor(int clientIf, String address, int handle, int authReq, byte[] value, AttributionSource attributionSource, SynchronousResultReceiver receiver)1025 public void writeDescriptor(int clientIf, String address, int handle, int authReq, 1026 byte[] value, AttributionSource attributionSource, 1027 SynchronousResultReceiver receiver) { 1028 try { 1029 receiver.send(writeDescriptor(clientIf, address, handle, authReq, value, 1030 attributionSource)); 1031 } catch (RuntimeException e) { 1032 receiver.propagateException(e); 1033 } 1034 } writeDescriptor(int clientIf, String address, int handle, int authReq, byte[] value, AttributionSource attributionSource)1035 private int writeDescriptor(int clientIf, String address, int handle, int authReq, 1036 byte[] value, AttributionSource attributionSource) { 1037 GattService service = getService(); 1038 if (service == null) { 1039 return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND; 1040 } 1041 return service.writeDescriptor(clientIf, address, handle, authReq, value, 1042 attributionSource); 1043 } 1044 1045 @Override beginReliableWrite(int clientIf, String address, AttributionSource attributionSource, SynchronousResultReceiver receiver)1046 public void beginReliableWrite(int clientIf, String address, 1047 AttributionSource attributionSource, SynchronousResultReceiver receiver) { 1048 try { 1049 beginReliableWrite(clientIf, address, attributionSource); 1050 receiver.send(null); 1051 } catch (RuntimeException e) { 1052 receiver.propagateException(e); 1053 } 1054 } beginReliableWrite(int clientIf, String address, AttributionSource attributionSource)1055 private void beginReliableWrite(int clientIf, String address, 1056 AttributionSource attributionSource) { 1057 GattService service = getService(); 1058 if (service == null) { 1059 return; 1060 } 1061 service.beginReliableWrite(clientIf, address, attributionSource); 1062 } 1063 1064 @Override endReliableWrite(int clientIf, String address, boolean execute, AttributionSource attributionSource, SynchronousResultReceiver receiver)1065 public void endReliableWrite(int clientIf, String address, boolean execute, 1066 AttributionSource attributionSource, SynchronousResultReceiver receiver) { 1067 try { 1068 endReliableWrite(clientIf, address, execute, attributionSource); 1069 receiver.send(null); 1070 } catch (RuntimeException e) { 1071 receiver.propagateException(e); 1072 } 1073 } endReliableWrite(int clientIf, String address, boolean execute, AttributionSource attributionSource)1074 private void endReliableWrite(int clientIf, String address, boolean execute, 1075 AttributionSource attributionSource) { 1076 GattService service = getService(); 1077 if (service == null) { 1078 return; 1079 } 1080 service.endReliableWrite(clientIf, address, execute, attributionSource); 1081 } 1082 1083 @Override registerForNotification(int clientIf, String address, int handle, boolean enable, AttributionSource attributionSource, SynchronousResultReceiver receiver)1084 public void registerForNotification(int clientIf, String address, int handle, 1085 boolean enable, AttributionSource attributionSource, 1086 SynchronousResultReceiver receiver) { 1087 try { 1088 registerForNotification(clientIf, address, handle, enable, attributionSource); 1089 receiver.send(null); 1090 } catch (RuntimeException e) { 1091 receiver.propagateException(e); 1092 } 1093 } registerForNotification(int clientIf, String address, int handle, boolean enable, AttributionSource attributionSource)1094 private void registerForNotification(int clientIf, String address, int handle, 1095 boolean enable, AttributionSource attributionSource) { 1096 GattService service = getService(); 1097 if (service == null) { 1098 return; 1099 } 1100 service.registerForNotification(clientIf, address, handle, enable, attributionSource); 1101 } 1102 1103 @Override readRemoteRssi(int clientIf, String address, AttributionSource attributionSource, SynchronousResultReceiver receiver)1104 public void readRemoteRssi(int clientIf, String address, 1105 AttributionSource attributionSource, SynchronousResultReceiver receiver) { 1106 try { 1107 readRemoteRssi(clientIf, address, attributionSource); 1108 receiver.send(null); 1109 } catch (RuntimeException e) { 1110 receiver.propagateException(e); 1111 } 1112 } readRemoteRssi(int clientIf, String address, AttributionSource attributionSource)1113 private void readRemoteRssi(int clientIf, String address, 1114 AttributionSource attributionSource) { 1115 GattService service = getService(); 1116 if (service == null) { 1117 return; 1118 } 1119 service.readRemoteRssi(clientIf, address, attributionSource); 1120 } 1121 1122 @Override configureMTU(int clientIf, String address, int mtu, AttributionSource attributionSource, SynchronousResultReceiver receiver)1123 public void configureMTU(int clientIf, String address, int mtu, 1124 AttributionSource attributionSource, SynchronousResultReceiver receiver) { 1125 try { 1126 configureMTU(clientIf, address, mtu, attributionSource); 1127 receiver.send(null); 1128 } catch (RuntimeException e) { 1129 receiver.propagateException(e); 1130 } 1131 } configureMTU(int clientIf, String address, int mtu, AttributionSource attributionSource)1132 private void configureMTU(int clientIf, String address, int mtu, 1133 AttributionSource attributionSource) { 1134 GattService service = getService(); 1135 if (service == null) { 1136 return; 1137 } 1138 service.configureMTU(clientIf, address, mtu, attributionSource); 1139 } 1140 1141 @Override connectionParameterUpdate(int clientIf, String address, int connectionPriority, AttributionSource attributionSource, SynchronousResultReceiver receiver)1142 public void connectionParameterUpdate(int clientIf, String address, 1143 int connectionPriority, AttributionSource attributionSource, 1144 SynchronousResultReceiver receiver) { 1145 try { 1146 connectionParameterUpdate(clientIf, address, connectionPriority, attributionSource); 1147 receiver.send(null); 1148 } catch (RuntimeException e) { 1149 receiver.propagateException(e); 1150 } 1151 } connectionParameterUpdate(int clientIf, String address, int connectionPriority, AttributionSource attributionSource)1152 private void connectionParameterUpdate(int clientIf, String address, 1153 int connectionPriority, AttributionSource attributionSource) { 1154 GattService service = getService(); 1155 if (service == null) { 1156 return; 1157 } 1158 service.connectionParameterUpdate( 1159 clientIf, address, connectionPriority, attributionSource); 1160 } 1161 1162 @Override leConnectionUpdate(int clientIf, String address, int minConnectionInterval, int maxConnectionInterval, int peripheralLatency, int supervisionTimeout, int minConnectionEventLen, int maxConnectionEventLen, AttributionSource attributionSource, SynchronousResultReceiver receiver)1163 public void leConnectionUpdate(int clientIf, String address, 1164 int minConnectionInterval, int maxConnectionInterval, 1165 int peripheralLatency, int supervisionTimeout, 1166 int minConnectionEventLen, int maxConnectionEventLen, 1167 AttributionSource attributionSource, SynchronousResultReceiver receiver) { 1168 try { 1169 leConnectionUpdate(clientIf, address, minConnectionInterval, maxConnectionInterval, 1170 peripheralLatency, supervisionTimeout, minConnectionEventLen, 1171 maxConnectionEventLen, attributionSource); 1172 receiver.send(null); 1173 } catch (RuntimeException e) { 1174 receiver.propagateException(e); 1175 } 1176 } leConnectionUpdate(int clientIf, String address, int minConnectionInterval, int maxConnectionInterval, int peripheralLatency, int supervisionTimeout, int minConnectionEventLen, int maxConnectionEventLen, AttributionSource attributionSource)1177 private void leConnectionUpdate(int clientIf, String address, 1178 int minConnectionInterval, int maxConnectionInterval, 1179 int peripheralLatency, int supervisionTimeout, 1180 int minConnectionEventLen, int maxConnectionEventLen, 1181 AttributionSource attributionSource) { 1182 GattService service = getService(); 1183 if (service == null) { 1184 return; 1185 } 1186 service.leConnectionUpdate(clientIf, address, minConnectionInterval, 1187 maxConnectionInterval, peripheralLatency, 1188 supervisionTimeout, minConnectionEventLen, 1189 maxConnectionEventLen, attributionSource); 1190 } 1191 1192 @Override subrateModeRequest(int clientIf, String address, int subrateMode, AttributionSource attributionSource, SynchronousResultReceiver receiver)1193 public void subrateModeRequest(int clientIf, String address, int subrateMode, 1194 AttributionSource attributionSource, SynchronousResultReceiver receiver) { 1195 try { 1196 subrateModeRequest(clientIf, address, subrateMode, attributionSource); 1197 receiver.send(null); 1198 } catch (RuntimeException e) { 1199 receiver.propagateException(e); 1200 } 1201 } subrateModeRequest(int clientIf, String address, int subrateMode, AttributionSource attributionSource)1202 private void subrateModeRequest(int clientIf, String address, int subrateMode, 1203 AttributionSource attributionSource) { 1204 GattService service = getService(); 1205 if (service == null) { 1206 return; 1207 } 1208 service.subrateModeRequest(clientIf, address, subrateMode, attributionSource); 1209 } 1210 1211 @Override leSubrateRequest(int clientIf, String address, int subrateMin, int subrateMax, int maxLatency, int contNumber, int supervisionTimeout, AttributionSource attributionSource, SynchronousResultReceiver receiver)1212 public void leSubrateRequest(int clientIf, String address, int subrateMin, int subrateMax, 1213 int maxLatency, int contNumber, int supervisionTimeout, 1214 AttributionSource attributionSource, SynchronousResultReceiver receiver) { 1215 try { 1216 leSubrateRequest(clientIf, address, subrateMin, subrateMax, maxLatency, contNumber, 1217 supervisionTimeout, attributionSource); 1218 receiver.send(null); 1219 } catch (RuntimeException e) { 1220 receiver.propagateException(e); 1221 } 1222 } leSubrateRequest(int clientIf, String address, int subrateMin, int subrateMax, int maxLatency, int contNumber, int supervisionTimeout, AttributionSource attributionSource)1223 private void leSubrateRequest(int clientIf, String address, int subrateMin, int subrateMax, 1224 int maxLatency, int contNumber, int supervisionTimeout, 1225 AttributionSource attributionSource) { 1226 GattService service = getService(); 1227 if (service == null) { 1228 return; 1229 } 1230 service.leSubrateRequest(clientIf, address, subrateMin, subrateMax, maxLatency, 1231 contNumber, supervisionTimeout, attributionSource); 1232 } 1233 1234 @Override registerServer(ParcelUuid uuid, IBluetoothGattServerCallback callback, boolean eattSupport, AttributionSource attributionSource, SynchronousResultReceiver receiver)1235 public void registerServer(ParcelUuid uuid, IBluetoothGattServerCallback callback, 1236 boolean eattSupport, AttributionSource attributionSource, 1237 SynchronousResultReceiver receiver) { 1238 try { 1239 registerServer(uuid, callback, eattSupport, attributionSource); 1240 receiver.send(null); 1241 } catch (RuntimeException e) { 1242 receiver.propagateException(e); 1243 } 1244 } registerServer(ParcelUuid uuid, IBluetoothGattServerCallback callback, boolean eatt_support, AttributionSource attributionSource)1245 private void registerServer(ParcelUuid uuid, IBluetoothGattServerCallback callback, 1246 boolean eatt_support, AttributionSource attributionSource) { 1247 GattService service = getService(); 1248 if (service == null) { 1249 return; 1250 } 1251 service.registerServer(uuid.getUuid(), callback, eatt_support, attributionSource); 1252 } 1253 1254 @Override unregisterServer(int serverIf, AttributionSource attributionSource, SynchronousResultReceiver receiver)1255 public void unregisterServer(int serverIf, AttributionSource attributionSource, 1256 SynchronousResultReceiver receiver) { 1257 try { 1258 unregisterServer(serverIf, attributionSource); 1259 receiver.send(null); 1260 } catch (RuntimeException e) { 1261 receiver.propagateException(e); 1262 } 1263 } unregisterServer(int serverIf, AttributionSource attributionSource)1264 private void unregisterServer(int serverIf, AttributionSource attributionSource) { 1265 GattService service = getService(); 1266 if (service == null) { 1267 return; 1268 } 1269 service.unregisterServer(serverIf, attributionSource); 1270 } 1271 1272 @Override serverConnect(int serverIf, String address, boolean isDirect, int transport, AttributionSource attributionSource, SynchronousResultReceiver receiver)1273 public void serverConnect(int serverIf, String address, boolean isDirect, int transport, 1274 AttributionSource attributionSource, SynchronousResultReceiver receiver) { 1275 try { 1276 serverConnect(serverIf, address, isDirect, transport, attributionSource); 1277 receiver.send(null); 1278 } catch (RuntimeException e) { 1279 receiver.propagateException(e); 1280 } 1281 } serverConnect(int serverIf, String address, boolean isDirect, int transport, AttributionSource attributionSource)1282 private void serverConnect(int serverIf, String address, boolean isDirect, int transport, 1283 AttributionSource attributionSource) { 1284 GattService service = getService(); 1285 if (service == null) { 1286 return; 1287 } 1288 service.serverConnect(serverIf, address, isDirect, transport, attributionSource); 1289 } 1290 1291 @Override serverDisconnect(int serverIf, String address, AttributionSource attributionSource, SynchronousResultReceiver receiver)1292 public void serverDisconnect(int serverIf, String address, 1293 AttributionSource attributionSource, SynchronousResultReceiver receiver) { 1294 try { 1295 serverDisconnect(serverIf, address, attributionSource); 1296 receiver.send(null); 1297 } catch (RuntimeException e) { 1298 receiver.propagateException(e); 1299 } 1300 } serverDisconnect(int serverIf, String address, AttributionSource attributionSource)1301 private void serverDisconnect(int serverIf, String address, 1302 AttributionSource attributionSource) { 1303 GattService service = getService(); 1304 if (service == null) { 1305 return; 1306 } 1307 service.serverDisconnect(serverIf, address, attributionSource); 1308 } 1309 1310 @Override serverSetPreferredPhy(int serverIf, String address, int txPhy, int rxPhy, int phyOptions, AttributionSource attributionSource, SynchronousResultReceiver receiver)1311 public void serverSetPreferredPhy(int serverIf, String address, int txPhy, int rxPhy, 1312 int phyOptions, AttributionSource attributionSource, 1313 SynchronousResultReceiver receiver) { 1314 try { 1315 serverSetPreferredPhy(serverIf, address, txPhy, rxPhy, phyOptions, 1316 attributionSource); 1317 receiver.send(null); 1318 } catch (RuntimeException e) { 1319 receiver.propagateException(e); 1320 } 1321 } serverSetPreferredPhy(int serverIf, String address, int txPhy, int rxPhy, int phyOptions, AttributionSource attributionSource)1322 private void serverSetPreferredPhy(int serverIf, String address, int txPhy, int rxPhy, 1323 int phyOptions, AttributionSource attributionSource) { 1324 GattService service = getService(); 1325 if (service == null) { 1326 return; 1327 } 1328 service.serverSetPreferredPhy( 1329 serverIf, address, txPhy, rxPhy, phyOptions, attributionSource); 1330 } 1331 1332 @Override serverReadPhy(int clientIf, String address, AttributionSource attributionSource, SynchronousResultReceiver receiver)1333 public void serverReadPhy(int clientIf, String address, AttributionSource attributionSource, 1334 SynchronousResultReceiver receiver) { 1335 try { 1336 serverReadPhy(clientIf, address, attributionSource); 1337 receiver.send(null); 1338 } catch (RuntimeException e) { 1339 receiver.propagateException(e); 1340 } 1341 } serverReadPhy(int clientIf, String address, AttributionSource attributionSource)1342 private void serverReadPhy(int clientIf, String address, 1343 AttributionSource attributionSource) { 1344 GattService service = getService(); 1345 if (service == null) { 1346 return; 1347 } 1348 service.serverReadPhy(clientIf, address, attributionSource); 1349 } 1350 1351 @Override addService(int serverIf, BluetoothGattService svc, AttributionSource attributionSource, SynchronousResultReceiver receiver)1352 public void addService(int serverIf, BluetoothGattService svc, 1353 AttributionSource attributionSource, SynchronousResultReceiver receiver) { 1354 try { 1355 addService(serverIf, svc, attributionSource); 1356 receiver.send(null); 1357 } catch (RuntimeException e) { 1358 receiver.propagateException(e); 1359 } 1360 } addService(int serverIf, BluetoothGattService svc, AttributionSource attributionSource)1361 private void addService(int serverIf, BluetoothGattService svc, 1362 AttributionSource attributionSource) { 1363 GattService service = getService(); 1364 if (service == null) { 1365 return; 1366 } 1367 1368 service.addService(serverIf, svc, attributionSource); 1369 } 1370 1371 @Override removeService(int serverIf, int handle, AttributionSource attributionSource, SynchronousResultReceiver receiver)1372 public void removeService(int serverIf, int handle, AttributionSource attributionSource, 1373 SynchronousResultReceiver receiver) { 1374 try { 1375 removeService(serverIf, handle, attributionSource); 1376 receiver.send(null); 1377 } catch (RuntimeException e) { 1378 receiver.propagateException(e); 1379 } 1380 } removeService(int serverIf, int handle, AttributionSource attributionSource)1381 private void removeService(int serverIf, int handle, AttributionSource attributionSource) { 1382 GattService service = getService(); 1383 if (service == null) { 1384 return; 1385 } 1386 service.removeService(serverIf, handle, attributionSource); 1387 } 1388 1389 @Override clearServices(int serverIf, AttributionSource attributionSource, SynchronousResultReceiver receiver)1390 public void clearServices(int serverIf, AttributionSource attributionSource, 1391 SynchronousResultReceiver receiver) { 1392 try { 1393 clearServices(serverIf, attributionSource); 1394 receiver.send(null); 1395 } catch (RuntimeException e) { 1396 receiver.propagateException(e); 1397 } 1398 } clearServices(int serverIf, AttributionSource attributionSource)1399 private void clearServices(int serverIf, AttributionSource attributionSource) { 1400 GattService service = getService(); 1401 if (service == null) { 1402 return; 1403 } 1404 service.clearServices(serverIf, attributionSource); 1405 } 1406 1407 @Override sendResponse(int serverIf, String address, int requestId, int status, int offset, byte[] value, AttributionSource attributionSource, SynchronousResultReceiver receiver)1408 public void sendResponse(int serverIf, String address, int requestId, int status, 1409 int offset, byte[] value, AttributionSource attributionSource, 1410 SynchronousResultReceiver receiver) { 1411 try { 1412 sendResponse(serverIf, address, requestId, status, offset, value, 1413 attributionSource); 1414 receiver.send(null); 1415 } catch (RuntimeException e) { 1416 receiver.propagateException(e); 1417 } 1418 } sendResponse(int serverIf, String address, int requestId, int status, int offset, byte[] value, AttributionSource attributionSource)1419 private void sendResponse(int serverIf, String address, int requestId, int status, 1420 int offset, byte[] value, AttributionSource attributionSource) { 1421 GattService service = getService(); 1422 if (service == null) { 1423 return; 1424 } 1425 service.sendResponse( 1426 serverIf, address, requestId, status, offset, value, attributionSource); 1427 } 1428 1429 @Override sendNotification(int serverIf, String address, int handle, boolean confirm, byte[] value, AttributionSource attributionSource, SynchronousResultReceiver receiver)1430 public void sendNotification(int serverIf, String address, int handle, boolean confirm, 1431 byte[] value, AttributionSource attributionSource, 1432 SynchronousResultReceiver receiver) { 1433 try { 1434 receiver.send(sendNotification(serverIf, address, handle, confirm, value, 1435 attributionSource)); 1436 } catch (RuntimeException e) { 1437 receiver.propagateException(e); 1438 } 1439 } sendNotification(int serverIf, String address, int handle, boolean confirm, byte[] value, AttributionSource attributionSource)1440 private int sendNotification(int serverIf, String address, int handle, boolean confirm, 1441 byte[] value, AttributionSource attributionSource) { 1442 GattService service = getService(); 1443 if (service == null) { 1444 return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND; 1445 } 1446 return service.sendNotification(serverIf, address, handle, confirm, value, 1447 attributionSource); 1448 } 1449 1450 @Override startAdvertisingSet(AdvertisingSetParameters parameters, AdvertiseData advertiseData, AdvertiseData scanResponse, PeriodicAdvertisingParameters periodicParameters, AdvertiseData periodicData, int duration, int maxExtAdvEvents, int serverIf, IAdvertisingSetCallback callback, AttributionSource attributionSource, SynchronousResultReceiver receiver)1451 public void startAdvertisingSet(AdvertisingSetParameters parameters, 1452 AdvertiseData advertiseData, AdvertiseData scanResponse, 1453 PeriodicAdvertisingParameters periodicParameters, AdvertiseData periodicData, 1454 int duration, int maxExtAdvEvents, int serverIf, IAdvertisingSetCallback callback, 1455 AttributionSource attributionSource, SynchronousResultReceiver receiver) { 1456 try { 1457 startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters, 1458 periodicData, duration, maxExtAdvEvents, serverIf, callback, 1459 attributionSource); 1460 receiver.send(null); 1461 } catch (RuntimeException e) { 1462 receiver.propagateException(e); 1463 } 1464 } startAdvertisingSet(AdvertisingSetParameters parameters, AdvertiseData advertiseData, AdvertiseData scanResponse, PeriodicAdvertisingParameters periodicParameters, AdvertiseData periodicData, int duration, int maxExtAdvEvents, int serverIf, IAdvertisingSetCallback callback, AttributionSource attributionSource)1465 private void startAdvertisingSet(AdvertisingSetParameters parameters, 1466 AdvertiseData advertiseData, AdvertiseData scanResponse, 1467 PeriodicAdvertisingParameters periodicParameters, AdvertiseData periodicData, 1468 int duration, int maxExtAdvEvents, int serverIf, IAdvertisingSetCallback callback, 1469 AttributionSource attributionSource) { 1470 GattService service = getService(); 1471 if (service == null) { 1472 return; 1473 } 1474 service.startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters, 1475 periodicData, duration, maxExtAdvEvents, serverIf, callback, attributionSource); 1476 } 1477 1478 @Override stopAdvertisingSet(IAdvertisingSetCallback callback, AttributionSource attributionSource, SynchronousResultReceiver receiver)1479 public void stopAdvertisingSet(IAdvertisingSetCallback callback, 1480 AttributionSource attributionSource, SynchronousResultReceiver receiver) { 1481 try { 1482 stopAdvertisingSet(callback, attributionSource); 1483 receiver.send(null); 1484 } catch (RuntimeException e) { 1485 receiver.propagateException(e); 1486 } 1487 } stopAdvertisingSet(IAdvertisingSetCallback callback, AttributionSource attributionSource)1488 private void stopAdvertisingSet(IAdvertisingSetCallback callback, 1489 AttributionSource attributionSource) { 1490 GattService service = getService(); 1491 if (service == null) { 1492 return; 1493 } 1494 service.stopAdvertisingSet(callback, attributionSource); 1495 } 1496 1497 @Override getOwnAddress(int advertiserId, AttributionSource attributionSource, SynchronousResultReceiver receiver)1498 public void getOwnAddress(int advertiserId, AttributionSource attributionSource, 1499 SynchronousResultReceiver receiver) { 1500 try { 1501 getOwnAddress(advertiserId, attributionSource); 1502 receiver.send(null); 1503 } catch (RuntimeException e) { 1504 receiver.propagateException(e); 1505 } 1506 } getOwnAddress(int advertiserId, AttributionSource attributionSource)1507 private void getOwnAddress(int advertiserId, AttributionSource attributionSource) { 1508 GattService service = getService(); 1509 if (service == null) { 1510 return; 1511 } 1512 service.getOwnAddress(advertiserId, attributionSource); 1513 } 1514 1515 @Override enableAdvertisingSet(int advertiserId, boolean enable, int duration, int maxExtAdvEvents, AttributionSource attributionSource, SynchronousResultReceiver receiver)1516 public void enableAdvertisingSet(int advertiserId, boolean enable, int duration, 1517 int maxExtAdvEvents, AttributionSource attributionSource, 1518 SynchronousResultReceiver receiver) { 1519 try { 1520 enableAdvertisingSet(advertiserId, enable, duration, maxExtAdvEvents, 1521 attributionSource); 1522 receiver.send(null); 1523 } catch (RuntimeException e) { 1524 receiver.propagateException(e); 1525 } 1526 } enableAdvertisingSet(int advertiserId, boolean enable, int duration, int maxExtAdvEvents, AttributionSource attributionSource)1527 private void enableAdvertisingSet(int advertiserId, boolean enable, int duration, 1528 int maxExtAdvEvents, AttributionSource attributionSource) { 1529 GattService service = getService(); 1530 if (service == null) { 1531 return; 1532 } 1533 service.enableAdvertisingSet( 1534 advertiserId, enable, duration, maxExtAdvEvents, attributionSource); 1535 } 1536 1537 @Override setAdvertisingData(int advertiserId, AdvertiseData data, AttributionSource attributionSource, SynchronousResultReceiver receiver)1538 public void setAdvertisingData(int advertiserId, AdvertiseData data, 1539 AttributionSource attributionSource, SynchronousResultReceiver receiver) { 1540 try { 1541 setAdvertisingData(advertiserId, data, attributionSource); 1542 receiver.send(null); 1543 } catch (RuntimeException e) { 1544 receiver.propagateException(e); 1545 } 1546 } setAdvertisingData(int advertiserId, AdvertiseData data, AttributionSource attributionSource)1547 private void setAdvertisingData(int advertiserId, AdvertiseData data, 1548 AttributionSource attributionSource) { 1549 GattService service = getService(); 1550 if (service == null) { 1551 return; 1552 } 1553 service.setAdvertisingData(advertiserId, data, attributionSource); 1554 } 1555 1556 @Override setScanResponseData(int advertiserId, AdvertiseData data, AttributionSource attributionSource, SynchronousResultReceiver receiver)1557 public void setScanResponseData(int advertiserId, AdvertiseData data, 1558 AttributionSource attributionSource, SynchronousResultReceiver receiver) { 1559 try { 1560 setScanResponseData(advertiserId, data, attributionSource); 1561 receiver.send(null); 1562 } catch (RuntimeException e) { 1563 receiver.propagateException(e); 1564 } 1565 } setScanResponseData(int advertiserId, AdvertiseData data, AttributionSource attributionSource)1566 private void setScanResponseData(int advertiserId, AdvertiseData data, 1567 AttributionSource attributionSource) { 1568 GattService service = getService(); 1569 if (service == null) { 1570 return; 1571 } 1572 service.setScanResponseData(advertiserId, data, attributionSource); 1573 } 1574 1575 @Override setAdvertisingParameters(int advertiserId, AdvertisingSetParameters parameters, AttributionSource attributionSource, SynchronousResultReceiver receiver)1576 public void setAdvertisingParameters(int advertiserId, 1577 AdvertisingSetParameters parameters, AttributionSource attributionSource, 1578 SynchronousResultReceiver receiver) { 1579 try { 1580 setAdvertisingParameters(advertiserId, parameters, attributionSource); 1581 receiver.send(null); 1582 } catch (RuntimeException e) { 1583 receiver.propagateException(e); 1584 } 1585 } setAdvertisingParameters(int advertiserId, AdvertisingSetParameters parameters, AttributionSource attributionSource)1586 private void setAdvertisingParameters(int advertiserId, 1587 AdvertisingSetParameters parameters, AttributionSource attributionSource) { 1588 GattService service = getService(); 1589 if (service == null) { 1590 return; 1591 } 1592 service.setAdvertisingParameters(advertiserId, parameters, attributionSource); 1593 } 1594 1595 @Override setPeriodicAdvertisingParameters(int advertiserId, PeriodicAdvertisingParameters parameters, AttributionSource attributionSource, SynchronousResultReceiver receiver)1596 public void setPeriodicAdvertisingParameters(int advertiserId, 1597 PeriodicAdvertisingParameters parameters, AttributionSource attributionSource, 1598 SynchronousResultReceiver receiver) { 1599 try { 1600 setPeriodicAdvertisingParameters(advertiserId, parameters, attributionSource); 1601 receiver.send(null); 1602 } catch (RuntimeException e) { 1603 receiver.propagateException(e); 1604 } 1605 } setPeriodicAdvertisingParameters(int advertiserId, PeriodicAdvertisingParameters parameters, AttributionSource attributionSource)1606 private void setPeriodicAdvertisingParameters(int advertiserId, 1607 PeriodicAdvertisingParameters parameters, AttributionSource attributionSource) { 1608 GattService service = getService(); 1609 if (service == null) { 1610 return; 1611 } 1612 service.setPeriodicAdvertisingParameters(advertiserId, parameters, attributionSource); 1613 } 1614 1615 @Override setPeriodicAdvertisingData(int advertiserId, AdvertiseData data, AttributionSource attributionSource, SynchronousResultReceiver receiver)1616 public void setPeriodicAdvertisingData(int advertiserId, AdvertiseData data, 1617 AttributionSource attributionSource, SynchronousResultReceiver receiver) { 1618 try { 1619 setPeriodicAdvertisingData(advertiserId, data, attributionSource); 1620 receiver.send(null); 1621 } catch (RuntimeException e) { 1622 receiver.propagateException(e); 1623 } 1624 } setPeriodicAdvertisingData(int advertiserId, AdvertiseData data, AttributionSource attributionSource)1625 private void setPeriodicAdvertisingData(int advertiserId, AdvertiseData data, 1626 AttributionSource attributionSource) { 1627 GattService service = getService(); 1628 if (service == null) { 1629 return; 1630 } 1631 service.setPeriodicAdvertisingData(advertiserId, data, attributionSource); 1632 } 1633 1634 @Override setPeriodicAdvertisingEnable(int advertiserId, boolean enable, AttributionSource attributionSource, SynchronousResultReceiver receiver)1635 public void setPeriodicAdvertisingEnable(int advertiserId, boolean enable, 1636 AttributionSource attributionSource, SynchronousResultReceiver receiver) { 1637 try { 1638 setPeriodicAdvertisingEnable(advertiserId, enable, attributionSource); 1639 receiver.send(null); 1640 } catch (RuntimeException e) { 1641 receiver.propagateException(e); 1642 } 1643 } setPeriodicAdvertisingEnable(int advertiserId, boolean enable, AttributionSource attributionSource)1644 private void setPeriodicAdvertisingEnable(int advertiserId, boolean enable, 1645 AttributionSource attributionSource) { 1646 GattService service = getService(); 1647 if (service == null) { 1648 return; 1649 } 1650 service.setPeriodicAdvertisingEnable(advertiserId, enable, attributionSource); 1651 } 1652 1653 @Override registerSync(ScanResult scanResult, int skip, int timeout, IPeriodicAdvertisingCallback callback, AttributionSource attributionSource, SynchronousResultReceiver receiver)1654 public void registerSync(ScanResult scanResult, int skip, int timeout, 1655 IPeriodicAdvertisingCallback callback, AttributionSource attributionSource, 1656 SynchronousResultReceiver receiver) { 1657 try { 1658 registerSync(scanResult, skip, timeout, callback, attributionSource); 1659 receiver.send(null); 1660 } catch (RuntimeException e) { 1661 receiver.propagateException(e); 1662 } 1663 } registerSync(ScanResult scanResult, int skip, int timeout, IPeriodicAdvertisingCallback callback, AttributionSource attributionSource)1664 private void registerSync(ScanResult scanResult, int skip, int timeout, 1665 IPeriodicAdvertisingCallback callback, AttributionSource attributionSource) { 1666 GattService service = getService(); 1667 if (service == null) { 1668 return; 1669 } 1670 service.registerSync(scanResult, skip, timeout, callback, attributionSource); 1671 } 1672 1673 @Override transferSync(BluetoothDevice bda, int serviceData , int syncHandle, AttributionSource attributionSource, SynchronousResultReceiver receiver)1674 public void transferSync(BluetoothDevice bda, int serviceData , int syncHandle, 1675 AttributionSource attributionSource, SynchronousResultReceiver receiver) { 1676 try { 1677 transferSync(bda, serviceData , syncHandle, attributionSource); 1678 receiver.send(null); 1679 } catch (RuntimeException e) { 1680 receiver.propagateException(e); 1681 } 1682 } transferSync(BluetoothDevice bda, int serviceData , int syncHandle, AttributionSource attributionSource)1683 public void transferSync(BluetoothDevice bda, int serviceData , int syncHandle, 1684 AttributionSource attributionSource) { 1685 GattService service = getService(); 1686 if (service == null) { 1687 return; 1688 } 1689 service.transferSync(bda, serviceData , syncHandle, attributionSource); 1690 } 1691 1692 @Override transferSetInfo(BluetoothDevice bda, int serviceData , int advHandle, IPeriodicAdvertisingCallback callback, AttributionSource attributionSource, SynchronousResultReceiver receiver)1693 public void transferSetInfo(BluetoothDevice bda, int serviceData , int advHandle, 1694 IPeriodicAdvertisingCallback callback, AttributionSource attributionSource, 1695 SynchronousResultReceiver receiver) { 1696 try { 1697 transferSetInfo(bda, serviceData , advHandle, callback, attributionSource); 1698 receiver.send(null); 1699 } catch (RuntimeException e) { 1700 receiver.propagateException(e); 1701 } 1702 } transferSetInfo(BluetoothDevice bda, int serviceData , int advHandle, IPeriodicAdvertisingCallback callback, AttributionSource attributionSource)1703 public void transferSetInfo(BluetoothDevice bda, int serviceData , int advHandle, 1704 IPeriodicAdvertisingCallback callback, AttributionSource attributionSource) { 1705 GattService service = getService(); 1706 if (service == null) { 1707 return; 1708 } 1709 service.transferSetInfo(bda, serviceData , advHandle, callback, attributionSource); 1710 } 1711 1712 @Override unregisterSync(IPeriodicAdvertisingCallback callback, AttributionSource attributionSource, SynchronousResultReceiver receiver)1713 public void unregisterSync(IPeriodicAdvertisingCallback callback, 1714 AttributionSource attributionSource, SynchronousResultReceiver receiver) { 1715 try { 1716 unregisterSync(callback, attributionSource); 1717 receiver.send(null); 1718 } catch (RuntimeException e) { 1719 receiver.propagateException(e); 1720 } 1721 } unregisterSync(IPeriodicAdvertisingCallback callback, AttributionSource attributionSource)1722 public void unregisterSync(IPeriodicAdvertisingCallback callback, 1723 AttributionSource attributionSource) { 1724 GattService service = getService(); 1725 if (service == null) { 1726 return; 1727 } 1728 service.unregisterSync(callback, attributionSource); 1729 } 1730 1731 @Override disconnectAll(AttributionSource attributionSource, SynchronousResultReceiver receiver)1732 public void disconnectAll(AttributionSource attributionSource, 1733 SynchronousResultReceiver receiver) { 1734 try { 1735 disconnectAll(attributionSource); 1736 receiver.send(null); 1737 } catch (RuntimeException e) { 1738 receiver.propagateException(e); 1739 } 1740 } disconnectAll(AttributionSource attributionSource)1741 private void disconnectAll(AttributionSource attributionSource) { 1742 GattService service = getService(); 1743 if (service == null) { 1744 return; 1745 } 1746 service.disconnectAll(attributionSource); 1747 } 1748 1749 @Override unregAll(AttributionSource source, SynchronousResultReceiver receiver)1750 public void unregAll(AttributionSource source, SynchronousResultReceiver receiver) { 1751 try { 1752 unregAll(source); 1753 receiver.send(null); 1754 } catch (RuntimeException e) { 1755 receiver.propagateException(e); 1756 } 1757 } unregAll(AttributionSource attributionSource)1758 private void unregAll(AttributionSource attributionSource) { 1759 GattService service = getService(); 1760 if (service == null) { 1761 return; 1762 } 1763 service.unregAll(attributionSource); 1764 } 1765 1766 @Override numHwTrackFiltersAvailable(AttributionSource attributionSource, SynchronousResultReceiver receiver)1767 public void numHwTrackFiltersAvailable(AttributionSource attributionSource, 1768 SynchronousResultReceiver receiver) { 1769 try { 1770 receiver.send(numHwTrackFiltersAvailable(attributionSource)); 1771 } catch (RuntimeException e) { 1772 receiver.propagateException(e); 1773 } 1774 } numHwTrackFiltersAvailable(AttributionSource attributionSource)1775 private int numHwTrackFiltersAvailable(AttributionSource attributionSource) { 1776 GattService service = getService(); 1777 if (service == null) { 1778 return 0; 1779 } 1780 return service.numHwTrackFiltersAvailable(attributionSource); 1781 } 1782 1783 @Override getSupportedDistanceMeasurementMethods(AttributionSource attributionSource, SynchronousResultReceiver receiver)1784 public void getSupportedDistanceMeasurementMethods(AttributionSource attributionSource, 1785 SynchronousResultReceiver receiver) { 1786 try { 1787 receiver.send(getSupportedDistanceMeasurementMethods(attributionSource)); 1788 } catch (RuntimeException e) { 1789 receiver.propagateException(e); 1790 } 1791 } 1792 getSupportedDistanceMeasurementMethods( AttributionSource attributionSource)1793 private List<DistanceMeasurementMethod> getSupportedDistanceMeasurementMethods( 1794 AttributionSource attributionSource) { 1795 GattService service = getService(); 1796 if (service == null || !callerIsSystemOrActiveOrManagedUser(service, TAG, 1797 "GattService getSupportedDistanceMeasurementMethods") 1798 || !Utils.checkConnectPermissionForDataDelivery( 1799 service, attributionSource, 1800 "GattService getSupportedDistanceMeasurementMethods")) { 1801 return new ArrayList<>(); 1802 } 1803 enforceBluetoothPrivilegedPermission(service); 1804 return Arrays.asList(service.getSupportedDistanceMeasurementMethods()); 1805 } 1806 1807 @Override startDistanceMeasurement(ParcelUuid uuid, DistanceMeasurementParams distanceMeasurementParams, IDistanceMeasurementCallback callback, AttributionSource attributionSource, SynchronousResultReceiver receiver)1808 public void startDistanceMeasurement(ParcelUuid uuid, 1809 DistanceMeasurementParams distanceMeasurementParams, 1810 IDistanceMeasurementCallback callback, AttributionSource attributionSource, 1811 SynchronousResultReceiver receiver) { 1812 try { 1813 startDistanceMeasurement(uuid, distanceMeasurementParams, callback, 1814 attributionSource); 1815 receiver.send(null); 1816 } catch (RuntimeException e) { 1817 receiver.propagateException(e); 1818 } 1819 } 1820 startDistanceMeasurement(ParcelUuid uuid, DistanceMeasurementParams distanceMeasurementParams, IDistanceMeasurementCallback callback, AttributionSource attributionSource)1821 private void startDistanceMeasurement(ParcelUuid uuid, 1822 DistanceMeasurementParams distanceMeasurementParams, 1823 IDistanceMeasurementCallback callback, AttributionSource attributionSource) { 1824 GattService service = getService(); 1825 if (service == null || !callerIsSystemOrActiveOrManagedUser(service, TAG, 1826 "startDistanceMeasurement") || !Utils.checkConnectPermissionForDataDelivery( 1827 service, attributionSource, "GattService startDistanceMeasurement")) { 1828 return; 1829 } 1830 enforceBluetoothPrivilegedPermission(service); 1831 service.startDistanceMeasurement(uuid.getUuid(), distanceMeasurementParams, callback); 1832 } 1833 1834 @Override stopDistanceMeasurement(ParcelUuid uuid, BluetoothDevice device, int method, AttributionSource attributionSource, SynchronousResultReceiver receiver)1835 public void stopDistanceMeasurement(ParcelUuid uuid, BluetoothDevice device, int method, 1836 AttributionSource attributionSource, SynchronousResultReceiver receiver) { 1837 try { 1838 receiver.send(stopDistanceMeasurement(uuid, device, method, attributionSource)); 1839 } catch (RuntimeException e) { 1840 receiver.propagateException(e); 1841 } 1842 } 1843 stopDistanceMeasurement(ParcelUuid uuid, BluetoothDevice device, int method, AttributionSource attributionSource)1844 private int stopDistanceMeasurement(ParcelUuid uuid, BluetoothDevice device, int method, 1845 AttributionSource attributionSource) { 1846 GattService service = getService(); 1847 if (service == null) { 1848 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; 1849 } else if (!callerIsSystemOrActiveOrManagedUser(service, TAG, 1850 "stopDistanceMeasurement")) { 1851 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; 1852 } else if (!Utils.checkConnectPermissionForDataDelivery( 1853 service, attributionSource, "GattService stopDistanceMeasurement")) { 1854 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; 1855 } 1856 enforceBluetoothPrivilegedPermission(service); 1857 return service.stopDistanceMeasurement(uuid.getUuid(), device, method); 1858 } 1859 }; 1860 1861 /************************************************************************** 1862 * Callback functions - CLIENT 1863 *************************************************************************/ 1864 1865 // EN format defined here: 1866 // https://blog.google/documents/70/Exposure_Notification_-_Bluetooth_Specification_v1.2.2.pdf 1867 private static final byte[] EXPOSURE_NOTIFICATION_FLAGS_PREAMBLE = new byte[] { 1868 // size 2, flag field, flags byte (value is not important) 1869 (byte) 0x02, (byte) 0x01 1870 }; 1871 private static final int EXPOSURE_NOTIFICATION_FLAGS_LENGTH = 0x2 + 1; 1872 private static final byte[] EXPOSURE_NOTIFICATION_PAYLOAD_PREAMBLE = new byte[] { 1873 // size 3, complete 16 bit UUID, EN UUID 1874 (byte) 0x03, (byte) 0x03, (byte) 0x6F, (byte) 0xFD, 1875 // size 23, data for 16 bit UUID, EN UUID 1876 (byte) 0x17, (byte) 0x16, (byte) 0x6F, (byte) 0xFD, 1877 // ...payload 1878 }; 1879 private static final int EXPOSURE_NOTIFICATION_PAYLOAD_LENGTH = 0x03 + 0x17 + 2; 1880 arrayStartsWith(byte[] array, byte[] prefix)1881 private static boolean arrayStartsWith(byte[] array, byte[] prefix) { 1882 if (array.length < prefix.length) { 1883 return false; 1884 } 1885 for (int i = 0; i < prefix.length; i++) { 1886 if (prefix[i] != array[i]) { 1887 return false; 1888 } 1889 } 1890 return true; 1891 } 1892 getSanitizedExposureNotification(ScanResult result)1893 ScanResult getSanitizedExposureNotification(ScanResult result) { 1894 ScanRecord record = result.getScanRecord(); 1895 // Remove the flags part of the payload, if present 1896 if (record.getBytes().length > EXPOSURE_NOTIFICATION_FLAGS_LENGTH 1897 && arrayStartsWith(record.getBytes(), EXPOSURE_NOTIFICATION_FLAGS_PREAMBLE)) { 1898 record = ScanRecord.parseFromBytes( 1899 Arrays.copyOfRange( 1900 record.getBytes(), 1901 EXPOSURE_NOTIFICATION_FLAGS_LENGTH, 1902 record.getBytes().length)); 1903 } 1904 1905 if (record.getBytes().length != EXPOSURE_NOTIFICATION_PAYLOAD_LENGTH) { 1906 return null; 1907 } 1908 if (!arrayStartsWith(record.getBytes(), EXPOSURE_NOTIFICATION_PAYLOAD_PREAMBLE)) { 1909 return null; 1910 } 1911 1912 return new ScanResult(null, 0, 0, 0, 0, 0, result.getRssi(), 0, record, 0); 1913 } 1914 onScanResult(int eventType, int addressType, String address, int primaryPhy, int secondaryPhy, int advertisingSid, int txPower, int rssi, int periodicAdvInt, byte[] advData, String originalAddress)1915 void onScanResult(int eventType, int addressType, String address, int primaryPhy, 1916 int secondaryPhy, int advertisingSid, int txPower, int rssi, int periodicAdvInt, 1917 byte[] advData, String originalAddress) { 1918 // When in testing mode, ignore all real-world events 1919 if (isTestModeEnabled()) return; 1920 1921 AppScanStats.recordScanRadioResultCount(); 1922 onScanResultInternal(eventType, addressType, address, primaryPhy, secondaryPhy, 1923 advertisingSid, txPower, rssi, periodicAdvInt, advData, originalAddress); 1924 } 1925 onScanResultInternal(int eventType, int addressType, String address, int primaryPhy, int secondaryPhy, int advertisingSid, int txPower, int rssi, int periodicAdvInt, byte[] advData, String originalAddress)1926 void onScanResultInternal(int eventType, int addressType, String address, int primaryPhy, 1927 int secondaryPhy, int advertisingSid, int txPower, int rssi, int periodicAdvInt, 1928 byte[] advData, String originalAddress) { 1929 if (VDBG) { 1930 Log.d(TAG, "onScanResult() - eventType=0x" + Integer.toHexString(eventType) 1931 + ", addressType=" + addressType + ", address=" + address + ", primaryPhy=" 1932 + primaryPhy + ", secondaryPhy=" + secondaryPhy + ", advertisingSid=0x" 1933 + Integer.toHexString(advertisingSid) + ", txPower=" + txPower + ", rssi=" 1934 + rssi + ", periodicAdvInt=0x" + Integer.toHexString(periodicAdvInt) 1935 + ", originalAddress=" + originalAddress); 1936 } 1937 1938 String identityAddress = mAdapterService.getIdentityAddress(address); 1939 if (!address.equals(identityAddress)) { 1940 if (VDBG) { 1941 Log.d(TAG, "found identityAddress of " + address + ", replace originalAddress as " 1942 + identityAddress); 1943 } 1944 originalAddress = identityAddress; 1945 } 1946 1947 1948 byte[] legacyAdvData = Arrays.copyOfRange(advData, 0, 62); 1949 1950 for (ScanClient client : mScanManager.getRegularScanQueue()) { 1951 ScannerMap.App app = mScannerMap.getById(client.scannerId); 1952 if (app == null) { 1953 if (VDBG) { 1954 Log.d(TAG, "App is null; skip."); 1955 } 1956 continue; 1957 } 1958 1959 BluetoothDevice device = 1960 BluetoothAdapter.getDefaultAdapter().getRemoteLeDevice(address, addressType); 1961 1962 ScanSettings settings = client.settings; 1963 byte[] scanRecordData; 1964 // This is for compability with applications that assume fixed size scan data. 1965 if (settings.getLegacy()) { 1966 if ((eventType & ET_LEGACY_MASK) == 0) { 1967 // If this is legacy scan, but nonlegacy result - skip. 1968 if (VDBG) { 1969 Log.d(TAG, "Legacy scan, non legacy result; skip."); 1970 } 1971 continue; 1972 } else { 1973 // Some apps are used to fixed-size advertise data. 1974 scanRecordData = legacyAdvData; 1975 } 1976 } else { 1977 scanRecordData = advData; 1978 } 1979 1980 ScanRecord scanRecord = ScanRecord.parseFromBytes(scanRecordData); 1981 ScanResult result = 1982 new ScanResult(device, eventType, primaryPhy, secondaryPhy, advertisingSid, 1983 txPower, rssi, periodicAdvInt, scanRecord, 1984 SystemClock.elapsedRealtimeNanos()); 1985 1986 if (client.hasDisavowedLocation) { 1987 if (mLocationDenylistPredicate.test(result)) { 1988 Log.i(TAG, "Skipping client for location deny list"); 1989 continue; 1990 } 1991 } 1992 1993 boolean hasPermission = hasScanResultPermission(client); 1994 if (!hasPermission) { 1995 for (String associatedDevice : client.associatedDevices) { 1996 if (associatedDevice.equalsIgnoreCase(address)) { 1997 hasPermission = true; 1998 break; 1999 } 2000 } 2001 } 2002 if (!hasPermission && client.eligibleForSanitizedExposureNotification) { 2003 ScanResult sanitized = getSanitizedExposureNotification(result); 2004 if (sanitized != null) { 2005 hasPermission = true; 2006 result = sanitized; 2007 } 2008 } 2009 MatchResult matchResult = matchesFilters(client, result, originalAddress); 2010 if (!hasPermission || !matchResult.getMatches()) { 2011 if (VDBG) { 2012 Log.d(TAG, "Skipping client: permission=" 2013 + hasPermission + " matches=" + matchResult.getMatches()); 2014 } 2015 continue; 2016 } 2017 2018 int callbackType = settings.getCallbackType(); 2019 if (!(callbackType == ScanSettings.CALLBACK_TYPE_ALL_MATCHES 2020 || callbackType == ScanSettings.CALLBACK_TYPE_ALL_MATCHES_AUTO_BATCH)) { 2021 if (VDBG) { 2022 Log.d(TAG, "Skipping client: CALLBACK_TYPE_ALL_MATCHES"); 2023 } 2024 continue; 2025 } 2026 2027 try { 2028 app.appScanStats.addResult(client.scannerId); 2029 if (app.callback != null) { 2030 app.callback.onScanResult(result); 2031 } else { 2032 // Send the PendingIntent 2033 ArrayList<ScanResult> results = new ArrayList<>(); 2034 results.add(result); 2035 sendResultsByPendingIntent(app.info, results, 2036 ScanSettings.CALLBACK_TYPE_ALL_MATCHES); 2037 } 2038 } catch (RemoteException | PendingIntent.CanceledException e) { 2039 Log.e(TAG, "Exception: " + e); 2040 mScannerMap.remove(client.scannerId); 2041 mScanManager.stopScan(client.scannerId); 2042 } 2043 } 2044 } 2045 sendResultByPendingIntent(PendingIntentInfo pii, ScanResult result, int callbackType, ScanClient client)2046 private void sendResultByPendingIntent(PendingIntentInfo pii, ScanResult result, 2047 int callbackType, ScanClient client) { 2048 ArrayList<ScanResult> results = new ArrayList<>(); 2049 results.add(result); 2050 try { 2051 sendResultsByPendingIntent(pii, results, callbackType); 2052 } catch (PendingIntent.CanceledException e) { 2053 final long token = Binder.clearCallingIdentity(); 2054 try { 2055 stopScan(client.scannerId, getAttributionSource()); 2056 unregisterScanner(client.scannerId, getAttributionSource()); 2057 } finally { 2058 Binder.restoreCallingIdentity(token); 2059 } 2060 } 2061 } 2062 sendResultsByPendingIntent(PendingIntentInfo pii, ArrayList<ScanResult> results, int callbackType)2063 private void sendResultsByPendingIntent(PendingIntentInfo pii, ArrayList<ScanResult> results, 2064 int callbackType) throws PendingIntent.CanceledException { 2065 Intent extrasIntent = new Intent(); 2066 extrasIntent.putParcelableArrayListExtra(BluetoothLeScanner.EXTRA_LIST_SCAN_RESULT, 2067 results); 2068 extrasIntent.putExtra(BluetoothLeScanner.EXTRA_CALLBACK_TYPE, callbackType); 2069 pii.intent.send(this, 0, extrasIntent); 2070 } 2071 sendErrorByPendingIntent(PendingIntentInfo pii, int errorCode)2072 private void sendErrorByPendingIntent(PendingIntentInfo pii, int errorCode) 2073 throws PendingIntent.CanceledException { 2074 Intent extrasIntent = new Intent(); 2075 extrasIntent.putExtra(BluetoothLeScanner.EXTRA_ERROR_CODE, errorCode); 2076 pii.intent.send(this, 0, extrasIntent); 2077 } 2078 onScannerRegistered(int status, int scannerId, long uuidLsb, long uuidMsb)2079 void onScannerRegistered(int status, int scannerId, long uuidLsb, long uuidMsb) 2080 throws RemoteException { 2081 UUID uuid = new UUID(uuidMsb, uuidLsb); 2082 if (DBG) { 2083 Log.d(TAG, "onScannerRegistered() - UUID=" + uuid + ", scannerId=" + scannerId 2084 + ", status=" + status); 2085 } 2086 2087 // First check the callback map 2088 ScannerMap.App cbApp = mScannerMap.getByUuid(uuid); 2089 if (cbApp != null) { 2090 if (status == 0) { 2091 cbApp.id = scannerId; 2092 // If app is callback based, setup a death recipient. App will initiate the start. 2093 // Otherwise, if PendingIntent based, start the scan directly. 2094 if (cbApp.callback != null) { 2095 cbApp.linkToDeath(new ScannerDeathRecipient(scannerId)); 2096 } else { 2097 continuePiStartScan(scannerId, cbApp); 2098 } 2099 } else { 2100 mScannerMap.remove(scannerId); 2101 } 2102 if (cbApp.callback != null) { 2103 cbApp.callback.onScannerRegistered(status, scannerId); 2104 } 2105 } 2106 } 2107 2108 /** Determines if the given scan client has the appropriate permissions to receive callbacks. */ hasScanResultPermission(final ScanClient client)2109 private boolean hasScanResultPermission(final ScanClient client) { 2110 if (client.hasNetworkSettingsPermission 2111 || client.hasNetworkSetupWizardPermission 2112 || client.hasScanWithoutLocationPermission) { 2113 return true; 2114 } 2115 if (client.hasDisavowedLocation) { 2116 return true; 2117 } 2118 return client.hasLocationPermission && !Utils.blockedByLocationOff(this, client.userHandle); 2119 } 2120 2121 // Check if a scan record matches a specific filters. matchesFilters(ScanClient client, ScanResult scanResult)2122 private MatchResult matchesFilters(ScanClient client, ScanResult scanResult) { 2123 return matchesFilters(client, scanResult, null); 2124 } 2125 2126 // Check if a scan record matches a specific filters or original address matchesFilters(ScanClient client, ScanResult scanResult, String originalAddress)2127 private MatchResult matchesFilters(ScanClient client, ScanResult scanResult, 2128 String originalAddress) { 2129 if (client.filters == null || client.filters.isEmpty()) { 2130 // TODO: Do we really wanna return true here? 2131 return new MatchResult(true, MatchOrigin.PSEUDO_ADDRESS); 2132 } 2133 for (ScanFilter filter : client.filters) { 2134 // Need to check the filter matches, and the original address without changing the API 2135 if (filter.matches(scanResult)) { 2136 return new MatchResult(true, MatchOrigin.PSEUDO_ADDRESS); 2137 } 2138 if (originalAddress != null 2139 && originalAddress.equalsIgnoreCase(filter.getDeviceAddress())) { 2140 return new MatchResult(true, MatchOrigin.ORIGINAL_ADDRESS); 2141 } 2142 } 2143 return new MatchResult(false, MatchOrigin.PSEUDO_ADDRESS); 2144 } 2145 onClientRegistered(int status, int clientIf, long uuidLsb, long uuidMsb)2146 void onClientRegistered(int status, int clientIf, long uuidLsb, long uuidMsb) 2147 throws RemoteException { 2148 UUID uuid = new UUID(uuidMsb, uuidLsb); 2149 if (DBG) { 2150 Log.d(TAG, "onClientRegistered() - UUID=" + uuid + ", clientIf=" + clientIf); 2151 } 2152 ClientMap.App app = mClientMap.getByUuid(uuid); 2153 if (app != null) { 2154 if (status == 0) { 2155 app.id = clientIf; 2156 app.linkToDeath(new ClientDeathRecipient(clientIf)); 2157 } else { 2158 mClientMap.remove(uuid); 2159 } 2160 app.callback.onClientRegistered(status, clientIf); 2161 } 2162 } 2163 onConnected(int clientIf, int connId, int status, String address)2164 void onConnected(int clientIf, int connId, int status, String address) throws RemoteException { 2165 if (DBG) { 2166 Log.d(TAG, "onConnected() - clientIf=" + clientIf + ", connId=" + connId + ", address=" 2167 + address); 2168 } 2169 int connectionState = BluetoothProtoEnums.CONNECTION_STATE_DISCONNECTED; 2170 if (status == 0) { 2171 mClientMap.addConnection(clientIf, connId, address); 2172 2173 // Allow one writeCharacteristic operation at a time for each connected remote device. 2174 synchronized (mPermits) { 2175 Log.d(TAG, "onConnected() - adding permit for address=" 2176 + address); 2177 mPermits.putIfAbsent(address, -1); 2178 } 2179 connectionState = BluetoothProtoEnums.CONNECTION_STATE_CONNECTED; 2180 2181 } 2182 ClientMap.App app = mClientMap.getById(clientIf); 2183 if (app != null) { 2184 app.callback.onClientConnectionState(status, clientIf, 2185 (status == BluetoothGatt.GATT_SUCCESS), address); 2186 } 2187 statsLogGattConnectionStateChange( 2188 BluetoothProfile.GATT, address, clientIf, connectionState, status); 2189 } 2190 onDisconnected(int clientIf, int connId, int status, String address)2191 void onDisconnected(int clientIf, int connId, int status, String address) 2192 throws RemoteException { 2193 if (DBG) { 2194 Log.d(TAG, 2195 "onDisconnected() - clientIf=" + clientIf + ", connId=" + connId + ", address=" 2196 + address); 2197 } 2198 2199 mClientMap.removeConnection(clientIf, connId); 2200 ClientMap.App app = mClientMap.getById(clientIf); 2201 2202 // Remove AtomicBoolean representing permit if no other connections rely on this remote device. 2203 if (!mClientMap.getConnectedDevices().contains(address)) { 2204 synchronized (mPermits) { 2205 Log.d(TAG, "onDisconnected() - removing permit for address=" 2206 + address); 2207 mPermits.remove(address); 2208 } 2209 } else { 2210 synchronized (mPermits) { 2211 if (mPermits.get(address) == connId) { 2212 Log.d(TAG, "onDisconnected() - set permit -1 for address=" + address); 2213 mPermits.put(address, -1); 2214 } 2215 } 2216 } 2217 2218 if (app != null) { 2219 app.callback.onClientConnectionState(status, clientIf, false, address); 2220 } 2221 statsLogGattConnectionStateChange( 2222 BluetoothProfile.GATT, address, clientIf, 2223 BluetoothProtoEnums.CONNECTION_STATE_DISCONNECTED, status); 2224 } 2225 onClientPhyUpdate(int connId, int txPhy, int rxPhy, int status)2226 void onClientPhyUpdate(int connId, int txPhy, int rxPhy, int status) throws RemoteException { 2227 if (DBG) { 2228 Log.d(TAG, "onClientPhyUpdate() - connId=" + connId + ", status=" + status); 2229 } 2230 2231 String address = mClientMap.addressByConnId(connId); 2232 if (address == null) { 2233 return; 2234 } 2235 2236 ClientMap.App app = mClientMap.getByConnId(connId); 2237 if (app == null) { 2238 return; 2239 } 2240 2241 app.callback.onPhyUpdate(address, txPhy, rxPhy, status); 2242 } 2243 onClientPhyRead(int clientIf, String address, int txPhy, int rxPhy, int status)2244 void onClientPhyRead(int clientIf, String address, int txPhy, int rxPhy, int status) 2245 throws RemoteException { 2246 if (DBG) { 2247 Log.d(TAG, 2248 "onClientPhyRead() - address=" + address + ", status=" + status + ", clientIf=" 2249 + clientIf); 2250 } 2251 2252 Integer connId = mClientMap.connIdByAddress(clientIf, address); 2253 if (connId == null) { 2254 Log.d(TAG, "onClientPhyRead() - no connection to " + address); 2255 return; 2256 } 2257 2258 ClientMap.App app = mClientMap.getByConnId(connId); 2259 if (app == null) { 2260 return; 2261 } 2262 2263 app.callback.onPhyRead(address, txPhy, rxPhy, status); 2264 } 2265 onClientConnUpdate(int connId, int interval, int latency, int timeout, int status)2266 void onClientConnUpdate(int connId, int interval, int latency, int timeout, int status) 2267 throws RemoteException { 2268 if (DBG) { 2269 Log.d(TAG, "onClientConnUpdate() - connId=" + connId + ", status=" + status); 2270 } 2271 2272 String address = mClientMap.addressByConnId(connId); 2273 if (address == null) { 2274 return; 2275 } 2276 2277 ClientMap.App app = mClientMap.getByConnId(connId); 2278 if (app == null) { 2279 return; 2280 } 2281 2282 app.callback.onConnectionUpdated(address, interval, latency, timeout, status); 2283 } 2284 onServiceChanged(int connId)2285 void onServiceChanged(int connId) throws RemoteException { 2286 if (DBG) { 2287 Log.d(TAG, "onServiceChanged - connId=" + connId); 2288 } 2289 2290 String address = mClientMap.addressByConnId(connId); 2291 if (address == null) { 2292 return; 2293 } 2294 2295 ClientMap.App app = mClientMap.getByConnId(connId); 2296 if (app == null) { 2297 return; 2298 } 2299 2300 app.callback.onServiceChanged(address); 2301 } 2302 onClientSubrateChange(int connId, int subrateFactor, int latency, int contNum, int timeout, int status)2303 void onClientSubrateChange(int connId, int subrateFactor, int latency, int contNum, 2304 int timeout, int status) throws RemoteException { 2305 if (DBG) { 2306 Log.d(TAG, "onClientSubrateChange() - connId=" + connId + ", status=" + status); 2307 } 2308 2309 String address = mClientMap.addressByConnId(connId); 2310 if (address == null) { 2311 return; 2312 } 2313 2314 ClientMap.App app = mClientMap.getByConnId(connId); 2315 if (app == null) { 2316 return; 2317 } 2318 2319 app.callback.onSubrateChange(address, subrateFactor, latency, contNum, timeout, status); 2320 } 2321 onServerPhyUpdate(int connId, int txPhy, int rxPhy, int status)2322 void onServerPhyUpdate(int connId, int txPhy, int rxPhy, int status) throws RemoteException { 2323 if (DBG) { 2324 Log.d(TAG, "onServerPhyUpdate() - connId=" + connId + ", status=" + status); 2325 } 2326 2327 String address = mServerMap.addressByConnId(connId); 2328 if (address == null) { 2329 return; 2330 } 2331 2332 ServerMap.App app = mServerMap.getByConnId(connId); 2333 if (app == null) { 2334 return; 2335 } 2336 2337 app.callback.onPhyUpdate(address, txPhy, rxPhy, status); 2338 } 2339 onServerPhyRead(int serverIf, String address, int txPhy, int rxPhy, int status)2340 void onServerPhyRead(int serverIf, String address, int txPhy, int rxPhy, int status) 2341 throws RemoteException { 2342 if (DBG) { 2343 Log.d(TAG, "onServerPhyRead() - address=" + address + ", status=" + status); 2344 } 2345 2346 Integer connId = mServerMap.connIdByAddress(serverIf, address); 2347 if (connId == null) { 2348 Log.d(TAG, "onServerPhyRead() - no connection to " + address); 2349 return; 2350 } 2351 2352 ServerMap.App app = mServerMap.getByConnId(connId); 2353 if (app == null) { 2354 return; 2355 } 2356 2357 app.callback.onPhyRead(address, txPhy, rxPhy, status); 2358 } 2359 onServerConnUpdate(int connId, int interval, int latency, int timeout, int status)2360 void onServerConnUpdate(int connId, int interval, int latency, int timeout, int status) 2361 throws RemoteException { 2362 if (DBG) { 2363 Log.d(TAG, "onServerConnUpdate() - connId=" + connId + ", status=" + status); 2364 } 2365 2366 String address = mServerMap.addressByConnId(connId); 2367 if (address == null) { 2368 return; 2369 } 2370 2371 ServerMap.App app = mServerMap.getByConnId(connId); 2372 if (app == null) { 2373 return; 2374 } 2375 2376 app.callback.onConnectionUpdated(address, interval, latency, timeout, status); 2377 } 2378 onServerSubrateChange(int connId, int subrateFactor, int latency, int contNum, int timeout, int status)2379 void onServerSubrateChange(int connId, int subrateFactor, int latency, int contNum, 2380 int timeout, int status) 2381 throws RemoteException { 2382 if (DBG) { 2383 Log.d(TAG, "onServerSubrateChange() - connId=" + connId + ", status=" + status); 2384 } 2385 2386 String address = mServerMap.addressByConnId(connId); 2387 if (address == null) { 2388 return; 2389 } 2390 2391 ServerMap.App app = mServerMap.getByConnId(connId); 2392 if (app == null) { 2393 return; 2394 } 2395 2396 app.callback.onSubrateChange(address, subrateFactor, latency, contNum, timeout, status); 2397 } 2398 onSearchCompleted(int connId, int status)2399 void onSearchCompleted(int connId, int status) throws RemoteException { 2400 if (DBG) { 2401 Log.d(TAG, "onSearchCompleted() - connId=" + connId + ", status=" + status); 2402 } 2403 // Gatt DB is ready! 2404 2405 // This callback was called from the jni_workqueue thread. If we make request to the stack 2406 // on the same thread, it might cause deadlock. Schedule request on a new thread instead. 2407 Thread t = new Thread(new Runnable() { 2408 @Override 2409 public void run() { 2410 mNativeInterface.gattClientGetGattDb(connId); 2411 } 2412 }); 2413 t.start(); 2414 } 2415 getSampleGattDbElement()2416 GattDbElement getSampleGattDbElement() { 2417 return new GattDbElement(); 2418 } 2419 onGetGattDb(int connId, ArrayList<GattDbElement> db)2420 void onGetGattDb(int connId, ArrayList<GattDbElement> db) throws RemoteException { 2421 String address = mClientMap.addressByConnId(connId); 2422 2423 if (DBG) { 2424 Log.d(TAG, "onGetGattDb() - address=" + address); 2425 } 2426 2427 ClientMap.App app = mClientMap.getByConnId(connId); 2428 if (app == null || app.callback == null) { 2429 Log.e(TAG, "app or callback is null"); 2430 return; 2431 } 2432 2433 List<BluetoothGattService> dbOut = new ArrayList<BluetoothGattService>(); 2434 Set<Integer> restrictedIds = new HashSet<>(); 2435 2436 BluetoothGattService currSrvc = null; 2437 BluetoothGattCharacteristic currChar = null; 2438 boolean isRestrictedSrvc = false; 2439 boolean isHidSrvc = false; 2440 boolean isRestrictedChar = false; 2441 2442 for (GattDbElement el : db) { 2443 switch (el.type) { 2444 case GattDbElement.TYPE_PRIMARY_SERVICE: 2445 case GattDbElement.TYPE_SECONDARY_SERVICE: 2446 if (DBG) { 2447 Log.d(TAG, "got service with UUID=" + el.uuid + " id: " + el.id); 2448 } 2449 2450 currSrvc = new BluetoothGattService(el.uuid, el.id, el.type); 2451 dbOut.add(currSrvc); 2452 isRestrictedSrvc = isRestrictedSrvcUuid(el.uuid); 2453 isHidSrvc = isHidSrvcUuid(el.uuid); 2454 if (isRestrictedSrvc) { 2455 restrictedIds.add(el.id); 2456 } 2457 break; 2458 2459 case GattDbElement.TYPE_CHARACTERISTIC: 2460 if (DBG) { 2461 Log.d(TAG, "got characteristic with UUID=" + el.uuid + " id: " + el.id); 2462 } 2463 2464 currChar = new BluetoothGattCharacteristic(el.uuid, el.id, el.properties, 0); 2465 currSrvc.addCharacteristic(currChar); 2466 isRestrictedChar = isRestrictedSrvc || (isHidSrvc && isHidCharUuid(el.uuid)); 2467 if (isRestrictedChar) { 2468 restrictedIds.add(el.id); 2469 } 2470 break; 2471 2472 case GattDbElement.TYPE_DESCRIPTOR: 2473 if (DBG) { 2474 Log.d(TAG, "got descriptor with UUID=" + el.uuid + " id: " + el.id); 2475 } 2476 2477 currChar.addDescriptor(new BluetoothGattDescriptor(el.uuid, el.id, 0)); 2478 if (isRestrictedChar) { 2479 restrictedIds.add(el.id); 2480 } 2481 break; 2482 2483 case GattDbElement.TYPE_INCLUDED_SERVICE: 2484 if (DBG) { 2485 Log.d(TAG, "got included service with UUID=" + el.uuid + " id: " + el.id 2486 + " startHandle: " + el.startHandle); 2487 } 2488 2489 currSrvc.addIncludedService( 2490 new BluetoothGattService(el.uuid, el.startHandle, el.type)); 2491 break; 2492 2493 default: 2494 Log.e(TAG, "got unknown element with type=" + el.type + " and UUID=" + el.uuid 2495 + " id: " + el.id); 2496 } 2497 } 2498 2499 if (!restrictedIds.isEmpty()) { 2500 mRestrictedHandles.put(connId, restrictedIds); 2501 } 2502 // Search is complete when there was error, or nothing more to process 2503 app.callback.onSearchComplete(address, dbOut, 0 /* status */); 2504 } 2505 onRegisterForNotifications(int connId, int status, int registered, int handle)2506 void onRegisterForNotifications(int connId, int status, int registered, int handle) { 2507 String address = mClientMap.addressByConnId(connId); 2508 2509 if (DBG) { 2510 Log.d(TAG, "onRegisterForNotifications() - address=" + address + ", status=" + status 2511 + ", registered=" + registered + ", handle=" + handle); 2512 } 2513 } 2514 onNotify(int connId, String address, int handle, boolean isNotify, byte[] data)2515 void onNotify(int connId, String address, int handle, boolean isNotify, byte[] data) 2516 throws RemoteException { 2517 2518 if (VDBG) { 2519 Log.d(TAG, "onNotify() - address=" + address + ", handle=" + handle + ", length=" 2520 + data.length); 2521 } 2522 2523 ClientMap.App app = mClientMap.getByConnId(connId); 2524 if (app != null) { 2525 try { 2526 permissionCheck(connId, handle); 2527 } catch (SecurityException ex) { 2528 // Only throws on apps with target SDK T+ as this old API did not throw prior to T 2529 if (checkCallerTargetSdk(this, app.name, Build.VERSION_CODES.TIRAMISU)) { 2530 throw ex; 2531 } 2532 Log.w(TAG, "onNotify() - permission check failed!"); 2533 return; 2534 } 2535 app.callback.onNotify(address, handle, data); 2536 } 2537 } 2538 onReadCharacteristic(int connId, int status, int handle, byte[] data)2539 void onReadCharacteristic(int connId, int status, int handle, byte[] data) 2540 throws RemoteException { 2541 String address = mClientMap.addressByConnId(connId); 2542 2543 if (VDBG) { 2544 Log.d(TAG, "onReadCharacteristic() - address=" + address + ", status=" + status 2545 + ", length=" + data.length); 2546 } 2547 2548 ClientMap.App app = mClientMap.getByConnId(connId); 2549 if (app != null) { 2550 app.callback.onCharacteristicRead(address, status, handle, data); 2551 } 2552 } 2553 onWriteCharacteristic(int connId, int status, int handle, byte[] data)2554 void onWriteCharacteristic(int connId, int status, int handle, byte[] data) 2555 throws RemoteException { 2556 String address = mClientMap.addressByConnId(connId); 2557 synchronized (mPermits) { 2558 Log.d(TAG, "onWriteCharacteristic() - increasing permit for address=" 2559 + address); 2560 mPermits.put(address, -1); 2561 } 2562 2563 if (VDBG) { 2564 Log.d(TAG, "onWriteCharacteristic() - address=" + address + ", status=" + status 2565 + ", length=" + data.length); 2566 } 2567 2568 ClientMap.App app = mClientMap.getByConnId(connId); 2569 if (app == null) { 2570 return; 2571 } 2572 2573 if (!app.isCongested) { 2574 app.callback.onCharacteristicWrite(address, status, handle, data); 2575 } else { 2576 if (status == BluetoothGatt.GATT_CONNECTION_CONGESTED) { 2577 status = BluetoothGatt.GATT_SUCCESS; 2578 } 2579 CallbackInfo callbackInfo = new CallbackInfo.Builder(address, status) 2580 .setHandle(handle) 2581 .setValue(data) 2582 .build(); 2583 app.queueCallback(callbackInfo); 2584 } 2585 } 2586 onExecuteCompleted(int connId, int status)2587 void onExecuteCompleted(int connId, int status) throws RemoteException { 2588 String address = mClientMap.addressByConnId(connId); 2589 if (VDBG) { 2590 Log.d(TAG, "onExecuteCompleted() - address=" + address + ", status=" + status); 2591 } 2592 2593 ClientMap.App app = mClientMap.getByConnId(connId); 2594 if (app != null) { 2595 app.callback.onExecuteWrite(address, status); 2596 } 2597 } 2598 onReadDescriptor(int connId, int status, int handle, byte[] data)2599 void onReadDescriptor(int connId, int status, int handle, byte[] data) throws RemoteException { 2600 String address = mClientMap.addressByConnId(connId); 2601 2602 if (VDBG) { 2603 Log.d(TAG, 2604 "onReadDescriptor() - address=" + address + ", status=" + status + ", length=" 2605 + data.length); 2606 } 2607 2608 ClientMap.App app = mClientMap.getByConnId(connId); 2609 if (app != null) { 2610 app.callback.onDescriptorRead(address, status, handle, data); 2611 } 2612 } 2613 onWriteDescriptor(int connId, int status, int handle, byte[] data)2614 void onWriteDescriptor(int connId, int status, int handle, byte[] data) 2615 throws RemoteException { 2616 String address = mClientMap.addressByConnId(connId); 2617 2618 if (VDBG) { 2619 Log.d(TAG, "onWriteDescriptor() - address=" + address + ", status=" + status 2620 + ", length=" + data.length); 2621 } 2622 2623 ClientMap.App app = mClientMap.getByConnId(connId); 2624 if (app != null) { 2625 app.callback.onDescriptorWrite(address, status, handle, data); 2626 } 2627 } 2628 onReadRemoteRssi(int clientIf, String address, int rssi, int status)2629 void onReadRemoteRssi(int clientIf, String address, int rssi, int status) 2630 throws RemoteException { 2631 if (DBG) { 2632 Log.d(TAG, 2633 "onReadRemoteRssi() - clientIf=" + clientIf + " address=" + address + ", rssi=" 2634 + rssi + ", status=" + status); 2635 } 2636 2637 ClientMap.App app = mClientMap.getById(clientIf); 2638 if (app != null) { 2639 app.callback.onReadRemoteRssi(address, rssi, status); 2640 } 2641 } 2642 onScanFilterEnableDisabled(int action, int status, int clientIf)2643 void onScanFilterEnableDisabled(int action, int status, int clientIf) { 2644 if (DBG) { 2645 Log.d(TAG, "onScanFilterEnableDisabled() - clientIf=" + clientIf + ", status=" + status 2646 + ", action=" + action); 2647 } 2648 mScanManager.callbackDone(clientIf, status); 2649 } 2650 onScanFilterParamsConfigured(int action, int status, int clientIf, int availableSpace)2651 void onScanFilterParamsConfigured(int action, int status, int clientIf, int availableSpace) { 2652 if (DBG) { 2653 Log.d(TAG, 2654 "onScanFilterParamsConfigured() - clientIf=" + clientIf + ", status=" + status 2655 + ", action=" + action + ", availableSpace=" + availableSpace); 2656 } 2657 mScanManager.callbackDone(clientIf, status); 2658 } 2659 onScanFilterConfig(int action, int status, int clientIf, int filterType, int availableSpace)2660 void onScanFilterConfig(int action, int status, int clientIf, int filterType, 2661 int availableSpace) { 2662 if (DBG) { 2663 Log.d(TAG, "onScanFilterConfig() - clientIf=" + clientIf + ", action = " + action 2664 + " status = " + status + ", filterType=" + filterType + ", availableSpace=" 2665 + availableSpace); 2666 } 2667 2668 mScanManager.callbackDone(clientIf, status); 2669 } 2670 onBatchScanStorageConfigured(int status, int clientIf)2671 void onBatchScanStorageConfigured(int status, int clientIf) { 2672 if (DBG) { 2673 Log.d(TAG, 2674 "onBatchScanStorageConfigured() - clientIf=" + clientIf + ", status=" + status); 2675 } 2676 mScanManager.callbackDone(clientIf, status); 2677 } 2678 2679 // TODO: split into two different callbacks : onBatchScanStarted and onBatchScanStopped. onBatchScanStartStopped(int startStopAction, int status, int clientIf)2680 void onBatchScanStartStopped(int startStopAction, int status, int clientIf) { 2681 if (DBG) { 2682 Log.d(TAG, "onBatchScanStartStopped() - clientIf=" + clientIf + ", status=" + status 2683 + ", startStopAction=" + startStopAction); 2684 } 2685 mScanManager.callbackDone(clientIf, status); 2686 } 2687 findBatchScanClientById(int scannerId)2688 ScanClient findBatchScanClientById(int scannerId) { 2689 for (ScanClient client : mScanManager.getBatchScanQueue()) { 2690 if (client.scannerId == scannerId) { 2691 return client; 2692 } 2693 } 2694 return null; 2695 } 2696 onBatchScanReports(int status, int scannerId, int reportType, int numRecords, byte[] recordData)2697 void onBatchScanReports(int status, int scannerId, int reportType, int numRecords, 2698 byte[] recordData) throws RemoteException { 2699 // When in testing mode, ignore all real-world events 2700 if (isTestModeEnabled()) return; 2701 2702 onBatchScanReportsInternal(status, scannerId, reportType, numRecords, recordData); 2703 } 2704 onBatchScanReportsInternal(int status, int scannerId, int reportType, int numRecords, byte[] recordData)2705 void onBatchScanReportsInternal(int status, int scannerId, int reportType, int numRecords, 2706 byte[] recordData) throws RemoteException { 2707 if (DBG) { 2708 Log.d(TAG, "onBatchScanReports() - scannerId=" + scannerId + ", status=" + status 2709 + ", reportType=" + reportType + ", numRecords=" + numRecords); 2710 } 2711 2712 Set<ScanResult> results = parseBatchScanResults(numRecords, reportType, recordData); 2713 if (reportType == ScanManager.SCAN_RESULT_TYPE_TRUNCATED) { 2714 // We only support single client for truncated mode. 2715 ScannerMap.App app = mScannerMap.getById(scannerId); 2716 if (app == null) { 2717 return; 2718 } 2719 2720 ScanClient client = findBatchScanClientById(scannerId); 2721 if (client == null) { 2722 return; 2723 } 2724 2725 ArrayList<ScanResult> permittedResults; 2726 if (hasScanResultPermission(client)) { 2727 permittedResults = new ArrayList<ScanResult>(results); 2728 } else { 2729 permittedResults = new ArrayList<ScanResult>(); 2730 for (ScanResult scanResult : results) { 2731 for (String associatedDevice : client.associatedDevices) { 2732 if (associatedDevice.equalsIgnoreCase(scanResult.getDevice() 2733 .getAddress())) { 2734 permittedResults.add(scanResult); 2735 } 2736 } 2737 } 2738 if (permittedResults.isEmpty()) { 2739 return; 2740 } 2741 } 2742 2743 if (client.hasDisavowedLocation) { 2744 permittedResults.removeIf(mLocationDenylistPredicate); 2745 } 2746 2747 if (app.callback != null) { 2748 app.callback.onBatchScanResults(permittedResults); 2749 } else { 2750 // PendingIntent based 2751 try { 2752 sendResultsByPendingIntent(app.info, permittedResults, 2753 ScanSettings.CALLBACK_TYPE_ALL_MATCHES); 2754 } catch (PendingIntent.CanceledException e) { 2755 } 2756 } 2757 } else { 2758 for (ScanClient client : mScanManager.getFullBatchScanQueue()) { 2759 // Deliver results for each client. 2760 deliverBatchScan(client, results); 2761 } 2762 } 2763 mScanManager.callbackDone(scannerId, status); 2764 } 2765 sendBatchScanResults(ScannerMap.App app, ScanClient client, ArrayList<ScanResult> results)2766 private void sendBatchScanResults(ScannerMap.App app, ScanClient client, 2767 ArrayList<ScanResult> results) { 2768 try { 2769 if (app.callback != null) { 2770 if (mScanManager.isAutoBatchScanClientEnabled(client)) { 2771 if (DBG) { 2772 Log.d(TAG, "sendBatchScanResults() to onScanResult()" + client); 2773 } 2774 for (ScanResult result : results) { 2775 app.appScanStats.addResult(client.scannerId); 2776 app.callback.onScanResult(result); 2777 } 2778 } else { 2779 if (DBG) { 2780 Log.d(TAG, "sendBatchScanResults() to onBatchScanResults()" + client); 2781 } 2782 app.callback.onBatchScanResults(results); 2783 } 2784 } else { 2785 sendResultsByPendingIntent(app.info, results, 2786 ScanSettings.CALLBACK_TYPE_ALL_MATCHES); 2787 } 2788 } catch (RemoteException | PendingIntent.CanceledException e) { 2789 Log.e(TAG, "Exception: " + e); 2790 mScannerMap.remove(client.scannerId); 2791 mScanManager.stopScan(client.scannerId); 2792 } 2793 } 2794 2795 // Check and deliver scan results for different scan clients. deliverBatchScan(ScanClient client, Set<ScanResult> allResults)2796 private void deliverBatchScan(ScanClient client, Set<ScanResult> allResults) 2797 throws RemoteException { 2798 ScannerMap.App app = mScannerMap.getById(client.scannerId); 2799 if (app == null) { 2800 return; 2801 } 2802 2803 ArrayList<ScanResult> permittedResults; 2804 if (hasScanResultPermission(client)) { 2805 permittedResults = new ArrayList<ScanResult>(allResults); 2806 } else { 2807 permittedResults = new ArrayList<ScanResult>(); 2808 for (ScanResult scanResult : allResults) { 2809 for (String associatedDevice : client.associatedDevices) { 2810 if (associatedDevice.equalsIgnoreCase(scanResult.getDevice().getAddress())) { 2811 permittedResults.add(scanResult); 2812 } 2813 } 2814 } 2815 if (permittedResults.isEmpty()) { 2816 return; 2817 } 2818 } 2819 2820 if (client.filters == null || client.filters.isEmpty()) { 2821 sendBatchScanResults(app, client, permittedResults); 2822 // TODO: Question to reviewer: Shouldn't there be a return here? 2823 } 2824 // Reconstruct the scan results. 2825 ArrayList<ScanResult> results = new ArrayList<ScanResult>(); 2826 for (ScanResult scanResult : permittedResults) { 2827 if (matchesFilters(client, scanResult).getMatches()) { 2828 results.add(scanResult); 2829 } 2830 } 2831 sendBatchScanResults(app, client, results); 2832 } 2833 parseBatchScanResults(int numRecords, int reportType, byte[] batchRecord)2834 private Set<ScanResult> parseBatchScanResults(int numRecords, int reportType, 2835 byte[] batchRecord) { 2836 if (numRecords == 0) { 2837 return Collections.emptySet(); 2838 } 2839 if (DBG) { 2840 Log.d(TAG, "current time is " + SystemClock.elapsedRealtimeNanos()); 2841 } 2842 if (reportType == ScanManager.SCAN_RESULT_TYPE_TRUNCATED) { 2843 return parseTruncatedResults(numRecords, batchRecord); 2844 } else { 2845 return parseFullResults(numRecords, batchRecord); 2846 } 2847 } 2848 parseTruncatedResults(int numRecords, byte[] batchRecord)2849 private Set<ScanResult> parseTruncatedResults(int numRecords, byte[] batchRecord) { 2850 if (DBG) { 2851 Log.d(TAG, "batch record " + Arrays.toString(batchRecord)); 2852 } 2853 Set<ScanResult> results = new HashSet<ScanResult>(numRecords); 2854 long now = SystemClock.elapsedRealtimeNanos(); 2855 for (int i = 0; i < numRecords; ++i) { 2856 byte[] record = 2857 extractBytes(batchRecord, i * TRUNCATED_RESULT_SIZE, TRUNCATED_RESULT_SIZE); 2858 byte[] address = extractBytes(record, 0, 6); 2859 reverse(address); 2860 BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address); 2861 int rssi = record[8]; 2862 long timestampNanos = now - parseTimestampNanos(extractBytes(record, 9, 2)); 2863 results.add(new ScanResult(device, ScanRecord.parseFromBytes(new byte[0]), rssi, 2864 timestampNanos)); 2865 } 2866 return results; 2867 } 2868 2869 @VisibleForTesting parseTimestampNanos(byte[] data)2870 long parseTimestampNanos(byte[] data) { 2871 long timestampUnit = NumberUtils.littleEndianByteArrayToInt(data); 2872 // Timestamp is in every 50 ms. 2873 return TimeUnit.MILLISECONDS.toNanos(timestampUnit * 50); 2874 } 2875 parseFullResults(int numRecords, byte[] batchRecord)2876 private Set<ScanResult> parseFullResults(int numRecords, byte[] batchRecord) { 2877 if (DBG) { 2878 Log.d(TAG, "Batch record : " + Arrays.toString(batchRecord)); 2879 } 2880 Set<ScanResult> results = new HashSet<ScanResult>(numRecords); 2881 int position = 0; 2882 long now = SystemClock.elapsedRealtimeNanos(); 2883 while (position < batchRecord.length) { 2884 byte[] address = extractBytes(batchRecord, position, 6); 2885 // TODO: remove temp hack. 2886 reverse(address); 2887 BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address); 2888 position += 6; 2889 // Skip address type. 2890 position++; 2891 // Skip tx power level. 2892 position++; 2893 int rssi = batchRecord[position++]; 2894 long timestampNanos = now - parseTimestampNanos(extractBytes(batchRecord, position, 2)); 2895 position += 2; 2896 2897 // Combine advertise packet and scan response packet. 2898 int advertisePacketLen = batchRecord[position++]; 2899 byte[] advertiseBytes = extractBytes(batchRecord, position, advertisePacketLen); 2900 position += advertisePacketLen; 2901 int scanResponsePacketLen = batchRecord[position++]; 2902 byte[] scanResponseBytes = extractBytes(batchRecord, position, scanResponsePacketLen); 2903 position += scanResponsePacketLen; 2904 byte[] scanRecord = new byte[advertisePacketLen + scanResponsePacketLen]; 2905 System.arraycopy(advertiseBytes, 0, scanRecord, 0, advertisePacketLen); 2906 System.arraycopy(scanResponseBytes, 0, scanRecord, advertisePacketLen, 2907 scanResponsePacketLen); 2908 if (DBG) { 2909 Log.d(TAG, "ScanRecord : " + Arrays.toString(scanRecord)); 2910 } 2911 results.add(new ScanResult(device, ScanRecord.parseFromBytes(scanRecord), rssi, 2912 timestampNanos)); 2913 } 2914 return results; 2915 } 2916 2917 // Reverse byte array. reverse(byte[] address)2918 private void reverse(byte[] address) { 2919 int len = address.length; 2920 for (int i = 0; i < len / 2; ++i) { 2921 byte b = address[i]; 2922 address[i] = address[len - 1 - i]; 2923 address[len - 1 - i] = b; 2924 } 2925 } 2926 2927 // Helper method to extract bytes from byte array. extractBytes(byte[] scanRecord, int start, int length)2928 private static byte[] extractBytes(byte[] scanRecord, int start, int length) { 2929 byte[] bytes = new byte[length]; 2930 System.arraycopy(scanRecord, start, bytes, 0, length); 2931 return bytes; 2932 } 2933 2934 @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) onBatchScanThresholdCrossed(int clientIf)2935 void onBatchScanThresholdCrossed(int clientIf) { 2936 if (DBG) { 2937 Log.d(TAG, "onBatchScanThresholdCrossed() - clientIf=" + clientIf); 2938 } 2939 flushPendingBatchResults(clientIf, getAttributionSource()); 2940 } 2941 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)2942 AdvtFilterOnFoundOnLostInfo createOnTrackAdvFoundLostObject(int clientIf, int advPktLen, 2943 byte[] advPkt, int scanRspLen, byte[] scanRsp, int filtIndex, int advState, 2944 int advInfoPresent, String address, int addrType, int txPower, int rssiValue, 2945 int timeStamp) { 2946 2947 return new AdvtFilterOnFoundOnLostInfo(clientIf, advPktLen, advPkt, scanRspLen, scanRsp, 2948 filtIndex, advState, advInfoPresent, address, addrType, txPower, rssiValue, 2949 timeStamp); 2950 } 2951 onTrackAdvFoundLost(AdvtFilterOnFoundOnLostInfo trackingInfo)2952 void onTrackAdvFoundLost(AdvtFilterOnFoundOnLostInfo trackingInfo) throws RemoteException { 2953 if (DBG) { 2954 Log.d(TAG, "onTrackAdvFoundLost() - scannerId= " + trackingInfo.getClientIf() 2955 + " address = " + trackingInfo.getAddress() + " adv_state = " 2956 + trackingInfo.getAdvState()); 2957 } 2958 2959 ScannerMap.App app = mScannerMap.getById(trackingInfo.getClientIf()); 2960 if (app == null || (app.callback == null && app.info == null)) { 2961 Log.e(TAG, "app or callback is null"); 2962 return; 2963 } 2964 2965 BluetoothDevice device = BluetoothAdapter.getDefaultAdapter() 2966 .getRemoteDevice(trackingInfo.getAddress()); 2967 int advertiserState = trackingInfo.getAdvState(); 2968 ScanResult result = 2969 new ScanResult(device, ScanRecord.parseFromBytes(trackingInfo.getResult()), 2970 trackingInfo.getRSSIValue(), SystemClock.elapsedRealtimeNanos()); 2971 2972 for (ScanClient client : mScanManager.getRegularScanQueue()) { 2973 if (client.scannerId == trackingInfo.getClientIf()) { 2974 ScanSettings settings = client.settings; 2975 if ((advertiserState == ADVT_STATE_ONFOUND) && ( 2976 (settings.getCallbackType() & ScanSettings.CALLBACK_TYPE_FIRST_MATCH) 2977 != 0)) { 2978 if (app.callback != null) { 2979 app.callback.onFoundOrLost(true, result); 2980 } else { 2981 sendResultByPendingIntent(app.info, result, 2982 ScanSettings.CALLBACK_TYPE_FIRST_MATCH, client); 2983 } 2984 } else if ((advertiserState == ADVT_STATE_ONLOST) && ( 2985 (settings.getCallbackType() & ScanSettings.CALLBACK_TYPE_MATCH_LOST) 2986 != 0)) { 2987 if (app.callback != null) { 2988 app.callback.onFoundOrLost(false, result); 2989 } else { 2990 sendResultByPendingIntent(app.info, result, 2991 ScanSettings.CALLBACK_TYPE_MATCH_LOST, client); 2992 } 2993 } else { 2994 if (DBG) { 2995 Log.d(TAG, "Not reporting onlost/onfound : " + advertiserState 2996 + " scannerId = " + client.scannerId + " callbackType " 2997 + settings.getCallbackType()); 2998 } 2999 } 3000 } 3001 } 3002 } 3003 onScanParamSetupCompleted(int status, int scannerId)3004 void onScanParamSetupCompleted(int status, int scannerId) throws RemoteException { 3005 ScannerMap.App app = mScannerMap.getById(scannerId); 3006 if (app == null || app.callback == null) { 3007 Log.e(TAG, "Advertise app or callback is null"); 3008 return; 3009 } 3010 if (DBG) { 3011 Log.d(TAG, "onScanParamSetupCompleted : " + status); 3012 } 3013 } 3014 3015 // callback from ScanManager for dispatch of errors apps. onScanManagerErrorCallback(int scannerId, int errorCode)3016 void onScanManagerErrorCallback(int scannerId, int errorCode) throws RemoteException { 3017 ScannerMap.App app = mScannerMap.getById(scannerId); 3018 if (app == null || (app.callback == null && app.info == null)) { 3019 Log.e(TAG, "App or callback is null"); 3020 return; 3021 } 3022 if (app.callback != null) { 3023 app.callback.onScanManagerErrorCallback(errorCode); 3024 } else { 3025 try { 3026 sendErrorByPendingIntent(app.info, errorCode); 3027 } catch (PendingIntent.CanceledException e) { 3028 Log.e(TAG, "Error sending error code via PendingIntent:" + e); 3029 } 3030 } 3031 } 3032 onConfigureMTU(int connId, int status, int mtu)3033 void onConfigureMTU(int connId, int status, int mtu) throws RemoteException { 3034 String address = mClientMap.addressByConnId(connId); 3035 3036 if (DBG) { 3037 Log.d(TAG, 3038 "onConfigureMTU() address=" + address + ", status=" + status + ", mtu=" + mtu); 3039 } 3040 3041 ClientMap.App app = mClientMap.getByConnId(connId); 3042 if (app != null) { 3043 app.callback.onConfigureMTU(address, mtu, status); 3044 } 3045 } 3046 onClientCongestion(int connId, boolean congested)3047 void onClientCongestion(int connId, boolean congested) throws RemoteException { 3048 if (VDBG) { 3049 Log.d(TAG, "onClientCongestion() - connId=" + connId + ", congested=" + congested); 3050 } 3051 3052 ClientMap.App app = mClientMap.getByConnId(connId); 3053 3054 if (app != null) { 3055 app.isCongested = congested; 3056 while (!app.isCongested) { 3057 CallbackInfo callbackInfo = app.popQueuedCallback(); 3058 if (callbackInfo == null) { 3059 return; 3060 } 3061 app.callback.onCharacteristicWrite(callbackInfo.address, callbackInfo.status, 3062 callbackInfo.handle, callbackInfo.value); 3063 } 3064 } 3065 } 3066 3067 /************************************************************************** 3068 * GATT Service functions - Shared CLIENT/SERVER 3069 *************************************************************************/ 3070 3071 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) getDevicesMatchingConnectionStates( int[] states, AttributionSource attributionSource)3072 List<BluetoothDevice> getDevicesMatchingConnectionStates( 3073 int[] states, AttributionSource attributionSource) { 3074 if (!Utils.checkConnectPermissionForDataDelivery( 3075 this, attributionSource, 3076 "GattService getDevicesMatchingConnectionStates")) { 3077 return new ArrayList<>(0); 3078 } 3079 3080 Map<BluetoothDevice, Integer> deviceStates = new HashMap<BluetoothDevice, Integer>(); 3081 3082 // Add paired LE devices 3083 3084 BluetoothDevice[] bondedDevices = mAdapterService.getBondedDevices(); 3085 for (BluetoothDevice device : bondedDevices) { 3086 if (getDeviceType(device) != AbstractionLayer.BT_DEVICE_TYPE_BREDR) { 3087 deviceStates.put(device, BluetoothProfile.STATE_DISCONNECTED); 3088 } 3089 } 3090 3091 // Add connected deviceStates 3092 3093 Set<String> connectedDevices = new HashSet<String>(); 3094 connectedDevices.addAll(mClientMap.getConnectedDevices()); 3095 connectedDevices.addAll(mServerMap.getConnectedDevices()); 3096 3097 for (String address : connectedDevices) { 3098 BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address); 3099 if (device != null) { 3100 deviceStates.put(device, BluetoothProfile.STATE_CONNECTED); 3101 } 3102 } 3103 3104 // Create matching device sub-set 3105 3106 List<BluetoothDevice> deviceList = new ArrayList<BluetoothDevice>(); 3107 3108 for (Map.Entry<BluetoothDevice, Integer> entry : deviceStates.entrySet()) { 3109 for (int state : states) { 3110 if (entry.getValue() == state) { 3111 deviceList.add(entry.getKey()); 3112 } 3113 } 3114 } 3115 3116 return deviceList; 3117 } 3118 3119 @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) registerScanner(IScannerCallback callback, WorkSource workSource, AttributionSource attributionSource)3120 void registerScanner(IScannerCallback callback, WorkSource workSource, 3121 AttributionSource attributionSource) throws RemoteException { 3122 if (!Utils.checkScanPermissionForDataDelivery( 3123 this, attributionSource, "GattService registerScanner")) { 3124 return; 3125 } 3126 3127 UUID uuid = UUID.randomUUID(); 3128 if (DBG) { 3129 Log.d(TAG, "registerScanner() - UUID=" + uuid); 3130 } 3131 3132 enforceImpersonatationPermissionIfNeeded(workSource); 3133 3134 AppScanStats app = mScannerMap.getAppScanStatsByUid(Binder.getCallingUid()); 3135 if (app != null && app.isScanningTooFrequently() 3136 && !Utils.checkCallerHasPrivilegedPermission(this)) { 3137 Log.e(TAG, "App '" + app.appName + "' is scanning too frequently"); 3138 callback.onScannerRegistered(ScanCallback.SCAN_FAILED_SCANNING_TOO_FREQUENTLY, -1); 3139 return; 3140 } 3141 3142 mScannerMap.add(uuid, workSource, callback, null, this); 3143 mScanManager.registerScanner(uuid); 3144 } 3145 3146 @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) unregisterScanner(int scannerId, AttributionSource attributionSource)3147 void unregisterScanner(int scannerId, AttributionSource attributionSource) { 3148 if (!Utils.checkScanPermissionForDataDelivery( 3149 this, attributionSource, "GattService unregisterScanner")) { 3150 return; 3151 } 3152 3153 if (DBG) { 3154 Log.d(TAG, "unregisterScanner() - scannerId=" + scannerId); 3155 } 3156 mScannerMap.remove(scannerId); 3157 mScanManager.unregisterScanner(scannerId); 3158 } 3159 getAssociatedDevices(String callingPackage)3160 private List<String> getAssociatedDevices(String callingPackage) { 3161 if (mCompanionManager == null) { 3162 return Collections.emptyList(); 3163 } 3164 3165 List<String> macAddresses = new ArrayList(); 3166 3167 final long identity = Binder.clearCallingIdentity(); 3168 try { 3169 for (AssociationInfo info : Utils.getCdmAssociations(mCompanionManager)) { 3170 if (info.getPackageName().equals(callingPackage) && !info.isSelfManaged() 3171 && info.getDeviceMacAddress() != null) { 3172 macAddresses.add(info.getDeviceMacAddress().toString()); 3173 } 3174 } 3175 } catch (SecurityException se) { 3176 // Not an app with associated devices 3177 } catch (Exception e) { 3178 Log.e(TAG, "Cannot check device associations for " + callingPackage, e); 3179 } finally { 3180 Binder.restoreCallingIdentity(identity); 3181 } 3182 return macAddresses; 3183 } 3184 3185 @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) startScan(int scannerId, ScanSettings settings, List<ScanFilter> filters, AttributionSource attributionSource)3186 void startScan(int scannerId, ScanSettings settings, List<ScanFilter> filters, 3187 AttributionSource attributionSource) { 3188 if (DBG) { 3189 Log.d(TAG, "start scan with filters"); 3190 } 3191 3192 if (!Utils.checkScanPermissionForDataDelivery( 3193 this, attributionSource, "Starting GATT scan.")) { 3194 return; 3195 } 3196 3197 enforcePrivilegedPermissionIfNeeded(settings); 3198 String callingPackage = attributionSource.getPackageName(); 3199 settings = enforceReportDelayFloor(settings); 3200 enforcePrivilegedPermissionIfNeeded(filters); 3201 final ScanClient scanClient = new ScanClient(scannerId, settings, filters); 3202 scanClient.userHandle = Binder.getCallingUserHandle(); 3203 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); 3204 scanClient.eligibleForSanitizedExposureNotification = 3205 callingPackage.equals(mExposureNotificationPackage); 3206 3207 scanClient.hasDisavowedLocation = 3208 Utils.hasDisavowedLocationForScan(this, attributionSource, isTestModeEnabled()); 3209 3210 scanClient.isQApp = checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.Q); 3211 if (!scanClient.hasDisavowedLocation) { 3212 if (scanClient.isQApp) { 3213 scanClient.hasLocationPermission = Utils.checkCallerHasFineLocation( 3214 this, attributionSource, scanClient.userHandle); 3215 } else { 3216 scanClient.hasLocationPermission = Utils.checkCallerHasCoarseOrFineLocation( 3217 this, attributionSource, scanClient.userHandle); 3218 } 3219 } 3220 scanClient.hasNetworkSettingsPermission = 3221 Utils.checkCallerHasNetworkSettingsPermission(this); 3222 scanClient.hasNetworkSetupWizardPermission = 3223 Utils.checkCallerHasNetworkSetupWizardPermission(this); 3224 scanClient.hasScanWithoutLocationPermission = 3225 Utils.checkCallerHasScanWithoutLocationPermission(this); 3226 scanClient.associatedDevices = getAssociatedDevices(callingPackage); 3227 3228 AppScanStats app = mScannerMap.getAppScanStatsById(scannerId); 3229 ScannerMap.App cbApp = mScannerMap.getById(scannerId); 3230 if (app != null) { 3231 scanClient.stats = app; 3232 boolean isFilteredScan = (filters != null) && !filters.isEmpty(); 3233 boolean isCallbackScan = false; 3234 if (cbApp != null) { 3235 isCallbackScan = cbApp.callback != null; 3236 } 3237 app.recordScanStart(settings, filters, isFilteredScan, isCallbackScan, scannerId); 3238 } 3239 3240 mScanManager.startScan(scanClient); 3241 mAdapterService.notifyActivityAttributionInfo(getAttributionSource(), 3242 AdapterService.ACTIVITY_ATTRIBUTION_NO_ACTIVE_DEVICE_ADDRESS); 3243 } 3244 3245 @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) registerPiAndStartScan(PendingIntent pendingIntent, ScanSettings settings, List<ScanFilter> filters, AttributionSource attributionSource)3246 void registerPiAndStartScan(PendingIntent pendingIntent, ScanSettings settings, 3247 List<ScanFilter> filters, AttributionSource attributionSource) { 3248 if (DBG) { 3249 Log.d(TAG, "start scan with filters, for PendingIntent"); 3250 } 3251 3252 if (!Utils.checkScanPermissionForDataDelivery( 3253 this, attributionSource, "Starting GATT scan.")) { 3254 return; 3255 } 3256 enforcePrivilegedPermissionIfNeeded(settings); 3257 settings = enforceReportDelayFloor(settings); 3258 enforcePrivilegedPermissionIfNeeded(filters); 3259 UUID uuid = UUID.randomUUID(); 3260 if (DBG) { 3261 Log.d(TAG, "startScan(PI) - UUID=" + uuid); 3262 } 3263 String callingPackage = attributionSource.getPackageName(); 3264 PendingIntentInfo piInfo = new PendingIntentInfo(); 3265 piInfo.intent = pendingIntent; 3266 piInfo.settings = settings; 3267 piInfo.filters = filters; 3268 piInfo.callingPackage = callingPackage; 3269 3270 // Don't start scan if the Pi scan already in mScannerMap. 3271 if (mScannerMap.getByContextInfo(piInfo) != null) { 3272 Log.d(TAG, "Don't startScan(PI) since the same Pi scan already in mScannerMap."); 3273 return; 3274 } 3275 3276 ScannerMap.App app = mScannerMap.add(uuid, null, null, piInfo, this); 3277 3278 app.mUserHandle = UserHandle.getUserHandleForUid(Binder.getCallingUid()); 3279 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); 3280 app.mEligibleForSanitizedExposureNotification = 3281 callingPackage.equals(mExposureNotificationPackage); 3282 3283 app.mHasDisavowedLocation = 3284 Utils.hasDisavowedLocationForScan(this, attributionSource, isTestModeEnabled()); 3285 3286 if (!app.mHasDisavowedLocation) { 3287 try { 3288 if (checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.Q)) { 3289 app.hasLocationPermission = Utils.checkCallerHasFineLocation( 3290 this, attributionSource, app.mUserHandle); 3291 } else { 3292 app.hasLocationPermission = Utils.checkCallerHasCoarseOrFineLocation( 3293 this, attributionSource, app.mUserHandle); 3294 } 3295 } catch (SecurityException se) { 3296 // No need to throw here. Just mark as not granted. 3297 app.hasLocationPermission = false; 3298 } 3299 } 3300 app.mHasNetworkSettingsPermission = 3301 Utils.checkCallerHasNetworkSettingsPermission(this); 3302 app.mHasNetworkSetupWizardPermission = 3303 Utils.checkCallerHasNetworkSetupWizardPermission(this); 3304 app.mHasScanWithoutLocationPermission = 3305 Utils.checkCallerHasScanWithoutLocationPermission(this); 3306 app.mAssociatedDevices = getAssociatedDevices(callingPackage); 3307 mScanManager.registerScanner(uuid); 3308 3309 // If this fails, we should stop the scan immediately. 3310 if (!pendingIntent.addCancelListener(Runnable::run, mScanIntentCancelListener)) { 3311 Log.d(TAG, "scanning PendingIntent is already cancelled, stopping scan."); 3312 stopScan(pendingIntent, attributionSource); 3313 } 3314 } 3315 continuePiStartScan(int scannerId, ScannerMap.App app)3316 void continuePiStartScan(int scannerId, ScannerMap.App app) { 3317 final PendingIntentInfo piInfo = app.info; 3318 final ScanClient scanClient = 3319 new ScanClient(scannerId, piInfo.settings, piInfo.filters); 3320 scanClient.hasLocationPermission = app.hasLocationPermission; 3321 scanClient.userHandle = app.mUserHandle; 3322 scanClient.isQApp = checkCallerTargetSdk(this, app.name, Build.VERSION_CODES.Q); 3323 scanClient.eligibleForSanitizedExposureNotification = 3324 app.mEligibleForSanitizedExposureNotification; 3325 scanClient.hasNetworkSettingsPermission = app.mHasNetworkSettingsPermission; 3326 scanClient.hasNetworkSetupWizardPermission = app.mHasNetworkSetupWizardPermission; 3327 scanClient.hasScanWithoutLocationPermission = app.mHasScanWithoutLocationPermission; 3328 scanClient.associatedDevices = app.mAssociatedDevices; 3329 scanClient.hasDisavowedLocation = app.mHasDisavowedLocation; 3330 3331 AppScanStats scanStats = mScannerMap.getAppScanStatsById(scannerId); 3332 if (scanStats != null) { 3333 scanClient.stats = scanStats; 3334 boolean isFilteredScan = (piInfo.filters != null) && !piInfo.filters.isEmpty(); 3335 scanStats.recordScanStart( 3336 piInfo.settings, piInfo.filters, isFilteredScan, false, scannerId); 3337 } 3338 3339 mScanManager.startScan(scanClient); 3340 } 3341 3342 @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) flushPendingBatchResults(int scannerId, AttributionSource attributionSource)3343 void flushPendingBatchResults(int scannerId, AttributionSource attributionSource) { 3344 if (!Utils.checkScanPermissionForDataDelivery( 3345 this, attributionSource, "GattService flushPendingBatchResults")) { 3346 return; 3347 } 3348 if (DBG) { 3349 Log.d(TAG, "flushPendingBatchResults - scannerId=" + scannerId); 3350 } 3351 mScanManager.flushBatchScanResults(new ScanClient(scannerId)); 3352 } 3353 3354 @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) stopScan(int scannerId, AttributionSource attributionSource)3355 void stopScan(int scannerId, AttributionSource attributionSource) { 3356 if (!Utils.checkScanPermissionForDataDelivery( 3357 this, attributionSource, "GattService stopScan")) { 3358 return; 3359 } 3360 int scanQueueSize = 3361 mScanManager.getBatchScanQueue().size() + mScanManager.getRegularScanQueue().size(); 3362 if (DBG) { 3363 Log.d(TAG, "stopScan() - queue size =" + scanQueueSize); 3364 } 3365 3366 AppScanStats app = null; 3367 app = mScannerMap.getAppScanStatsById(scannerId); 3368 if (app != null) { 3369 app.recordScanStop(scannerId); 3370 } 3371 3372 mScanManager.stopScan(scannerId); 3373 mAdapterService.notifyActivityAttributionInfo(getAttributionSource(), 3374 AdapterService.ACTIVITY_ATTRIBUTION_NO_ACTIVE_DEVICE_ADDRESS); 3375 } 3376 3377 @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) stopScan(PendingIntent intent, AttributionSource attributionSource)3378 void stopScan(PendingIntent intent, AttributionSource attributionSource) { 3379 if (!Utils.checkScanPermissionForDataDelivery( 3380 this, attributionSource, "GattService stopScan")) { 3381 return; 3382 } 3383 PendingIntentInfo pii = new PendingIntentInfo(); 3384 pii.intent = intent; 3385 ScannerMap.App app = mScannerMap.getByContextInfo(pii); 3386 if (VDBG) { 3387 Log.d(TAG, "stopScan(PendingIntent): app found = " + app); 3388 } 3389 if (app != null) { 3390 intent.removeCancelListener(mScanIntentCancelListener); 3391 final int scannerId = app.id; 3392 stopScan(scannerId, attributionSource); 3393 // Also unregister the scanner 3394 unregisterScanner(scannerId, attributionSource); 3395 } 3396 } 3397 3398 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) disconnectAll(AttributionSource attributionSource)3399 void disconnectAll(AttributionSource attributionSource) { 3400 if (DBG) { 3401 Log.d(TAG, "disconnectAll()"); 3402 } 3403 Map<Integer, String> connMap = mClientMap.getConnectedMap(); 3404 for (Map.Entry<Integer, String> entry : connMap.entrySet()) { 3405 if (DBG) { 3406 Log.d(TAG, "disconnecting addr:" + entry.getValue()); 3407 } 3408 clientDisconnect(entry.getKey(), entry.getValue(), attributionSource); 3409 //clientDisconnect(int clientIf, String address) 3410 } 3411 } 3412 3413 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) unregAll(AttributionSource attributionSource)3414 void unregAll(AttributionSource attributionSource) { 3415 for (Integer appId : mClientMap.getAllAppsIds()) { 3416 if (DBG) { 3417 Log.d(TAG, "unreg:" + appId); 3418 } 3419 unregisterClient(appId, attributionSource); 3420 } 3421 } 3422 3423 /************************************************************************** 3424 * PERIODIC SCANNING 3425 *************************************************************************/ 3426 @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) registerSync(ScanResult scanResult, int skip, int timeout, IPeriodicAdvertisingCallback callback, AttributionSource attributionSource)3427 void registerSync(ScanResult scanResult, int skip, int timeout, 3428 IPeriodicAdvertisingCallback callback, AttributionSource attributionSource) { 3429 if (!Utils.checkScanPermissionForDataDelivery( 3430 this, attributionSource, "GattService registerSync")) { 3431 return; 3432 } 3433 mPeriodicScanManager.startSync(scanResult, skip, timeout, callback); 3434 } 3435 3436 @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) unregisterSync( IPeriodicAdvertisingCallback callback, AttributionSource attributionSource)3437 void unregisterSync( 3438 IPeriodicAdvertisingCallback callback, AttributionSource attributionSource) { 3439 if (!Utils.checkScanPermissionForDataDelivery( 3440 this, attributionSource, "GattService unregisterSync")) { 3441 return; 3442 } 3443 mPeriodicScanManager.stopSync(callback); 3444 } 3445 transferSync(BluetoothDevice bda, int serviceData, int syncHandle, AttributionSource attributionSource)3446 void transferSync(BluetoothDevice bda, int serviceData, int syncHandle, 3447 AttributionSource attributionSource) { 3448 if (!Utils.checkScanPermissionForDataDelivery( 3449 this, attributionSource, "GattService transferSync")) { 3450 return; 3451 } 3452 mPeriodicScanManager.transferSync(bda, serviceData, syncHandle); 3453 } 3454 transferSetInfo(BluetoothDevice bda, int serviceData, int advHandle, IPeriodicAdvertisingCallback callback, AttributionSource attributionSource)3455 void transferSetInfo(BluetoothDevice bda, int serviceData, 3456 int advHandle, IPeriodicAdvertisingCallback callback, 3457 AttributionSource attributionSource) { 3458 if (!Utils.checkScanPermissionForDataDelivery( 3459 this, attributionSource, "GattService transferSetInfo")) { 3460 return; 3461 } 3462 mPeriodicScanManager.transferSetInfo(bda, serviceData, advHandle, callback); 3463 } 3464 3465 /************************************************************************** 3466 * ADVERTISING SET 3467 *************************************************************************/ 3468 @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) startAdvertisingSet(AdvertisingSetParameters parameters, AdvertiseData advertiseData, AdvertiseData scanResponse, PeriodicAdvertisingParameters periodicParameters, AdvertiseData periodicData, int duration, int maxExtAdvEvents, int serverIf, IAdvertisingSetCallback callback, AttributionSource attributionSource)3469 void startAdvertisingSet(AdvertisingSetParameters parameters, AdvertiseData advertiseData, 3470 AdvertiseData scanResponse, PeriodicAdvertisingParameters periodicParameters, 3471 AdvertiseData periodicData, int duration, int maxExtAdvEvents, int serverIf, 3472 IAdvertisingSetCallback callback, AttributionSource attributionSource) { 3473 if (!Utils.checkAdvertisePermissionForDataDelivery( 3474 this, attributionSource, "GattService startAdvertisingSet")) { 3475 return; 3476 } 3477 if (parameters.getOwnAddressType() != AdvertisingSetParameters.ADDRESS_TYPE_DEFAULT 3478 || serverIf != 0) { 3479 Utils.enforceBluetoothPrivilegedPermission(this); 3480 } 3481 mAdvertiseManager.startAdvertisingSet(parameters, advertiseData, scanResponse, 3482 periodicParameters, periodicData, duration, maxExtAdvEvents, serverIf, callback); 3483 } 3484 3485 @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) stopAdvertisingSet(IAdvertisingSetCallback callback, AttributionSource attributionSource)3486 void stopAdvertisingSet(IAdvertisingSetCallback callback, AttributionSource attributionSource) { 3487 if (!Utils.checkAdvertisePermissionForDataDelivery( 3488 this, attributionSource, "GattService stopAdvertisingSet")) { 3489 return; 3490 } 3491 mAdvertiseManager.stopAdvertisingSet(callback); 3492 } 3493 3494 @RequiresPermission(allOf = { 3495 android.Manifest.permission.BLUETOOTH_ADVERTISE, 3496 android.Manifest.permission.BLUETOOTH_PRIVILEGED, 3497 }) getOwnAddress(int advertiserId, AttributionSource attributionSource)3498 void getOwnAddress(int advertiserId, AttributionSource attributionSource) { 3499 if (!Utils.checkAdvertisePermissionForDataDelivery( 3500 this, attributionSource, "GattService getOwnAddress")) { 3501 return; 3502 } 3503 enforceBluetoothPrivilegedPermission(this); 3504 mAdvertiseManager.getOwnAddress(advertiserId); 3505 } 3506 3507 @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) enableAdvertisingSet(int advertiserId, boolean enable, int duration, int maxExtAdvEvents, AttributionSource attributionSource)3508 void enableAdvertisingSet(int advertiserId, boolean enable, int duration, int maxExtAdvEvents, 3509 AttributionSource attributionSource) { 3510 if (!Utils.checkAdvertisePermissionForDataDelivery( 3511 this, attributionSource, "GattService enableAdvertisingSet")) { 3512 return; 3513 } 3514 mAdvertiseManager.enableAdvertisingSet(advertiserId, enable, duration, maxExtAdvEvents); 3515 } 3516 3517 @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) setAdvertisingData( int advertiserId, AdvertiseData data, AttributionSource attributionSource)3518 void setAdvertisingData( 3519 int advertiserId, AdvertiseData data, AttributionSource attributionSource) { 3520 if (!Utils.checkAdvertisePermissionForDataDelivery( 3521 this, attributionSource, "GattService setAdvertisingData")) { 3522 return; 3523 } 3524 mAdvertiseManager.setAdvertisingData(advertiserId, data); 3525 } 3526 3527 @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) setScanResponseData( int advertiserId, AdvertiseData data, AttributionSource attributionSource)3528 void setScanResponseData( 3529 int advertiserId, AdvertiseData data, AttributionSource attributionSource) { 3530 if (!Utils.checkAdvertisePermissionForDataDelivery( 3531 this, attributionSource, "GattService setScanResponseData")) { 3532 return; 3533 } 3534 mAdvertiseManager.setScanResponseData(advertiserId, data); 3535 } 3536 3537 @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) setAdvertisingParameters(int advertiserId, AdvertisingSetParameters parameters, AttributionSource attributionSource)3538 void setAdvertisingParameters(int advertiserId, AdvertisingSetParameters parameters, 3539 AttributionSource attributionSource) { 3540 if (!Utils.checkAdvertisePermissionForDataDelivery( 3541 this, attributionSource, "GattService setAdvertisingParameters")) { 3542 return; 3543 } 3544 mAdvertiseManager.setAdvertisingParameters(advertiserId, parameters); 3545 } 3546 3547 @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) setPeriodicAdvertisingParameters(int advertiserId, PeriodicAdvertisingParameters parameters, AttributionSource attributionSource)3548 void setPeriodicAdvertisingParameters(int advertiserId, 3549 PeriodicAdvertisingParameters parameters, AttributionSource attributionSource) { 3550 if (!Utils.checkAdvertisePermissionForDataDelivery( 3551 this, attributionSource, "GattService setPeriodicAdvertisingParameters")) { 3552 return; 3553 } 3554 mAdvertiseManager.setPeriodicAdvertisingParameters(advertiserId, parameters); 3555 } 3556 3557 @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) setPeriodicAdvertisingData( int advertiserId, AdvertiseData data, AttributionSource attributionSource)3558 void setPeriodicAdvertisingData( 3559 int advertiserId, AdvertiseData data, AttributionSource attributionSource) { 3560 if (!Utils.checkAdvertisePermissionForDataDelivery( 3561 this, attributionSource, "GattService setPeriodicAdvertisingData")) { 3562 return; 3563 } 3564 mAdvertiseManager.setPeriodicAdvertisingData(advertiserId, data); 3565 } 3566 3567 @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) setPeriodicAdvertisingEnable( int advertiserId, boolean enable, AttributionSource attributionSource)3568 void setPeriodicAdvertisingEnable( 3569 int advertiserId, boolean enable, AttributionSource attributionSource) { 3570 if (!Utils.checkAdvertisePermissionForDataDelivery( 3571 this, attributionSource, "GattService setPeriodicAdvertisingEnable")) { 3572 return; 3573 } 3574 mAdvertiseManager.setPeriodicAdvertisingEnable(advertiserId, enable); 3575 } 3576 3577 /************************************************************************** 3578 * Distance Measurement 3579 *************************************************************************/ 3580 getSupportedDistanceMeasurementMethods()3581 DistanceMeasurementMethod[] getSupportedDistanceMeasurementMethods() { 3582 return mDistanceMeasurementManager.getSupportedDistanceMeasurementMethods(); 3583 } 3584 3585 startDistanceMeasurement(UUID uuid, DistanceMeasurementParams distanceMeasurementParams, IDistanceMeasurementCallback callback)3586 void startDistanceMeasurement(UUID uuid, 3587 DistanceMeasurementParams distanceMeasurementParams, 3588 IDistanceMeasurementCallback callback) { 3589 mDistanceMeasurementManager.startDistanceMeasurement(uuid, distanceMeasurementParams, 3590 callback); 3591 } 3592 stopDistanceMeasurement(UUID uuid, BluetoothDevice device, int method)3593 int stopDistanceMeasurement(UUID uuid, BluetoothDevice device, int method) { 3594 return mDistanceMeasurementManager.stopDistanceMeasurement(uuid, device, method, false); 3595 } 3596 3597 /************************************************************************** 3598 * GATT Service functions - CLIENT 3599 *************************************************************************/ 3600 3601 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) registerClient(UUID uuid, IBluetoothGattCallback callback, boolean eatt_support, AttributionSource attributionSource)3602 void registerClient(UUID uuid, IBluetoothGattCallback callback, boolean eatt_support, 3603 AttributionSource attributionSource) { 3604 if (!Utils.checkConnectPermissionForDataDelivery( 3605 this, attributionSource, "GattService registerClient")) { 3606 return; 3607 } 3608 3609 if (DBG) { 3610 Log.d(TAG, "registerClient() - UUID=" + uuid); 3611 } 3612 mClientMap.add(uuid, null, callback, null, this); 3613 mNativeInterface.gattClientRegisterApp(uuid.getLeastSignificantBits(), 3614 uuid.getMostSignificantBits(), eatt_support); 3615 } 3616 3617 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) unregisterClient(int clientIf, AttributionSource attributionSource)3618 void unregisterClient(int clientIf, AttributionSource attributionSource) { 3619 if (!Utils.checkConnectPermissionForDataDelivery( 3620 this, attributionSource, "GattService unregisterClient")) { 3621 return; 3622 } 3623 3624 if (DBG) { 3625 Log.d(TAG, "unregisterClient() - clientIf=" + clientIf); 3626 } 3627 mClientMap.remove(clientIf); 3628 mNativeInterface.gattClientUnregisterApp(clientIf); 3629 } 3630 3631 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) clientConnect(int clientIf, String address, int addressType, boolean isDirect, int transport, boolean opportunistic, int phy, AttributionSource attributionSource)3632 void clientConnect(int clientIf, String address, int addressType, boolean isDirect, 3633 int transport, boolean opportunistic, int phy, AttributionSource attributionSource) { 3634 if (!Utils.checkConnectPermissionForDataDelivery( 3635 this, attributionSource, "GattService clientConnect")) { 3636 return; 3637 } 3638 3639 if (DBG) { 3640 Log.d(TAG, "clientConnect() - address=" + address + ", addressType=" 3641 + addressType + ", isDirect=" + isDirect + ", opportunistic=" 3642 + opportunistic + ", phy=" + phy); 3643 } 3644 statsLogAppPackage(address, attributionSource.getUid(), clientIf); 3645 if (isDirect) { 3646 MetricsLogger.getInstance().count(BluetoothProtoEnums.GATT_CLIENT_CONNECT_IS_DIRECT, 1); 3647 } else { 3648 MetricsLogger.getInstance().count(BluetoothProtoEnums.GATT_CLIENT_CONNECT_IS_AUTOCONNECT, 1); 3649 } 3650 statsLogGattConnectionStateChange( 3651 BluetoothProfile.GATT, address, clientIf, 3652 BluetoothProtoEnums.CONNECTION_STATE_CONNECTING, -1); 3653 mNativeInterface.gattClientConnect(clientIf, address, addressType, isDirect, transport, 3654 opportunistic, phy); 3655 } 3656 3657 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) clientDisconnect(int clientIf, String address, AttributionSource attributionSource)3658 void clientDisconnect(int clientIf, String address, AttributionSource attributionSource) { 3659 if (!Utils.checkConnectPermissionForDataDelivery( 3660 this, attributionSource, "GattService clientDisconnect")) { 3661 return; 3662 } 3663 3664 Integer connId = mClientMap.connIdByAddress(clientIf, address); 3665 if (DBG) { 3666 Log.d(TAG, "clientDisconnect() - address=" + address + ", connId=" + connId); 3667 } 3668 statsLogGattConnectionStateChange( 3669 BluetoothProfile.GATT, address, clientIf, 3670 BluetoothProtoEnums.CONNECTION_STATE_DISCONNECTING, -1); 3671 mNativeInterface.gattClientDisconnect(clientIf, address, connId != null ? connId : 0); 3672 } 3673 3674 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) clientSetPreferredPhy(int clientIf, String address, int txPhy, int rxPhy, int phyOptions, AttributionSource attributionSource)3675 void clientSetPreferredPhy(int clientIf, String address, int txPhy, int rxPhy, int phyOptions, 3676 AttributionSource attributionSource) { 3677 if (!Utils.checkConnectPermissionForDataDelivery( 3678 this, attributionSource, "GattService clientSetPreferredPhy")) { 3679 return; 3680 } 3681 3682 Integer connId = mClientMap.connIdByAddress(clientIf, address); 3683 if (connId == null) { 3684 if (DBG) { 3685 Log.d(TAG, "clientSetPreferredPhy() - no connection to " + address); 3686 } 3687 return; 3688 } 3689 3690 if (DBG) { 3691 Log.d(TAG, "clientSetPreferredPhy() - address=" + address + ", connId=" + connId); 3692 } 3693 mNativeInterface.gattClientSetPreferredPhy(clientIf, address, txPhy, rxPhy, phyOptions); 3694 } 3695 3696 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) clientReadPhy(int clientIf, String address, AttributionSource attributionSource)3697 void clientReadPhy(int clientIf, String address, AttributionSource attributionSource) { 3698 if (!Utils.checkConnectPermissionForDataDelivery( 3699 this, attributionSource, "GattService clientReadPhy")) { 3700 return; 3701 } 3702 3703 Integer connId = mClientMap.connIdByAddress(clientIf, address); 3704 if (connId == null) { 3705 if (DBG) { 3706 Log.d(TAG, "clientReadPhy() - no connection to " + address); 3707 } 3708 return; 3709 } 3710 3711 if (DBG) { 3712 Log.d(TAG, "clientReadPhy() - address=" + address + ", connId=" + connId); 3713 } 3714 mNativeInterface.gattClientReadPhy(clientIf, address); 3715 } 3716 3717 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) numHwTrackFiltersAvailable(AttributionSource attributionSource)3718 int numHwTrackFiltersAvailable(AttributionSource attributionSource) { 3719 if (!Utils.checkConnectPermissionForDataDelivery( 3720 this, attributionSource, "GattService numHwTrackFiltersAvailable")) { 3721 return 0; 3722 } 3723 return (AdapterService.getAdapterService().getTotalNumOfTrackableAdvertisements() 3724 - mScanManager.getCurrentUsedTrackingAdvertisement()); 3725 } 3726 3727 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) getRegisteredServiceUuids(AttributionSource attributionSource)3728 synchronized List<ParcelUuid> getRegisteredServiceUuids(AttributionSource attributionSource) { 3729 if (!Utils.checkConnectPermissionForDataDelivery( 3730 this, attributionSource, "GattService getRegisteredServiceUuids")) { 3731 return new ArrayList<>(0); 3732 } 3733 List<ParcelUuid> serviceUuids = new ArrayList<ParcelUuid>(); 3734 for (HandleMap.Entry entry : mHandleMap.getEntries()) { 3735 serviceUuids.add(new ParcelUuid(entry.uuid)); 3736 } 3737 return serviceUuids; 3738 } 3739 3740 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) getConnectedDevices(AttributionSource attributionSource)3741 List<String> getConnectedDevices(AttributionSource attributionSource) { 3742 if (!Utils.checkConnectPermissionForDataDelivery( 3743 this, attributionSource, "GattService getConnectedDevices")) { 3744 return new ArrayList<>(0); 3745 } 3746 3747 Set<String> connectedDevAddress = new HashSet<String>(); 3748 connectedDevAddress.addAll(mClientMap.getConnectedDevices()); 3749 connectedDevAddress.addAll(mServerMap.getConnectedDevices()); 3750 List<String> connectedDeviceList = new ArrayList<String>(connectedDevAddress); 3751 return connectedDeviceList; 3752 } 3753 3754 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) refreshDevice(int clientIf, String address, AttributionSource attributionSource)3755 void refreshDevice(int clientIf, String address, AttributionSource attributionSource) { 3756 if (!Utils.checkConnectPermissionForDataDelivery( 3757 this, attributionSource, "GattService refreshDevice")) { 3758 return; 3759 } 3760 3761 if (DBG) { 3762 Log.d(TAG, "refreshDevice() - address=" + address); 3763 } 3764 mNativeInterface.gattClientRefresh(clientIf, address); 3765 } 3766 3767 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) discoverServices(int clientIf, String address, AttributionSource attributionSource)3768 void discoverServices(int clientIf, String address, AttributionSource attributionSource) { 3769 if (!Utils.checkConnectPermissionForDataDelivery( 3770 this, attributionSource, "GattService discoverServices")) { 3771 return; 3772 } 3773 3774 Integer connId = mClientMap.connIdByAddress(clientIf, address); 3775 if (DBG) { 3776 Log.d(TAG, "discoverServices() - address=" + address + ", connId=" + connId); 3777 } 3778 3779 if (connId != null) { 3780 mNativeInterface.gattClientSearchService(connId, true, 0, 0); 3781 } else { 3782 Log.e(TAG, "discoverServices() - No connection for " + address + "..."); 3783 } 3784 } 3785 3786 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) discoverServiceByUuid( int clientIf, String address, UUID uuid, AttributionSource attributionSource)3787 void discoverServiceByUuid( 3788 int clientIf, String address, UUID uuid, AttributionSource attributionSource) { 3789 if (!Utils.checkConnectPermissionForDataDelivery( 3790 this, attributionSource, "GattService discoverServiceByUuid")) { 3791 return; 3792 } 3793 3794 Integer connId = mClientMap.connIdByAddress(clientIf, address); 3795 if (connId != null) { 3796 mNativeInterface.gattClientDiscoverServiceByUuid(connId, uuid.getLeastSignificantBits(), 3797 uuid.getMostSignificantBits()); 3798 } else { 3799 Log.e(TAG, "discoverServiceByUuid() - No connection for " + address + "..."); 3800 } 3801 } 3802 3803 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) readCharacteristic(int clientIf, String address, int handle, int authReq, AttributionSource attributionSource)3804 void readCharacteristic(int clientIf, String address, int handle, int authReq, 3805 AttributionSource attributionSource) { 3806 if (!Utils.checkConnectPermissionForDataDelivery( 3807 this, attributionSource, "GattService readCharacteristic")) { 3808 return; 3809 } 3810 3811 if (VDBG) { 3812 Log.d(TAG, "readCharacteristic() - address=" + address); 3813 } 3814 3815 Integer connId = mClientMap.connIdByAddress(clientIf, address); 3816 if (connId == null) { 3817 Log.e(TAG, "readCharacteristic() - No connection for " + address + "..."); 3818 return; 3819 } 3820 3821 try { 3822 permissionCheck(connId, handle); 3823 } catch (SecurityException ex) { 3824 String callingPackage = attributionSource.getPackageName(); 3825 // Only throws on apps with target SDK T+ as this old API did not throw prior to T 3826 if (checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.TIRAMISU)) { 3827 throw ex; 3828 } 3829 Log.w(TAG, "readCharacteristic() - permission check failed!"); 3830 return; 3831 } 3832 3833 mNativeInterface.gattClientReadCharacteristic(connId, handle, authReq); 3834 } 3835 3836 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) readUsingCharacteristicUuid(int clientIf, String address, UUID uuid, int startHandle, int endHandle, int authReq, AttributionSource attributionSource)3837 void readUsingCharacteristicUuid(int clientIf, String address, UUID uuid, int startHandle, 3838 int endHandle, int authReq, AttributionSource attributionSource) { 3839 if (!Utils.checkConnectPermissionForDataDelivery( 3840 this, attributionSource, "GattService readUsingCharacteristicUuid")) { 3841 return; 3842 } 3843 3844 if (VDBG) { 3845 Log.d(TAG, "readUsingCharacteristicUuid() - address=" + address); 3846 } 3847 3848 Integer connId = mClientMap.connIdByAddress(clientIf, address); 3849 if (connId == null) { 3850 Log.e(TAG, "readUsingCharacteristicUuid() - No connection for " + address + "..."); 3851 return; 3852 } 3853 3854 try { 3855 permissionCheck(uuid); 3856 } catch (SecurityException ex) { 3857 String callingPackage = attributionSource.getPackageName(); 3858 // Only throws on apps with target SDK T+ as this old API did not throw prior to T 3859 if (checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.TIRAMISU)) { 3860 throw ex; 3861 } 3862 Log.w(TAG, "readUsingCharacteristicUuid() - permission check failed!"); 3863 return; 3864 } 3865 3866 mNativeInterface.gattClientReadUsingCharacteristicUuid(connId, 3867 uuid.getLeastSignificantBits(), uuid.getMostSignificantBits(), startHandle, 3868 endHandle, authReq); 3869 } 3870 3871 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) writeCharacteristic(int clientIf, String address, int handle, int writeType, int authReq, byte[] value, AttributionSource attributionSource)3872 int writeCharacteristic(int clientIf, String address, int handle, int writeType, int authReq, 3873 byte[] value, AttributionSource attributionSource) { 3874 if (!Utils.checkConnectPermissionForDataDelivery( 3875 this, attributionSource, "GattService writeCharacteristic")) { 3876 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; 3877 } 3878 3879 if (VDBG) { 3880 Log.d(TAG, "writeCharacteristic() - address=" + address); 3881 } 3882 3883 if (mReliableQueue.contains(address)) { 3884 writeType = 3; // Prepared write 3885 } 3886 3887 Integer connId = mClientMap.connIdByAddress(clientIf, address); 3888 if (connId == null) { 3889 Log.e(TAG, "writeCharacteristic() - No connection for " + address + "..."); 3890 return BluetoothStatusCodes.ERROR_DEVICE_NOT_CONNECTED; 3891 } 3892 permissionCheck(connId, handle); 3893 3894 Log.d(TAG, "writeCharacteristic() - trying to acquire permit."); 3895 // Lock the thread until onCharacteristicWrite callback comes back. 3896 synchronized (mPermits) { 3897 Integer permit = mPermits.get(address); 3898 if (permit == null) { 3899 Log.d(TAG, "writeCharacteristic() - atomicBoolean uninitialized!"); 3900 return BluetoothStatusCodes.ERROR_DEVICE_NOT_CONNECTED; 3901 } 3902 3903 boolean success = (permit == -1); 3904 if (!success) { 3905 Log.d(TAG, "writeCharacteristic() - no permit available."); 3906 return BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY; 3907 } 3908 mPermits.put(address, connId); 3909 } 3910 3911 mNativeInterface.gattClientWriteCharacteristic(connId, handle, writeType, authReq, value); 3912 return BluetoothStatusCodes.SUCCESS; 3913 } 3914 3915 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) readDescriptor(int clientIf, String address, int handle, int authReq, AttributionSource attributionSource)3916 void readDescriptor(int clientIf, String address, int handle, int authReq, 3917 AttributionSource attributionSource) { 3918 if (!Utils.checkConnectPermissionForDataDelivery( 3919 this, attributionSource, "GattService readDescriptor")) { 3920 return; 3921 } 3922 3923 if (VDBG) { 3924 Log.d(TAG, "readDescriptor() - address=" + address); 3925 } 3926 3927 Integer connId = mClientMap.connIdByAddress(clientIf, address); 3928 if (connId == null) { 3929 Log.e(TAG, "readDescriptor() - No connection for " + address + "..."); 3930 return; 3931 } 3932 3933 try { 3934 permissionCheck(connId, handle); 3935 } catch (SecurityException ex) { 3936 String callingPackage = attributionSource.getPackageName(); 3937 // Only throws on apps with target SDK T+ as this old API did not throw prior to T 3938 if (checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.TIRAMISU)) { 3939 throw ex; 3940 } 3941 Log.w(TAG, "readDescriptor() - permission check failed!"); 3942 return; 3943 } 3944 3945 mNativeInterface.gattClientReadDescriptor(connId, handle, authReq); 3946 } 3947 3948 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) writeDescriptor(int clientIf, String address, int handle, int authReq, byte[] value, AttributionSource attributionSource)3949 int writeDescriptor(int clientIf, String address, int handle, int authReq, byte[] value, 3950 AttributionSource attributionSource) { 3951 if (!Utils.checkConnectPermissionForDataDelivery( 3952 this, attributionSource, "GattService writeDescriptor")) { 3953 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; 3954 } 3955 if (VDBG) { 3956 Log.d(TAG, "writeDescriptor() - address=" + address); 3957 } 3958 3959 Integer connId = mClientMap.connIdByAddress(clientIf, address); 3960 if (connId == null) { 3961 Log.e(TAG, "writeDescriptor() - No connection for " + address + "..."); 3962 return BluetoothStatusCodes.ERROR_DEVICE_NOT_CONNECTED; 3963 } 3964 permissionCheck(connId, handle); 3965 3966 mNativeInterface.gattClientWriteDescriptor(connId, handle, authReq, value); 3967 return BluetoothStatusCodes.SUCCESS; 3968 } 3969 3970 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) beginReliableWrite(int clientIf, String address, AttributionSource attributionSource)3971 void beginReliableWrite(int clientIf, String address, AttributionSource attributionSource) { 3972 if (!Utils.checkConnectPermissionForDataDelivery( 3973 this, attributionSource, "GattService beginReliableWrite")) { 3974 return; 3975 } 3976 3977 if (DBG) { 3978 Log.d(TAG, "beginReliableWrite() - address=" + address); 3979 } 3980 mReliableQueue.add(address); 3981 } 3982 3983 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) endReliableWrite( int clientIf, String address, boolean execute, AttributionSource attributionSource)3984 void endReliableWrite( 3985 int clientIf, String address, boolean execute, AttributionSource attributionSource) { 3986 if (!Utils.checkConnectPermissionForDataDelivery( 3987 this, attributionSource, "GattService endReliableWrite")) { 3988 return; 3989 } 3990 3991 if (DBG) { 3992 Log.d(TAG, "endReliableWrite() - address=" + address + " execute: " + execute); 3993 } 3994 mReliableQueue.remove(address); 3995 3996 Integer connId = mClientMap.connIdByAddress(clientIf, address); 3997 if (connId != null) { 3998 mNativeInterface.gattClientExecuteWrite(connId, execute); 3999 } 4000 } 4001 4002 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) registerForNotification(int clientIf, String address, int handle, boolean enable, AttributionSource attributionSource)4003 void registerForNotification(int clientIf, String address, int handle, boolean enable, 4004 AttributionSource attributionSource) { 4005 if (!Utils.checkConnectPermissionForDataDelivery( 4006 this, attributionSource, "GattService registerForNotification")) { 4007 return; 4008 } 4009 4010 if (DBG) { 4011 Log.d(TAG, "registerForNotification() - address=" + address + " enable: " + enable); 4012 } 4013 4014 Integer connId = mClientMap.connIdByAddress(clientIf, address); 4015 if (connId == null) { 4016 Log.e(TAG, "registerForNotification() - No connection for " + address + "..."); 4017 return; 4018 } 4019 4020 try { 4021 permissionCheck(connId, handle); 4022 } catch (SecurityException ex) { 4023 String callingPackage = attributionSource.getPackageName(); 4024 // Only throws on apps with target SDK T+ as this old API did not throw prior to T 4025 if (checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.TIRAMISU)) { 4026 throw ex; 4027 } 4028 Log.w(TAG, "registerForNotification() - permission check failed!"); 4029 return; 4030 } 4031 4032 mNativeInterface.gattClientRegisterForNotifications(clientIf, address, handle, enable); 4033 } 4034 4035 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) readRemoteRssi(int clientIf, String address, AttributionSource attributionSource)4036 void readRemoteRssi(int clientIf, String address, AttributionSource attributionSource) { 4037 if (!Utils.checkConnectPermissionForDataDelivery( 4038 this, attributionSource, "GattService readRemoteRssi")) { 4039 return; 4040 } 4041 4042 if (DBG) { 4043 Log.d(TAG, "readRemoteRssi() - address=" + address); 4044 } 4045 mNativeInterface.gattClientReadRemoteRssi(clientIf, address); 4046 } 4047 4048 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) configureMTU(int clientIf, String address, int mtu, AttributionSource attributionSource)4049 void configureMTU(int clientIf, String address, int mtu, AttributionSource attributionSource) { 4050 if (!Utils.checkConnectPermissionForDataDelivery( 4051 this, attributionSource, "GattService configureMTU")) { 4052 return; 4053 } 4054 4055 if (DBG) { 4056 Log.d(TAG, "configureMTU() - address=" + address + " mtu=" + mtu); 4057 } 4058 Integer connId = mClientMap.connIdByAddress(clientIf, address); 4059 if (connId != null) { 4060 mNativeInterface.gattClientConfigureMTU(connId, mtu); 4061 } else { 4062 Log.e(TAG, "configureMTU() - No connection for " + address + "..."); 4063 } 4064 } 4065 4066 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) connectionParameterUpdate(int clientIf, String address, int connectionPriority, AttributionSource attributionSource)4067 void connectionParameterUpdate(int clientIf, String address, int connectionPriority, 4068 AttributionSource attributionSource) { 4069 if (!Utils.checkConnectPermissionForDataDelivery( 4070 this, attributionSource, "GattService connectionParameterUpdate")) { 4071 return; 4072 } 4073 4074 int minInterval; 4075 int maxInterval; 4076 4077 // Peripheral latency 4078 int latency; 4079 4080 // Link supervision timeout is measured in N * 10ms 4081 int timeout = 500; // 5s 4082 4083 4084 CompanionManager manager = 4085 AdapterService.getAdapterService().getCompanionManager(); 4086 4087 minInterval = manager.getGattConnParameters( 4088 address, CompanionManager.GATT_CONN_INTERVAL_MIN, connectionPriority); 4089 maxInterval = manager.getGattConnParameters( 4090 address, CompanionManager.GATT_CONN_INTERVAL_MAX, connectionPriority); 4091 latency = manager.getGattConnParameters( 4092 address, CompanionManager.GATT_CONN_LATENCY, connectionPriority); 4093 4094 Log.d(TAG, "connectionParameterUpdate() - address=" + address + " params=" 4095 + connectionPriority + " interval=" + minInterval + "/" + maxInterval 4096 + " timeout=" + timeout); 4097 4098 mNativeInterface.gattConnectionParameterUpdate(clientIf, address, minInterval, maxInterval, 4099 latency, timeout, 0, 0); 4100 } 4101 4102 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) leConnectionUpdate(int clientIf, String address, int minInterval, int maxInterval, int peripheralLatency, int supervisionTimeout, int minConnectionEventLen, int maxConnectionEventLen, AttributionSource attributionSource)4103 void leConnectionUpdate(int clientIf, String address, int minInterval, 4104 int maxInterval, int peripheralLatency, 4105 int supervisionTimeout, int minConnectionEventLen, 4106 int maxConnectionEventLen, AttributionSource attributionSource) { 4107 if (!Utils.checkConnectPermissionForDataDelivery( 4108 this, attributionSource, "GattService leConnectionUpdate")) { 4109 return; 4110 } 4111 4112 Log.d(TAG, "leConnectionUpdate() - address=" + address + ", intervals=" 4113 + minInterval + "/" + maxInterval + ", latency=" + peripheralLatency 4114 + ", timeout=" + supervisionTimeout + "msec" + ", min_ce=" 4115 + minConnectionEventLen + ", max_ce=" + maxConnectionEventLen); 4116 4117 mNativeInterface.gattConnectionParameterUpdate(clientIf, address, minInterval, maxInterval, 4118 peripheralLatency, supervisionTimeout, 4119 minConnectionEventLen, maxConnectionEventLen); 4120 } 4121 4122 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) subrateModeRequest(int clientIf, String address, int subrateMode, AttributionSource attributionSource)4123 void subrateModeRequest(int clientIf, String address, int subrateMode, 4124 AttributionSource attributionSource) { 4125 if (!Utils.checkConnectPermissionForDataDelivery( 4126 this, attributionSource, "GattService subrateModeRequest")) { 4127 return; 4128 } 4129 4130 int subrateMin; 4131 int subrateMax; 4132 int maxLatency; 4133 int contNumber; 4134 // Link supervision timeout is measured in N * 10ms 4135 int supervisionTimeout = 500; // 5s 4136 4137 Resources res = getResources(); 4138 4139 switch (subrateMode) { 4140 case BluetoothGatt.SUBRATE_REQUEST_MODE_HIGH: 4141 subrateMin = res.getInteger(R.integer.subrate_mode_high_priority_min_subrate); 4142 subrateMax = res.getInteger(R.integer.subrate_mode_high_priority_max_subrate); 4143 maxLatency = res.getInteger(R.integer.subrate_mode_high_priority_latency); 4144 contNumber = res.getInteger(R.integer.subrate_mode_high_priority_cont_number); 4145 break; 4146 4147 case BluetoothGatt.SUBRATE_REQUEST_MODE_LOW_POWER: 4148 subrateMin = res.getInteger(R.integer.subrate_mode_low_power_min_subrate); 4149 subrateMax = res.getInteger(R.integer.subrate_mode_low_power_max_subrate); 4150 maxLatency = res.getInteger(R.integer.subrate_mode_low_power_latency); 4151 contNumber = res.getInteger(R.integer.subrate_mode_low_power_cont_number); 4152 break; 4153 4154 case BluetoothGatt.SUBRATE_REQUEST_MODE_BALANCED: 4155 default: 4156 subrateMin = res.getInteger(R.integer.subrate_mode_balanced_min_subrate); 4157 subrateMax = res.getInteger(R.integer.subrate_mode_balanced_max_subrate); 4158 maxLatency = res.getInteger(R.integer.subrate_mode_balanced_latency); 4159 contNumber = res.getInteger(R.integer.subrate_mode_balanced_cont_number); 4160 break; 4161 } 4162 4163 if (DBG) { 4164 Log.d(TAG, "subrateModeRequest() - " 4165 + "address=" + BluetoothUtils.toAnonymizedAddress(address) 4166 + ", subrate min/max=" + subrateMin + "/" + subrateMax 4167 + ", maxLatency=" + maxLatency 4168 + ", continuation Number=" + contNumber 4169 + ", timeout=" + supervisionTimeout); 4170 } 4171 4172 mNativeInterface.gattSubrateRequest(clientIf, address, subrateMin, subrateMax, maxLatency, 4173 contNumber, supervisionTimeout); 4174 } 4175 4176 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) leSubrateRequest(int clientIf, String address, int subrateMin, int subrateMax, int maxLatency, int contNumber, int supervisionTimeout, AttributionSource attributionSource)4177 void leSubrateRequest(int clientIf, String address, int subrateMin, int subrateMax, 4178 int maxLatency, int contNumber, int supervisionTimeout, 4179 AttributionSource attributionSource) { 4180 if (!Utils.checkConnectPermissionForDataDelivery( 4181 this, attributionSource, "GattService leSubrateRequest")) { 4182 return; 4183 } 4184 4185 if (DBG) { 4186 Log.d(TAG, "leSubrateRequest() - " 4187 + "address=" + BluetoothUtils.toAnonymizedAddress(address) 4188 + ", subrate min/max=" + subrateMin + "/" + subrateMax 4189 + ", maxLatency=" + maxLatency 4190 + ", continuation Number=" + contNumber 4191 + ", timeout=" + supervisionTimeout); 4192 } 4193 4194 mNativeInterface.gattSubrateRequest(clientIf, address, subrateMin, subrateMax, maxLatency, 4195 contNumber, supervisionTimeout); 4196 } 4197 4198 /************************************************************************** 4199 * Callback functions - SERVER 4200 *************************************************************************/ 4201 onServerRegistered(int status, int serverIf, long uuidLsb, long uuidMsb)4202 void onServerRegistered(int status, int serverIf, long uuidLsb, long uuidMsb) 4203 throws RemoteException { 4204 4205 UUID uuid = new UUID(uuidMsb, uuidLsb); 4206 if (DBG) { 4207 Log.d(TAG, "onServerRegistered() - UUID=" + uuid + ", serverIf=" + serverIf); 4208 } 4209 ServerMap.App app = mServerMap.getByUuid(uuid); 4210 if (app != null) { 4211 app.id = serverIf; 4212 app.linkToDeath(new ServerDeathRecipient(serverIf)); 4213 app.callback.onServerRegistered(status, serverIf); 4214 } 4215 } 4216 onServiceAdded(int status, int serverIf, List<GattDbElement> service)4217 void onServiceAdded(int status, int serverIf, List<GattDbElement> service) 4218 throws RemoteException { 4219 if (DBG) { 4220 Log.d(TAG, "onServiceAdded(), status=" + status); 4221 } 4222 4223 if (status != 0) { 4224 return; 4225 } 4226 4227 GattDbElement svcEl = service.get(0); 4228 int srvcHandle = svcEl.attributeHandle; 4229 4230 BluetoothGattService svc = null; 4231 4232 for (GattDbElement el : service) { 4233 if (el.type == GattDbElement.TYPE_PRIMARY_SERVICE) { 4234 mHandleMap.addService(serverIf, el.attributeHandle, el.uuid, 4235 BluetoothGattService.SERVICE_TYPE_PRIMARY, 0, false); 4236 svc = new BluetoothGattService(svcEl.uuid, svcEl.attributeHandle, 4237 BluetoothGattService.SERVICE_TYPE_PRIMARY); 4238 } else if (el.type == GattDbElement.TYPE_SECONDARY_SERVICE) { 4239 mHandleMap.addService(serverIf, el.attributeHandle, el.uuid, 4240 BluetoothGattService.SERVICE_TYPE_SECONDARY, 0, false); 4241 svc = new BluetoothGattService(svcEl.uuid, svcEl.attributeHandle, 4242 BluetoothGattService.SERVICE_TYPE_SECONDARY); 4243 } else if (el.type == GattDbElement.TYPE_CHARACTERISTIC) { 4244 mHandleMap.addCharacteristic(serverIf, el.attributeHandle, el.uuid, srvcHandle); 4245 svc.addCharacteristic( 4246 new BluetoothGattCharacteristic(el.uuid, el.attributeHandle, el.properties, 4247 el.permissions)); 4248 } else if (el.type == GattDbElement.TYPE_DESCRIPTOR) { 4249 mHandleMap.addDescriptor(serverIf, el.attributeHandle, el.uuid, srvcHandle); 4250 List<BluetoothGattCharacteristic> chars = svc.getCharacteristics(); 4251 chars.get(chars.size() - 1) 4252 .addDescriptor(new BluetoothGattDescriptor(el.uuid, el.attributeHandle, 4253 el.permissions)); 4254 } 4255 } 4256 mHandleMap.setStarted(serverIf, srvcHandle, true); 4257 4258 ServerMap.App app = mServerMap.getById(serverIf); 4259 if (app != null) { 4260 app.callback.onServiceAdded(status, svc); 4261 } 4262 } 4263 onServiceStopped(int status, int serverIf, int srvcHandle)4264 void onServiceStopped(int status, int serverIf, int srvcHandle) throws RemoteException { 4265 if (DBG) { 4266 Log.d(TAG, "onServiceStopped() srvcHandle=" + srvcHandle + ", status=" + status); 4267 } 4268 if (status == 0) { 4269 mHandleMap.setStarted(serverIf, srvcHandle, false); 4270 } 4271 stopNextService(serverIf, status); 4272 } 4273 onServiceDeleted(int status, int serverIf, int srvcHandle)4274 void onServiceDeleted(int status, int serverIf, int srvcHandle) { 4275 if (DBG) { 4276 Log.d(TAG, "onServiceDeleted() srvcHandle=" + srvcHandle + ", status=" + status); 4277 } 4278 mHandleMap.deleteService(serverIf, srvcHandle); 4279 } 4280 onClientConnected(String address, boolean connected, int connId, int serverIf)4281 void onClientConnected(String address, boolean connected, int connId, int serverIf) 4282 throws RemoteException { 4283 4284 if (DBG) { 4285 Log.d(TAG, 4286 "onClientConnected() connId=" + connId + ", address=" + address + ", connected=" 4287 + connected); 4288 } 4289 4290 ServerMap.App app = mServerMap.getById(serverIf); 4291 if (app == null) { 4292 return; 4293 } 4294 int connectionState; 4295 if (connected) { 4296 mServerMap.addConnection(serverIf, connId, address); 4297 connectionState = BluetoothProtoEnums.CONNECTION_STATE_CONNECTED; 4298 } else { 4299 mServerMap.removeConnection(serverIf, connId); 4300 connectionState = BluetoothProtoEnums.CONNECTION_STATE_DISCONNECTED; 4301 } 4302 4303 int applicationUid = -1; 4304 4305 try { 4306 applicationUid = this.getPackageManager().getPackageUid(app.name, PackageInfoFlags.of(0)); 4307 4308 } catch (NameNotFoundException e) { 4309 Log.d(TAG, "onClientConnected() uid_not_found=" + app.name); 4310 } 4311 4312 app.callback.onServerConnectionState((byte) 0, serverIf, connected, address); 4313 statsLogAppPackage(address, applicationUid, serverIf); 4314 statsLogGattConnectionStateChange( 4315 BluetoothProfile.GATT_SERVER, address, serverIf, connectionState, -1); 4316 } 4317 onServerReadCharacteristic(String address, int connId, int transId, int handle, int offset, boolean isLong)4318 void onServerReadCharacteristic(String address, int connId, int transId, int handle, int offset, 4319 boolean isLong) throws RemoteException { 4320 if (VDBG) { 4321 Log.d(TAG, "onServerReadCharacteristic() connId=" + connId + ", address=" + address 4322 + ", handle=" + handle + ", requestId=" + transId + ", offset=" + offset); 4323 } 4324 4325 HandleMap.Entry entry = mHandleMap.getByHandle(handle); 4326 if (entry == null) { 4327 return; 4328 } 4329 4330 mHandleMap.addRequest(transId, handle); 4331 4332 ServerMap.App app = mServerMap.getById(entry.serverIf); 4333 if (app == null) { 4334 return; 4335 } 4336 4337 app.callback.onCharacteristicReadRequest(address, transId, offset, isLong, handle); 4338 } 4339 onServerReadDescriptor(String address, int connId, int transId, int handle, int offset, boolean isLong)4340 void onServerReadDescriptor(String address, int connId, int transId, int handle, int offset, 4341 boolean isLong) throws RemoteException { 4342 if (VDBG) { 4343 Log.d(TAG, "onServerReadDescriptor() connId=" + connId + ", address=" + address 4344 + ", handle=" + handle + ", requestId=" + transId + ", offset=" + offset); 4345 } 4346 4347 HandleMap.Entry entry = mHandleMap.getByHandle(handle); 4348 if (entry == null) { 4349 return; 4350 } 4351 4352 mHandleMap.addRequest(transId, handle); 4353 4354 ServerMap.App app = mServerMap.getById(entry.serverIf); 4355 if (app == null) { 4356 return; 4357 } 4358 4359 app.callback.onDescriptorReadRequest(address, transId, offset, isLong, handle); 4360 } 4361 onServerWriteCharacteristic(String address, int connId, int transId, int handle, int offset, int length, boolean needRsp, boolean isPrep, byte[] data)4362 void onServerWriteCharacteristic(String address, int connId, int transId, int handle, 4363 int offset, int length, boolean needRsp, boolean isPrep, byte[] data) 4364 throws RemoteException { 4365 if (VDBG) { 4366 Log.d(TAG, "onServerWriteCharacteristic() connId=" + connId + ", address=" + address 4367 + ", handle=" + handle + ", requestId=" + transId + ", isPrep=" + isPrep 4368 + ", offset=" + offset); 4369 } 4370 4371 HandleMap.Entry entry = mHandleMap.getByHandle(handle); 4372 if (entry == null) { 4373 return; 4374 } 4375 4376 mHandleMap.addRequest(transId, handle); 4377 4378 ServerMap.App app = mServerMap.getById(entry.serverIf); 4379 if (app == null) { 4380 return; 4381 } 4382 4383 app.callback.onCharacteristicWriteRequest(address, transId, offset, length, isPrep, needRsp, 4384 handle, data); 4385 } 4386 onServerWriteDescriptor(String address, int connId, int transId, int handle, int offset, int length, boolean needRsp, boolean isPrep, byte[] data)4387 void onServerWriteDescriptor(String address, int connId, int transId, int handle, int offset, 4388 int length, boolean needRsp, boolean isPrep, byte[] data) throws RemoteException { 4389 if (VDBG) { 4390 Log.d(TAG, "onAttributeWrite() connId=" + connId + ", address=" + address + ", handle=" 4391 + handle + ", requestId=" + transId + ", isPrep=" + isPrep + ", offset=" 4392 + offset); 4393 } 4394 4395 HandleMap.Entry entry = mHandleMap.getByHandle(handle); 4396 if (entry == null) { 4397 return; 4398 } 4399 4400 mHandleMap.addRequest(transId, handle); 4401 4402 ServerMap.App app = mServerMap.getById(entry.serverIf); 4403 if (app == null) { 4404 return; 4405 } 4406 4407 app.callback.onDescriptorWriteRequest(address, transId, offset, length, isPrep, needRsp, 4408 handle, data); 4409 } 4410 onExecuteWrite(String address, int connId, int transId, int execWrite)4411 void onExecuteWrite(String address, int connId, int transId, int execWrite) 4412 throws RemoteException { 4413 if (DBG) { 4414 Log.d(TAG, "onExecuteWrite() connId=" + connId + ", address=" + address + ", transId=" 4415 + transId); 4416 } 4417 4418 ServerMap.App app = mServerMap.getByConnId(connId); 4419 if (app == null) { 4420 return; 4421 } 4422 4423 app.callback.onExecuteWrite(address, transId, execWrite == 1); 4424 } 4425 onResponseSendCompleted(int status, int attrHandle)4426 void onResponseSendCompleted(int status, int attrHandle) { 4427 if (DBG) { 4428 Log.d(TAG, "onResponseSendCompleted() handle=" + attrHandle); 4429 } 4430 } 4431 onNotificationSent(int connId, int status)4432 void onNotificationSent(int connId, int status) throws RemoteException { 4433 if (VDBG) { 4434 Log.d(TAG, "onNotificationSent() connId=" + connId + ", status=" + status); 4435 } 4436 4437 String address = mServerMap.addressByConnId(connId); 4438 if (address == null) { 4439 return; 4440 } 4441 4442 ServerMap.App app = mServerMap.getByConnId(connId); 4443 if (app == null) { 4444 return; 4445 } 4446 4447 if (!app.isCongested) { 4448 app.callback.onNotificationSent(address, status); 4449 } else { 4450 if (status == BluetoothGatt.GATT_CONNECTION_CONGESTED) { 4451 status = BluetoothGatt.GATT_SUCCESS; 4452 } 4453 app.queueCallback(new CallbackInfo.Builder(address, status).build()); 4454 } 4455 } 4456 onServerCongestion(int connId, boolean congested)4457 void onServerCongestion(int connId, boolean congested) throws RemoteException { 4458 if (DBG) { 4459 Log.d(TAG, "onServerCongestion() - connId=" + connId + ", congested=" + congested); 4460 } 4461 4462 ServerMap.App app = mServerMap.getByConnId(connId); 4463 if (app == null) { 4464 return; 4465 } 4466 4467 app.isCongested = congested; 4468 while (!app.isCongested) { 4469 CallbackInfo callbackInfo = app.popQueuedCallback(); 4470 if (callbackInfo == null) { 4471 return; 4472 } 4473 app.callback.onNotificationSent(callbackInfo.address, callbackInfo.status); 4474 } 4475 } 4476 onMtuChanged(int connId, int mtu)4477 void onMtuChanged(int connId, int mtu) throws RemoteException { 4478 if (DBG) { 4479 Log.d(TAG, "onMtuChanged() - connId=" + connId + ", mtu=" + mtu); 4480 } 4481 4482 String address = mServerMap.addressByConnId(connId); 4483 if (address == null) { 4484 return; 4485 } 4486 4487 ServerMap.App app = mServerMap.getByConnId(connId); 4488 if (app == null) { 4489 return; 4490 } 4491 4492 app.callback.onMtuChanged(address, mtu); 4493 } 4494 4495 /************************************************************************** 4496 * GATT Service functions - SERVER 4497 *************************************************************************/ 4498 4499 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) registerServer(UUID uuid, IBluetoothGattServerCallback callback, boolean eatt_support, AttributionSource attributionSource)4500 void registerServer(UUID uuid, IBluetoothGattServerCallback callback, boolean eatt_support, 4501 AttributionSource attributionSource) { 4502 if (!Utils.checkConnectPermissionForDataDelivery( 4503 this, attributionSource, "GattService registerServer")) { 4504 return; 4505 } 4506 4507 if (DBG) { 4508 Log.d(TAG, "registerServer() - UUID=" + uuid); 4509 } 4510 mServerMap.add(uuid, null, callback, null, this); 4511 mNativeInterface.gattServerRegisterApp(uuid.getLeastSignificantBits(), 4512 uuid.getMostSignificantBits(), eatt_support); 4513 } 4514 4515 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) unregisterServer(int serverIf, AttributionSource attributionSource)4516 void unregisterServer(int serverIf, AttributionSource attributionSource) { 4517 if (!Utils.checkConnectPermissionForDataDelivery( 4518 this, attributionSource, "GattService unregisterServer")) { 4519 return; 4520 } 4521 4522 if (DBG) { 4523 Log.d(TAG, "unregisterServer() - serverIf=" + serverIf); 4524 } 4525 4526 deleteServices(serverIf); 4527 4528 mServerMap.remove(serverIf); 4529 mNativeInterface.gattServerUnregisterApp(serverIf); 4530 } 4531 4532 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) serverConnect(int serverIf, String address, boolean isDirect, int transport, AttributionSource attributionSource)4533 void serverConnect(int serverIf, String address, boolean isDirect, int transport, 4534 AttributionSource attributionSource) { 4535 if (!Utils.checkConnectPermissionForDataDelivery( 4536 this, attributionSource, "GattService serverConnect")) { 4537 return; 4538 } 4539 4540 if (DBG) { 4541 Log.d(TAG, "serverConnect() - address=" + address); 4542 } 4543 mNativeInterface.gattServerConnect(serverIf, address, isDirect, transport); 4544 } 4545 4546 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) serverDisconnect(int serverIf, String address, AttributionSource attributionSource)4547 void serverDisconnect(int serverIf, String address, AttributionSource attributionSource) { 4548 if (!Utils.checkConnectPermissionForDataDelivery( 4549 this, attributionSource, "GattService serverDisconnect")) { 4550 return; 4551 } 4552 4553 Integer connId = mServerMap.connIdByAddress(serverIf, address); 4554 if (DBG) { 4555 Log.d(TAG, "serverDisconnect() - address=" + address + ", connId=" + connId); 4556 } 4557 4558 mNativeInterface.gattServerDisconnect(serverIf, address, connId != null ? connId : 0); 4559 } 4560 4561 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) serverSetPreferredPhy(int serverIf, String address, int txPhy, int rxPhy, int phyOptions, AttributionSource attributionSource)4562 void serverSetPreferredPhy(int serverIf, String address, int txPhy, int rxPhy, int phyOptions, 4563 AttributionSource attributionSource) { 4564 if (!Utils.checkConnectPermissionForDataDelivery( 4565 this, attributionSource, "GattService serverSetPreferredPhy")) { 4566 return; 4567 } 4568 4569 Integer connId = mServerMap.connIdByAddress(serverIf, address); 4570 if (connId == null) { 4571 if (DBG) { 4572 Log.d(TAG, "serverSetPreferredPhy() - no connection to " + address); 4573 } 4574 return; 4575 } 4576 4577 if (DBG) { 4578 Log.d(TAG, "serverSetPreferredPhy() - address=" + address + ", connId=" + connId); 4579 } 4580 mNativeInterface.gattServerSetPreferredPhy(serverIf, address, txPhy, rxPhy, phyOptions); 4581 } 4582 4583 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) serverReadPhy(int serverIf, String address, AttributionSource attributionSource)4584 void serverReadPhy(int serverIf, String address, AttributionSource attributionSource) { 4585 if (!Utils.checkConnectPermissionForDataDelivery( 4586 this, attributionSource, "GattService serverReadPhy")) { 4587 return; 4588 } 4589 4590 Integer connId = mServerMap.connIdByAddress(serverIf, address); 4591 if (connId == null) { 4592 if (DBG) { 4593 Log.d(TAG, "serverReadPhy() - no connection to " + address); 4594 } 4595 return; 4596 } 4597 4598 if (DBG) { 4599 Log.d(TAG, "serverReadPhy() - address=" + address + ", connId=" + connId); 4600 } 4601 mNativeInterface.gattServerReadPhy(serverIf, address); 4602 } 4603 4604 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) addService( int serverIf, BluetoothGattService service, AttributionSource attributionSource)4605 void addService( 4606 int serverIf, BluetoothGattService service, AttributionSource attributionSource) { 4607 if (!Utils.checkConnectPermissionForDataDelivery( 4608 this, attributionSource, "GattService addService")) { 4609 return; 4610 } 4611 4612 if (DBG) { 4613 Log.d(TAG, "addService() - uuid=" + service.getUuid()); 4614 } 4615 4616 List<GattDbElement> db = new ArrayList<GattDbElement>(); 4617 4618 if (service.getType() == BluetoothGattService.SERVICE_TYPE_PRIMARY) { 4619 db.add(GattDbElement.createPrimaryService(service.getUuid())); 4620 } else { 4621 db.add(GattDbElement.createSecondaryService(service.getUuid())); 4622 } 4623 4624 for (BluetoothGattService includedService : service.getIncludedServices()) { 4625 int inclSrvcHandle = includedService.getInstanceId(); 4626 4627 if (mHandleMap.checkServiceExists(includedService.getUuid(), inclSrvcHandle)) { 4628 db.add(GattDbElement.createIncludedService(inclSrvcHandle)); 4629 } else { 4630 Log.e(TAG, 4631 "included service with UUID " + includedService.getUuid() + " not found!"); 4632 } 4633 } 4634 4635 for (BluetoothGattCharacteristic characteristic : service.getCharacteristics()) { 4636 int permission = 4637 ((characteristic.getKeySize() - 7) << 12) + characteristic.getPermissions(); 4638 db.add(GattDbElement.createCharacteristic(characteristic.getUuid(), 4639 characteristic.getProperties(), permission)); 4640 4641 for (BluetoothGattDescriptor descriptor : characteristic.getDescriptors()) { 4642 permission = 4643 ((characteristic.getKeySize() - 7) << 12) + descriptor.getPermissions(); 4644 db.add(GattDbElement.createDescriptor(descriptor.getUuid(), permission)); 4645 } 4646 } 4647 4648 mNativeInterface.gattServerAddService(serverIf, db); 4649 } 4650 4651 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) removeService(int serverIf, int handle, AttributionSource attributionSource)4652 void removeService(int serverIf, int handle, AttributionSource attributionSource) { 4653 if (!Utils.checkConnectPermissionForDataDelivery( 4654 this, attributionSource, "GattService removeService")) { 4655 return; 4656 } 4657 4658 if (DBG) { 4659 Log.d(TAG, "removeService() - handle=" + handle); 4660 } 4661 4662 mNativeInterface.gattServerDeleteService(serverIf, handle); 4663 } 4664 4665 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) clearServices(int serverIf, AttributionSource attributionSource)4666 void clearServices(int serverIf, AttributionSource attributionSource) { 4667 if (!Utils.checkConnectPermissionForDataDelivery( 4668 this, attributionSource, "GattService clearServices")) { 4669 return; 4670 } 4671 4672 if (DBG) { 4673 Log.d(TAG, "clearServices()"); 4674 } 4675 deleteServices(serverIf); 4676 } 4677 4678 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) sendResponse(int serverIf, String address, int requestId, int status, int offset, byte[] value, AttributionSource attributionSource)4679 void sendResponse(int serverIf, String address, int requestId, int status, int offset, 4680 byte[] value, AttributionSource attributionSource) { 4681 if (!Utils.checkConnectPermissionForDataDelivery( 4682 this, attributionSource, "GattService sendResponse")) { 4683 return; 4684 } 4685 4686 if (VDBG) { 4687 Log.d(TAG, "sendResponse() - address=" + address); 4688 } 4689 4690 int handle = 0; 4691 HandleMap.Entry entry = mHandleMap.getByRequestId(requestId); 4692 if (entry != null) { 4693 handle = entry.handle; 4694 } 4695 4696 Integer connId = mServerMap.connIdByAddress(serverIf, address); 4697 mNativeInterface.gattServerSendResponse(serverIf, connId != null ? connId : 0, requestId, 4698 (byte) status, handle, offset, value, (byte) 0); 4699 mHandleMap.deleteRequest(requestId); 4700 } 4701 4702 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) sendNotification(int serverIf, String address, int handle, boolean confirm, byte[] value, AttributionSource attributionSource)4703 int sendNotification(int serverIf, String address, int handle, boolean confirm, byte[] value, 4704 AttributionSource attributionSource) { 4705 if (!Utils.checkConnectPermissionForDataDelivery( 4706 this, attributionSource, "GattService sendNotification")) { 4707 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; 4708 } 4709 4710 if (VDBG) { 4711 Log.d(TAG, "sendNotification() - address=" + address + " handle=" + handle); 4712 } 4713 4714 Integer connId = mServerMap.connIdByAddress(serverIf, address); 4715 if (connId == null || connId == 0) { 4716 return BluetoothStatusCodes.ERROR_DEVICE_NOT_CONNECTED; 4717 } 4718 4719 if (confirm) { 4720 mNativeInterface.gattServerSendIndication(serverIf, handle, connId, value); 4721 } else { 4722 mNativeInterface.gattServerSendNotification(serverIf, handle, connId, value); 4723 } 4724 4725 return BluetoothStatusCodes.SUCCESS; 4726 } 4727 4728 4729 /************************************************************************** 4730 * Private functions 4731 *************************************************************************/ 4732 isHidSrvcUuid(final UUID uuid)4733 private boolean isHidSrvcUuid(final UUID uuid) { 4734 return HID_SERVICE_UUID.equals(uuid); 4735 } 4736 isHidCharUuid(final UUID uuid)4737 private boolean isHidCharUuid(final UUID uuid) { 4738 for (UUID hidUuid : HID_UUIDS) { 4739 if (hidUuid.equals(uuid)) { 4740 return true; 4741 } 4742 } 4743 return false; 4744 } 4745 isAndroidTvRemoteSrvcUuid(final UUID uuid)4746 private boolean isAndroidTvRemoteSrvcUuid(final UUID uuid) { 4747 return ANDROID_TV_REMOTE_SERVICE_UUID.equals(uuid); 4748 } 4749 isFidoSrvcUuid(final UUID uuid)4750 private boolean isFidoSrvcUuid(final UUID uuid) { 4751 return FIDO_SERVICE_UUID.equals(uuid); 4752 } 4753 isLeAudioSrvcUuid(final UUID uuid)4754 private boolean isLeAudioSrvcUuid(final UUID uuid) { 4755 for (UUID leAudioUuid : LE_AUDIO_SERVICE_UUIDS) { 4756 if (leAudioUuid.equals(uuid)) { 4757 return true; 4758 } 4759 } 4760 return false; 4761 } 4762 isRestrictedSrvcUuid(final UUID uuid)4763 private boolean isRestrictedSrvcUuid(final UUID uuid) { 4764 return isFidoSrvcUuid(uuid) 4765 || isAndroidTvRemoteSrvcUuid(uuid) 4766 || isLeAudioSrvcUuid(uuid); 4767 } 4768 getDeviceType(BluetoothDevice device)4769 private int getDeviceType(BluetoothDevice device) { 4770 int type = mNativeInterface.gattClientGetDeviceType(device.getAddress()); 4771 if (DBG) { 4772 Log.d(TAG, "getDeviceType() - device=" + device + ", type=" + type); 4773 } 4774 return type; 4775 } 4776 needsPrivilegedPermissionForScan(ScanSettings settings)4777 private boolean needsPrivilegedPermissionForScan(ScanSettings settings) { 4778 // BLE scan only mode needs special permission. 4779 if (mAdapterService.getState() != BluetoothAdapter.STATE_ON) { 4780 return true; 4781 } 4782 4783 // Regular scan, no special permission. 4784 if (settings == null) { 4785 return false; 4786 } 4787 4788 // Ambient discovery mode, needs privileged permission. 4789 if (settings.getScanMode() == ScanSettings.SCAN_MODE_AMBIENT_DISCOVERY) { 4790 return true; 4791 } 4792 4793 // Regular scan, no special permission. 4794 if (settings.getReportDelayMillis() == 0) { 4795 return false; 4796 } 4797 4798 // Batch scan, truncated mode needs permission. 4799 return settings.getScanResultType() == ScanSettings.SCAN_RESULT_TYPE_ABBREVIATED; 4800 } 4801 4802 /* 4803 * The {@link ScanFilter#setDeviceAddress} API overloads are @SystemApi access methods. This 4804 * requires that the permissions be BLUETOOTH_PRIVILEGED. 4805 */ 4806 @SuppressLint("AndroidFrameworkRequiresPermission") enforcePrivilegedPermissionIfNeeded(List<ScanFilter> filters)4807 private void enforcePrivilegedPermissionIfNeeded(List<ScanFilter> filters) { 4808 if (DBG) { 4809 Log.d(TAG, "enforcePrivilegedPermissionIfNeeded(" + filters + ")"); 4810 } 4811 // Some 3p API cases may have null filters, need to allow 4812 if (filters != null) { 4813 for (ScanFilter filter : filters) { 4814 // The only case to enforce here is if there is an address 4815 // If there is an address, enforce if the correct combination criteria is met. 4816 if (filter.getDeviceAddress() != null) { 4817 // At this point we have an address, that means a caller used the 4818 // setDeviceAddress(address) public API for the ScanFilter 4819 // We don't want to enforce if the type is PUBLIC and the IRK is null 4820 // However, if we have a different type that means the caller used a new 4821 // @SystemApi such as setDeviceAddress(address, type) or 4822 // setDeviceAddress(address, type, irk) which are both @SystemApi and require 4823 // permissions to be enforced 4824 if (filter.getAddressType() 4825 == BluetoothDevice.ADDRESS_TYPE_PUBLIC && filter.getIrk() == null) { 4826 // Do not enforce 4827 } else { 4828 enforceBluetoothPrivilegedPermission(this); 4829 } 4830 } 4831 } 4832 } 4833 } 4834 4835 @SuppressLint("AndroidFrameworkRequiresPermission") enforcePrivilegedPermissionIfNeeded(ScanSettings settings)4836 private void enforcePrivilegedPermissionIfNeeded(ScanSettings settings) { 4837 if (needsPrivilegedPermissionForScan(settings)) { 4838 enforceBluetoothPrivilegedPermission(this); 4839 } 4840 } 4841 4842 // Enforce caller has UPDATE_DEVICE_STATS permission, which allows the caller to blame other 4843 // apps for Bluetooth usage. A {@link SecurityException} will be thrown if the caller app does 4844 // not have UPDATE_DEVICE_STATS permission. 4845 @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) enforceImpersonatationPermission()4846 private void enforceImpersonatationPermission() { 4847 enforceCallingOrSelfPermission(android.Manifest.permission.UPDATE_DEVICE_STATS, 4848 "Need UPDATE_DEVICE_STATS permission"); 4849 } 4850 4851 @SuppressLint("AndroidFrameworkRequiresPermission") enforceImpersonatationPermissionIfNeeded(WorkSource workSource)4852 private void enforceImpersonatationPermissionIfNeeded(WorkSource workSource) { 4853 if (workSource != null) { 4854 enforceImpersonatationPermission(); 4855 } 4856 } 4857 4858 /** 4859 * Ensures the report delay is either 0 or at least the floor value (5000ms) 4860 * 4861 * @param settings are the scan settings passed into a request to start le scanning 4862 * @return the passed in ScanSettings object if the report delay is 0 or above the floor value; 4863 * a new ScanSettings object with the report delay being the floor value if the original 4864 * report delay was between 0 and the floor value (exclusive of both) 4865 */ 4866 @VisibleForTesting enforceReportDelayFloor(ScanSettings settings)4867 ScanSettings enforceReportDelayFloor(ScanSettings settings) { 4868 if (settings.getReportDelayMillis() == 0) { 4869 return settings; 4870 } 4871 4872 // Need to clear identity to pass device config permission check 4873 final long callerToken = Binder.clearCallingIdentity(); 4874 try { 4875 long floor = DeviceConfig.getLong(DeviceConfig.NAMESPACE_BLUETOOTH, "report_delay", 4876 DEFAULT_REPORT_DELAY_FLOOR); 4877 4878 if (settings.getReportDelayMillis() > floor) { 4879 return settings; 4880 } else { 4881 return new ScanSettings.Builder() 4882 .setCallbackType(settings.getCallbackType()) 4883 .setLegacy(settings.getLegacy()) 4884 .setMatchMode(settings.getMatchMode()) 4885 .setNumOfMatches(settings.getNumOfMatches()) 4886 .setPhy(settings.getPhy()) 4887 .setReportDelay(floor) 4888 .setScanMode(settings.getScanMode()) 4889 .setScanResultType(settings.getScanResultType()) 4890 .build(); 4891 } 4892 } finally { 4893 Binder.restoreCallingIdentity(callerToken); 4894 } 4895 } 4896 stopNextService(int serverIf, int status)4897 private void stopNextService(int serverIf, int status) throws RemoteException { 4898 if (DBG) { 4899 Log.d(TAG, "stopNextService() - serverIf=" + serverIf + ", status=" + status); 4900 } 4901 4902 if (status == 0) { 4903 List<HandleMap.Entry> entries = mHandleMap.getEntries(); 4904 for (HandleMap.Entry entry : entries) { 4905 if (entry.type != HandleMap.TYPE_SERVICE || entry.serverIf != serverIf 4906 || !entry.started) { 4907 continue; 4908 } 4909 4910 mNativeInterface.gattServerStopService(serverIf, entry.handle); 4911 return; 4912 } 4913 } 4914 } 4915 deleteServices(int serverIf)4916 private void deleteServices(int serverIf) { 4917 if (DBG) { 4918 Log.d(TAG, "deleteServices() - serverIf=" + serverIf); 4919 } 4920 4921 /* 4922 * Figure out which handles to delete. 4923 * The handles are copied into a new list to avoid race conditions. 4924 */ 4925 List<Integer> handleList = new ArrayList<Integer>(); 4926 List<HandleMap.Entry> entries = mHandleMap.getEntries(); 4927 for (HandleMap.Entry entry : entries) { 4928 if (entry.type != HandleMap.TYPE_SERVICE || entry.serverIf != serverIf) { 4929 continue; 4930 } 4931 handleList.add(entry.handle); 4932 } 4933 4934 /* Now actually delete the services.... */ 4935 for (Integer handle : handleList) { 4936 mNativeInterface.gattServerDeleteService(serverIf, handle); 4937 } 4938 } 4939 dumpRegisterId(StringBuilder sb)4940 void dumpRegisterId(StringBuilder sb) { 4941 sb.append(" Scanner:\n"); 4942 for (Integer appId : mScannerMap.getAllAppsIds()) { 4943 println(sb, " app_if: " + appId + ", appName: " + mScannerMap.getById(appId).name); 4944 } 4945 sb.append(" Client:\n"); 4946 for (Integer appId : mClientMap.getAllAppsIds()) { 4947 println(sb, " app_if: " + appId + ", appName: " + mClientMap.getById(appId).name); 4948 } 4949 sb.append(" Server:\n"); 4950 for (Integer appId : mServerMap.getAllAppsIds()) { 4951 println(sb, " app_if: " + appId + ", appName: " + mServerMap.getById(appId).name); 4952 } 4953 sb.append("\n\n"); 4954 } 4955 4956 @Override dump(StringBuilder sb)4957 public void dump(StringBuilder sb) { 4958 super.dump(sb); 4959 println(sb, "mAdvertisingServiceUuids:"); 4960 for (UUID uuid : mAdvertisingServiceUuids) { 4961 println(sb, " " + uuid); 4962 } 4963 4964 println(sb, "mMaxScanFilters: " + mMaxScanFilters); 4965 4966 sb.append("\nRegistered App\n"); 4967 dumpRegisterId(sb); 4968 4969 sb.append("GATT Scanner Map\n"); 4970 mScannerMap.dump(sb); 4971 4972 sb.append("GATT Advertiser Map\n"); 4973 mAdvertiserMap.dumpAdvertiser(sb); 4974 4975 sb.append("GATT Client Map\n"); 4976 mClientMap.dump(sb); 4977 4978 sb.append("GATT Server Map\n"); 4979 mServerMap.dump(sb); 4980 4981 sb.append("GATT Handle Map\n"); 4982 mHandleMap.dump(sb); 4983 } 4984 addScanEvent(BluetoothMetricsProto.ScanEvent event)4985 void addScanEvent(BluetoothMetricsProto.ScanEvent event) { 4986 synchronized (mScanEvents) { 4987 if (mScanEvents.size() == NUM_SCAN_EVENTS_KEPT) { 4988 mScanEvents.remove(); 4989 } 4990 mScanEvents.add(event); 4991 } 4992 } 4993 statsLogAppPackage(String address, int applicationUid, int sessionIndex)4994 private void statsLogAppPackage(String address, int applicationUid, int sessionIndex) { 4995 BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address); 4996 BluetoothStatsLog.write( 4997 BluetoothStatsLog.BLUETOOTH_GATT_APP_INFO, 4998 sessionIndex, mAdapterService.getMetricId(device), applicationUid); 4999 if (DBG) { 5000 Log.d(TAG, "Gatt Logging: metric_id=" + mAdapterService.getMetricId(device) 5001 + ", app_uid=" + applicationUid); 5002 } 5003 } 5004 statsLogGattConnectionStateChange( int profile, String address, int sessionIndex, int connectionState, int connectionStatus)5005 private void statsLogGattConnectionStateChange( 5006 int profile, String address, int sessionIndex, int connectionState, 5007 int connectionStatus) { 5008 BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address); 5009 BluetoothStatsLog.write( 5010 BluetoothStatsLog.BLUETOOTH_CONNECTION_STATE_CHANGED, connectionState, 5011 0 /* deprecated */, profile, new byte[0], 5012 mAdapterService.getMetricId(device), sessionIndex, connectionStatus); 5013 if (DBG) { 5014 Log.d(TAG, "Gatt Logging: metric_id=" + mAdapterService.getMetricId(device) 5015 + ", session_index=" + sessionIndex 5016 + ", connection state=" + connectionState 5017 + ", connection status=" + connectionStatus); 5018 } 5019 } 5020 5021 @Override dumpProto(BluetoothMetricsProto.BluetoothLog.Builder builder)5022 public void dumpProto(BluetoothMetricsProto.BluetoothLog.Builder builder) { 5023 synchronized (mScanEvents) { 5024 builder.addAllScanEvent(mScanEvents); 5025 } 5026 } 5027 5028 /************************************************************************** 5029 * GATT Test functions 5030 *************************************************************************/ gattTestCommand(int command, UUID uuid1, String bda1, int p1, int p2, int p3, int p4, int p5)5031 void gattTestCommand(int command, UUID uuid1, String bda1, int p1, int p2, int p3, int p4, 5032 int p5) { 5033 if (bda1 == null) { 5034 bda1 = "00:00:00:00:00:00"; 5035 } 5036 if (uuid1 != null) { 5037 mNativeInterface.gattTest(command, uuid1.getLeastSignificantBits(), 5038 uuid1.getMostSignificantBits(), bda1, p1, p2, p3, p4, p5); 5039 } else { 5040 mNativeInterface.gattTest(command, 0, 0, bda1, p1, p2, p3, p4, p5); 5041 } 5042 } 5043 } 5044