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