1 /* 2 * Copyright (C) 2012 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.btservice; 18 19 import static android.bluetooth.BluetoothDevice.TRANSPORT_AUTO; 20 import static android.text.format.DateUtils.MINUTE_IN_MILLIS; 21 import static android.text.format.DateUtils.SECOND_IN_MILLIS; 22 23 import static com.android.bluetooth.Utils.callerIsSystemOrActiveOrManagedUser; 24 import static com.android.bluetooth.Utils.enforceBluetoothPrivilegedPermission; 25 import static com.android.bluetooth.Utils.enforceCdmAssociation; 26 import static com.android.bluetooth.Utils.enforceDumpPermission; 27 import static com.android.bluetooth.Utils.enforceLocalMacAddressPermission; 28 import static com.android.bluetooth.Utils.getBytesFromAddress; 29 import static com.android.bluetooth.Utils.hasBluetoothPrivilegedPermission; 30 import static com.android.bluetooth.Utils.isPackageNameAccurate; 31 32 import android.annotation.NonNull; 33 import android.annotation.RequiresPermission; 34 import android.annotation.SuppressLint; 35 import android.app.AlarmManager; 36 import android.app.AppOpsManager; 37 import android.app.PendingIntent; 38 import android.app.Service; 39 import android.app.admin.DevicePolicyManager; 40 import android.bluetooth.BluetoothA2dp; 41 import android.bluetooth.BluetoothActivityEnergyInfo; 42 import android.bluetooth.BluetoothAdapter; 43 import android.bluetooth.BluetoothAdapter.ActiveDeviceProfile; 44 import android.bluetooth.BluetoothAdapter.ActiveDeviceUse; 45 import android.bluetooth.BluetoothClass; 46 import android.bluetooth.BluetoothDevice; 47 import android.bluetooth.BluetoothFrameworkInitializer; 48 import android.bluetooth.BluetoothMap; 49 import android.bluetooth.BluetoothProfile; 50 import android.bluetooth.BluetoothProtoEnums; 51 import android.bluetooth.BluetoothSap; 52 import android.bluetooth.BluetoothServerSocket; 53 import android.bluetooth.BluetoothSinkAudioPolicy; 54 import android.bluetooth.BluetoothSocket; 55 import android.bluetooth.BluetoothStatusCodes; 56 import android.bluetooth.BluetoothUuid; 57 import android.bluetooth.BufferConstraints; 58 import android.bluetooth.IBluetooth; 59 import android.bluetooth.IBluetoothActivityEnergyInfoListener; 60 import android.bluetooth.IBluetoothCallback; 61 import android.bluetooth.IBluetoothConnectionCallback; 62 import android.bluetooth.IBluetoothMetadataListener; 63 import android.bluetooth.IBluetoothOobDataCallback; 64 import android.bluetooth.IBluetoothSocketManager; 65 import android.bluetooth.IncomingRfcommSocketInfo; 66 import android.bluetooth.OobData; 67 import android.bluetooth.UidTraffic; 68 import android.companion.CompanionDeviceManager; 69 import android.content.AttributionSource; 70 import android.content.BroadcastReceiver; 71 import android.content.Context; 72 import android.content.Intent; 73 import android.content.IntentFilter; 74 import android.content.SharedPreferences; 75 import android.content.pm.PackageManager; 76 import android.os.AsyncTask; 77 import android.os.BatteryStatsManager; 78 import android.os.Binder; 79 import android.os.Build; 80 import android.os.Bundle; 81 import android.os.Handler; 82 import android.os.IBinder; 83 import android.os.Looper; 84 import android.os.Message; 85 import android.os.ParcelUuid; 86 import android.os.PowerManager; 87 import android.os.RemoteCallbackList; 88 import android.os.RemoteException; 89 import android.os.SystemClock; 90 import android.os.SystemProperties; 91 import android.os.UserHandle; 92 import android.os.UserManager; 93 import android.provider.DeviceConfig; 94 import android.provider.Settings; 95 import android.sysprop.BluetoothProperties; 96 import android.text.TextUtils; 97 import android.util.Base64; 98 import android.util.Log; 99 import android.util.SparseArray; 100 101 import com.android.bluetooth.BluetoothMetricsProto; 102 import com.android.bluetooth.BluetoothStatsLog; 103 import com.android.bluetooth.R; 104 import com.android.bluetooth.Utils; 105 import com.android.bluetooth.a2dp.A2dpService; 106 import com.android.bluetooth.a2dpsink.A2dpSinkService; 107 import com.android.bluetooth.bas.BatteryService; 108 import com.android.bluetooth.bass_client.BassClientService; 109 import com.android.bluetooth.btservice.RemoteDevices.DeviceProperties; 110 import com.android.bluetooth.btservice.activityattribution.ActivityAttributionService; 111 import com.android.bluetooth.btservice.bluetoothkeystore.BluetoothKeystoreService; 112 import com.android.bluetooth.btservice.storage.DatabaseManager; 113 import com.android.bluetooth.btservice.storage.MetadataDatabase; 114 import com.android.bluetooth.csip.CsipSetCoordinatorService; 115 import com.android.bluetooth.gatt.GattService; 116 import com.android.bluetooth.gatt.ScanManager; 117 import com.android.bluetooth.hap.HapClientService; 118 import com.android.bluetooth.hearingaid.HearingAidService; 119 import com.android.bluetooth.hfp.HeadsetService; 120 import com.android.bluetooth.hfpclient.HeadsetClientService; 121 import com.android.bluetooth.hid.HidDeviceService; 122 import com.android.bluetooth.hid.HidHostService; 123 import com.android.bluetooth.le_audio.LeAudioService; 124 import com.android.bluetooth.map.BluetoothMapService; 125 import com.android.bluetooth.mapclient.MapClientService; 126 import com.android.bluetooth.pan.PanService; 127 import com.android.bluetooth.pbap.BluetoothPbapService; 128 import com.android.bluetooth.pbapclient.PbapClientService; 129 import com.android.bluetooth.sap.SapService; 130 import com.android.bluetooth.sdp.SdpManager; 131 import com.android.bluetooth.telephony.BluetoothInCallService; 132 import com.android.bluetooth.vc.VolumeControlService; 133 import com.android.internal.annotations.GuardedBy; 134 import com.android.internal.annotations.VisibleForTesting; 135 import com.android.modules.utils.BackgroundThread; 136 import com.android.modules.utils.BytesMatcher; 137 import com.android.modules.utils.SynchronousResultReceiver; 138 139 import com.google.protobuf.InvalidProtocolBufferException; 140 141 import libcore.util.SneakyThrow; 142 143 import java.io.FileDescriptor; 144 import java.io.FileOutputStream; 145 import java.io.IOException; 146 import java.io.PrintWriter; 147 import java.time.Duration; 148 import java.util.ArrayDeque; 149 import java.util.ArrayList; 150 import java.util.Arrays; 151 import java.util.HashMap; 152 import java.util.HashSet; 153 import java.util.Iterator; 154 import java.util.List; 155 import java.util.Map; 156 import java.util.Set; 157 import java.util.UUID; 158 import java.util.concurrent.ConcurrentHashMap; 159 import java.util.concurrent.ConcurrentLinkedQueue; 160 import java.util.concurrent.Executor; 161 import java.util.function.Predicate; 162 import java.util.regex.Pattern; 163 164 public class AdapterService extends Service { 165 private static final String TAG = "BluetoothAdapterService"; 166 private static final boolean DBG = true; 167 private static final boolean VERBOSE = false; 168 private static final int MIN_ADVT_INSTANCES_FOR_MA = 5; 169 private static final int MIN_OFFLOADED_FILTERS = 10; 170 private static final int MIN_OFFLOADED_SCAN_STORAGE_BYTES = 1024; 171 private static final Duration PENDING_SOCKET_HANDOFF_TIMEOUT = Duration.ofMinutes(1); 172 private static final Duration GENERATE_LOCAL_OOB_DATA_TIMEOUT = Duration.ofSeconds(2); 173 174 private final Object mEnergyInfoLock = new Object(); 175 private int mStackReportedState; 176 private long mTxTimeTotalMs; 177 private long mRxTimeTotalMs; 178 private long mIdleTimeTotalMs; 179 private long mEnergyUsedTotalVoltAmpSecMicro; 180 private final SparseArray<UidTraffic> mUidTraffic = new SparseArray<>(); 181 182 private final ArrayList<String> mStartedProfiles = new ArrayList<>(); 183 private final ArrayList<ProfileService> mRegisteredProfiles = new ArrayList<>(); 184 private final ArrayList<ProfileService> mRunningProfiles = new ArrayList<>(); 185 186 public static final String ACTION_LOAD_ADAPTER_PROPERTIES = 187 "com.android.bluetooth.btservice.action.LOAD_ADAPTER_PROPERTIES"; 188 public static final String ACTION_SERVICE_STATE_CHANGED = 189 "com.android.bluetooth.btservice.action.STATE_CHANGED"; 190 public static final String EXTRA_ACTION = "action"; 191 public static final int PROFILE_CONN_REJECTED = 2; 192 193 private static final String ACTION_ALARM_WAKEUP = 194 "com.android.bluetooth.btservice.action.ALARM_WAKEUP"; 195 196 static final String BLUETOOTH_BTSNOOP_LOG_MODE_PROPERTY = "persist.bluetooth.btsnooplogmode"; 197 static final String BLUETOOTH_BTSNOOP_DEFAULT_MODE_PROPERTY = 198 "persist.bluetooth.btsnoopdefaultmode"; 199 private String mSnoopLogSettingAtEnable = "empty"; 200 private String mDefaultSnoopLogSettingAtEnable = "empty"; 201 202 public static final String BLUETOOTH_PRIVILEGED = 203 android.Manifest.permission.BLUETOOTH_PRIVILEGED; 204 static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; 205 static final String LOCAL_MAC_ADDRESS_PERM = android.Manifest.permission.LOCAL_MAC_ADDRESS; 206 static final String RECEIVE_MAP_PERM = android.Manifest.permission.RECEIVE_BLUETOOTH_MAP; 207 208 static final String PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE = 209 "phonebook_access_permission"; 210 static final String MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE = 211 "message_access_permission"; 212 static final String SIM_ACCESS_PERMISSION_PREFERENCE_FILE = "sim_access_permission"; 213 214 private static final int CONTROLLER_ENERGY_UPDATE_TIMEOUT_MILLIS = 30; 215 216 public static final String ACTIVITY_ATTRIBUTION_NO_ACTIVE_DEVICE_ADDRESS = 217 "no_active_device_address"; 218 219 // Report ID definition 220 public enum BqrQualityReportId { 221 QUALITY_REPORT_ID_MONITOR_MODE(0x01), 222 QUALITY_REPORT_ID_APPROACH_LSTO(0x02), 223 QUALITY_REPORT_ID_A2DP_AUDIO_CHOPPY(0x03), 224 QUALITY_REPORT_ID_SCO_VOICE_CHOPPY(0x04), 225 QUALITY_REPORT_ID_ROOT_INFLAMMATION(0x05), 226 QUALITY_REPORT_ID_LMP_LL_MESSAGE_TRACE(0x11), 227 QUALITY_REPORT_ID_BT_SCHEDULING_TRACE(0x12), 228 QUALITY_REPORT_ID_CONTROLLER_DBG_INFO(0x13); 229 230 private final int value; BqrQualityReportId(int value)231 private BqrQualityReportId(int value) { 232 this.value = value; 233 } getValue()234 public int getValue() { 235 return value; 236 } 237 }; 238 239 private final ArrayList<DiscoveringPackage> mDiscoveringPackages = new ArrayList<>(); 240 241 static { classInitNative()242 classInitNative(); 243 } 244 245 private static AdapterService sAdapterService; 246 getAdapterService()247 public static synchronized AdapterService getAdapterService() { 248 return sAdapterService; 249 } 250 setAdapterService(AdapterService instance)251 private static synchronized void setAdapterService(AdapterService instance) { 252 Log.d(TAG, "setAdapterService() - trying to set service to " + instance); 253 if (instance == null) { 254 return; 255 } 256 sAdapterService = instance; 257 } 258 clearAdapterService(AdapterService current)259 private static synchronized void clearAdapterService(AdapterService current) { 260 if (sAdapterService == current) { 261 sAdapterService = null; 262 } 263 } 264 265 private BluetoothAdapter mAdapter; 266 @VisibleForTesting 267 AdapterProperties mAdapterProperties; 268 private AdapterState mAdapterStateMachine; 269 private BondStateMachine mBondStateMachine; 270 private JniCallbacks mJniCallbacks; 271 private RemoteDevices mRemoteDevices; 272 273 /* TODO: Consider to remove the search API from this class, if changed to use call-back */ 274 private SdpManager mSdpManager = null; 275 276 private boolean mNativeAvailable; 277 private boolean mCleaningUp; 278 private final HashMap<BluetoothDevice, ArrayList<IBluetoothMetadataListener>> 279 mMetadataListeners = new HashMap<>(); 280 private final HashMap<String, Integer> mProfileServicesState = new HashMap<String, Integer>(); 281 private Set<IBluetoothConnectionCallback> mBluetoothConnectionCallbacks = new HashSet<>(); 282 //Only BluetoothManagerService should be registered 283 private RemoteCallbackList<IBluetoothCallback> mCallbacks; 284 private int mCurrentRequestId; 285 private boolean mQuietmode = false; 286 private HashMap<String, CallerInfo> mBondAttemptCallerInfo = new HashMap<>(); 287 288 private final Map<UUID, RfcommListenerData> mBluetoothServerSockets = new ConcurrentHashMap<>(); 289 private final Executor mSocketServersExecutor = r -> new Thread(r).start(); 290 291 private AlarmManager mAlarmManager; 292 private PendingIntent mPendingAlarm; 293 private BatteryStatsManager mBatteryStatsManager; 294 private PowerManager mPowerManager; 295 private PowerManager.WakeLock mWakeLock; 296 private String mWakeLockName; 297 private UserManager mUserManager; 298 private CompanionDeviceManager mCompanionDeviceManager; 299 300 private PhonePolicy mPhonePolicy; 301 private ActiveDeviceManager mActiveDeviceManager; 302 private DatabaseManager mDatabaseManager; 303 private SilenceDeviceManager mSilenceDeviceManager; 304 private CompanionManager mBtCompanionManager; 305 private AppOpsManager mAppOps; 306 307 private BluetoothSocketManagerBinder mBluetoothSocketManagerBinder; 308 309 private BluetoothKeystoreService mBluetoothKeystoreService; 310 private A2dpService mA2dpService; 311 private A2dpSinkService mA2dpSinkService; 312 private ActivityAttributionService mActivityAttributionService; 313 private HeadsetService mHeadsetService; 314 private HeadsetClientService mHeadsetClientService; 315 private BluetoothMapService mMapService; 316 private MapClientService mMapClientService; 317 private HidDeviceService mHidDeviceService; 318 private HidHostService mHidHostService; 319 private PanService mPanService; 320 private BluetoothPbapService mPbapService; 321 private PbapClientService mPbapClientService; 322 private HearingAidService mHearingAidService; 323 private HapClientService mHapClientService; 324 private SapService mSapService; 325 private VolumeControlService mVolumeControlService; 326 private CsipSetCoordinatorService mCsipSetCoordinatorService; 327 private LeAudioService mLeAudioService; 328 private BassClientService mBassClientService; 329 private BatteryService mBatteryService; 330 331 private volatile boolean mTestModeEnabled = false; 332 333 private MetricsLogger mMetricsLogger; 334 335 /** 336 * Register a {@link ProfileService} with AdapterService. 337 * 338 * @param profile the service being added. 339 */ addProfile(ProfileService profile)340 public void addProfile(ProfileService profile) { 341 mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_REGISTERED, profile).sendToTarget(); 342 } 343 344 /** 345 * Unregister a ProfileService with AdapterService. 346 * 347 * @param profile the service being removed. 348 */ removeProfile(ProfileService profile)349 public void removeProfile(ProfileService profile) { 350 mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_UNREGISTERED, profile).sendToTarget(); 351 } 352 353 /** 354 * Notify AdapterService that a ProfileService has started or stopped. 355 * 356 * @param profile the service being removed. 357 * @param state {@link BluetoothAdapter#STATE_ON} or {@link BluetoothAdapter#STATE_OFF} 358 */ onProfileServiceStateChanged(ProfileService profile, int state)359 public void onProfileServiceStateChanged(ProfileService profile, int state) { 360 if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) { 361 throw new IllegalArgumentException(BluetoothAdapter.nameForState(state)); 362 } 363 Message m = mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_STATE_CHANGED); 364 m.obj = profile; 365 m.arg1 = state; 366 mHandler.sendMessage(m); 367 } 368 369 /** 370 * Confirm whether the ProfileService is started expectedly. 371 * 372 * @param serviceSampleName the service simple name. 373 * @return true if the service is started expectedly, false otherwise. 374 */ isStartedProfile(String serviceSampleName)375 public boolean isStartedProfile(String serviceSampleName) { 376 return mStartedProfiles.contains(serviceSampleName); 377 } 378 379 private static final int MESSAGE_PROFILE_SERVICE_STATE_CHANGED = 1; 380 private static final int MESSAGE_PROFILE_SERVICE_REGISTERED = 2; 381 private static final int MESSAGE_PROFILE_SERVICE_UNREGISTERED = 3; 382 383 class AdapterServiceHandler extends Handler { 384 @Override handleMessage(Message msg)385 public void handleMessage(Message msg) { 386 verboseLog("handleMessage() - Message: " + msg.what); 387 388 switch (msg.what) { 389 case MESSAGE_PROFILE_SERVICE_STATE_CHANGED: 390 verboseLog("handleMessage() - MESSAGE_PROFILE_SERVICE_STATE_CHANGED"); 391 processProfileServiceStateChanged((ProfileService) msg.obj, msg.arg1); 392 break; 393 case MESSAGE_PROFILE_SERVICE_REGISTERED: 394 verboseLog("handleMessage() - MESSAGE_PROFILE_SERVICE_REGISTERED"); 395 registerProfileService((ProfileService) msg.obj); 396 break; 397 case MESSAGE_PROFILE_SERVICE_UNREGISTERED: 398 verboseLog("handleMessage() - MESSAGE_PROFILE_SERVICE_UNREGISTERED"); 399 unregisterProfileService((ProfileService) msg.obj); 400 break; 401 } 402 } 403 registerProfileService(ProfileService profile)404 private void registerProfileService(ProfileService profile) { 405 if (mRegisteredProfiles.contains(profile)) { 406 Log.e(TAG, profile.getName() + " already registered."); 407 return; 408 } 409 mRegisteredProfiles.add(profile); 410 } 411 unregisterProfileService(ProfileService profile)412 private void unregisterProfileService(ProfileService profile) { 413 if (!mRegisteredProfiles.contains(profile)) { 414 Log.e(TAG, profile.getName() + " not registered (UNREGISTER)."); 415 return; 416 } 417 mRegisteredProfiles.remove(profile); 418 } 419 processProfileServiceStateChanged(ProfileService profile, int state)420 private void processProfileServiceStateChanged(ProfileService profile, int state) { 421 switch (state) { 422 case BluetoothAdapter.STATE_ON: 423 if (!mRegisteredProfiles.contains(profile)) { 424 Log.e(TAG, profile.getName() + " not registered (STATE_ON)."); 425 return; 426 } 427 if (mRunningProfiles.contains(profile)) { 428 Log.e(TAG, profile.getName() + " already running."); 429 return; 430 } 431 mRunningProfiles.add(profile); 432 // TODO(b/228875190): GATT is assumed supported. GATT starting triggers hardware 433 // initializtion. Configuring a device without GATT causes start up failures. 434 if (GattService.class.getSimpleName().equals(profile.getName())) { 435 enableNative(); 436 } else if (mRegisteredProfiles.size() == Config.getSupportedProfiles().length 437 && mRegisteredProfiles.size() == mRunningProfiles.size()) { 438 mAdapterProperties.onBluetoothReady(); 439 updateUuids(); 440 setBluetoothClassFromConfig(); 441 initProfileServices(); 442 getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_LOCAL_IO_CAPS); 443 getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_LOCAL_IO_CAPS_BLE); 444 getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_DYNAMIC_AUDIO_BUFFER); 445 mAdapterStateMachine.sendMessage(AdapterState.BREDR_STARTED); 446 mBtCompanionManager.loadCompanionInfo(); 447 } 448 break; 449 case BluetoothAdapter.STATE_OFF: 450 if (!mRegisteredProfiles.contains(profile)) { 451 Log.e(TAG, profile.getName() + " not registered (STATE_OFF)."); 452 return; 453 } 454 if (!mRunningProfiles.contains(profile)) { 455 Log.e(TAG, profile.getName() + " not running."); 456 return; 457 } 458 mRunningProfiles.remove(profile); 459 // TODO(b/228875190): GATT is assumed supported. GATT is expected to be the only 460 // profile available in the "BLE ON" state. If only GATT is left, send 461 // BREDR_STOPPED. If GATT is stopped, deinitialize the hardware. 462 if ((mRunningProfiles.size() == 1 && (GattService.class.getSimpleName() 463 .equals(mRunningProfiles.get(0).getName())))) { 464 mAdapterStateMachine.sendMessage(AdapterState.BREDR_STOPPED); 465 } else if (mRunningProfiles.size() == 0) { 466 disableNative(); 467 } 468 break; 469 default: 470 Log.e(TAG, "Unhandled profile state: " + state); 471 } 472 } 473 } 474 475 private final AdapterServiceHandler mHandler = new AdapterServiceHandler(); 476 477 @Override onCreate()478 public void onCreate() { 479 super.onCreate(); 480 initMetricsLogger(); 481 debugLog("onCreate()"); 482 mDeviceConfigListener.start(); 483 mRemoteDevices = new RemoteDevices(this, Looper.getMainLooper()); 484 mRemoteDevices.init(); 485 clearDiscoveringPackages(); 486 mBinder = new AdapterServiceBinder(this); 487 mAdapter = BluetoothAdapter.getDefaultAdapter(); 488 mAdapterProperties = new AdapterProperties(this); 489 mAdapterStateMachine = AdapterState.make(this); 490 mJniCallbacks = new JniCallbacks(this, mAdapterProperties); 491 mBluetoothKeystoreService = new BluetoothKeystoreService(isCommonCriteriaMode()); 492 mBluetoothKeystoreService.start(); 493 int configCompareResult = mBluetoothKeystoreService.getCompareResult(); 494 495 // Start tracking Binder latency for the bluetooth process. 496 BluetoothFrameworkInitializer.initializeBinderCallsStats(getApplicationContext()); 497 498 // Android TV doesn't show consent dialogs for just works and encryption only le pairing 499 boolean isAtvDevice = getApplicationContext().getPackageManager().hasSystemFeature( 500 PackageManager.FEATURE_LEANBACK_ONLY); 501 mUserManager = getSystemService(UserManager.class); 502 initNative(mUserManager.isGuestUser(), isCommonCriteriaMode(), configCompareResult, 503 getInitFlags(), isAtvDevice, getApplicationInfo().dataDir); 504 mNativeAvailable = true; 505 mCallbacks = new RemoteCallbackList<IBluetoothCallback>(); 506 mAppOps = getSystemService(AppOpsManager.class); 507 //Load the name and address 508 getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDADDR); 509 getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDNAME); 510 getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_CLASS_OF_DEVICE); 511 mAlarmManager = getSystemService(AlarmManager.class); 512 mPowerManager = getSystemService(PowerManager.class); 513 mBatteryStatsManager = getSystemService(BatteryStatsManager.class); 514 mCompanionDeviceManager = getSystemService(CompanionDeviceManager.class); 515 516 mBluetoothKeystoreService.initJni(); 517 518 mSdpManager = SdpManager.init(this); 519 registerReceiver(mAlarmBroadcastReceiver, new IntentFilter(ACTION_ALARM_WAKEUP)); 520 521 mDatabaseManager = new DatabaseManager(this); 522 mDatabaseManager.start(MetadataDatabase.createDatabase(this)); 523 524 boolean isAutomotiveDevice = getApplicationContext().getPackageManager().hasSystemFeature( 525 PackageManager.FEATURE_AUTOMOTIVE); 526 527 /* 528 * Phone policy is specific to phone implementations and hence if a device wants to exclude 529 * it out then it can be disabled by using the flag below. Phone policy is never used on 530 * Android Automotive OS builds, in favor of a policy currently located in 531 * CarBluetoothService. 532 */ 533 if (!isAutomotiveDevice && getResources().getBoolean(R.bool.enable_phone_policy)) { 534 Log.i(TAG, "Phone policy enabled"); 535 mPhonePolicy = new PhonePolicy(this, new ServiceFactory()); 536 mPhonePolicy.start(); 537 } else { 538 Log.i(TAG, "Phone policy disabled"); 539 } 540 541 mActiveDeviceManager = new ActiveDeviceManager(this, new ServiceFactory()); 542 mActiveDeviceManager.start(); 543 544 mSilenceDeviceManager = new SilenceDeviceManager(this, new ServiceFactory(), 545 Looper.getMainLooper()); 546 mSilenceDeviceManager.start(); 547 548 mBtCompanionManager = new CompanionManager(this, new ServiceFactory()); 549 550 mBluetoothSocketManagerBinder = new BluetoothSocketManagerBinder(this); 551 552 mActivityAttributionService = new ActivityAttributionService(); 553 mActivityAttributionService.start(); 554 555 setAdapterService(this); 556 557 invalidateBluetoothCaches(); 558 559 // First call to getSharedPreferences will result in a file read into 560 // memory cache. Call it here asynchronously to avoid potential ANR 561 // in the future 562 new AsyncTask<Void, Void, Void>() { 563 @Override 564 protected Void doInBackground(Void... params) { 565 getSharedPreferences(PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE, 566 Context.MODE_PRIVATE); 567 getSharedPreferences(MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE, 568 Context.MODE_PRIVATE); 569 getSharedPreferences(SIM_ACCESS_PERMISSION_PREFERENCE_FILE, Context.MODE_PRIVATE); 570 return null; 571 } 572 }.execute(); 573 574 try { 575 int systemUiUid = getApplicationContext() 576 .createContextAsUser(UserHandle.SYSTEM, /* flags= */ 0) 577 .getPackageManager() 578 .getPackageUid("com.android.systemui", PackageManager.MATCH_SYSTEM_ONLY); 579 580 Utils.setSystemUiUid(systemUiUid); 581 } catch (PackageManager.NameNotFoundException e) { 582 // Some platforms, such as wearables do not have a system ui. 583 Log.w(TAG, "Unable to resolve SystemUI's UID.", e); 584 } 585 } 586 587 @Override onBind(Intent intent)588 public IBinder onBind(Intent intent) { 589 debugLog("onBind()"); 590 return mBinder; 591 } 592 593 @Override onUnbind(Intent intent)594 public boolean onUnbind(Intent intent) { 595 debugLog("onUnbind() - calling cleanup"); 596 cleanup(); 597 return super.onUnbind(intent); 598 } 599 600 @Override onDestroy()601 public void onDestroy() { 602 debugLog("onDestroy()"); 603 if (!isMock()) { 604 // TODO(b/27859763) 605 Log.i(TAG, "Force exit to cleanup internal state in Bluetooth stack"); 606 System.exit(0); 607 } 608 } 609 initMetricsLogger()610 private boolean initMetricsLogger() { 611 if (mMetricsLogger != null) { 612 return false; 613 } 614 mMetricsLogger = MetricsLogger.getInstance(); 615 return mMetricsLogger.init(this); 616 } 617 closeMetricsLogger()618 private boolean closeMetricsLogger() { 619 if (mMetricsLogger == null) { 620 return false; 621 } 622 boolean result = mMetricsLogger.close(); 623 mMetricsLogger = null; 624 return result; 625 } 626 setMetricsLogger(MetricsLogger metricsLogger)627 public void setMetricsLogger(MetricsLogger metricsLogger) { 628 mMetricsLogger = metricsLogger; 629 } 630 bringUpBle()631 void bringUpBle() { 632 debugLog("bleOnProcessStart()"); 633 634 if (getResources().getBoolean( 635 R.bool.config_bluetooth_reload_supported_profiles_when_enabled)) { 636 Config.init(getApplicationContext()); 637 } 638 639 // Reset |mRemoteDevices| whenever BLE is turned off then on 640 // This is to replace the fact that |mRemoteDevices| was 641 // reinitialized in previous code. 642 // 643 // TODO(apanicke): The reason is unclear but 644 // I believe it is to clear the variable every time BLE was 645 // turned off then on. The same effect can be achieved by 646 // calling cleanup but this may not be necessary at all 647 // We should figure out why this is needed later 648 mRemoteDevices.reset(); 649 mAdapterProperties.init(mRemoteDevices); 650 651 debugLog("bleOnProcessStart() - Make Bond State Machine"); 652 mBondStateMachine = BondStateMachine.make(this, mAdapterProperties, mRemoteDevices); 653 654 mJniCallbacks.init(mBondStateMachine, mRemoteDevices); 655 656 mBatteryStatsManager.reportBleScanReset(); 657 BluetoothStatsLog.write_non_chained(BluetoothStatsLog.BLE_SCAN_STATE_CHANGED, -1, null, 658 BluetoothStatsLog.BLE_SCAN_STATE_CHANGED__STATE__RESET, false, false, false); 659 660 // TODO(b/228875190): GATT is assumed supported. As a result, we don't respect the 661 // configuration sysprop. Configuring a device without GATT, although rare, will cause stack 662 // start up errors yielding init loops. 663 if (!GattService.isEnabled()) { 664 Log.w(TAG, 665 "GATT is configured off but the stack assumes it to be enabled. Start anyway."); 666 } 667 setProfileServiceState(GattService.class, BluetoothAdapter.STATE_ON); 668 } 669 bringDownBle()670 void bringDownBle() { 671 stopGattProfileService(); 672 } 673 stateChangeCallback(int status)674 void stateChangeCallback(int status) { 675 if (status == AbstractionLayer.BT_STATE_OFF) { 676 debugLog("stateChangeCallback: disableNative() completed"); 677 mAdapterStateMachine.sendMessage(AdapterState.BLE_STOPPED); 678 } else if (status == AbstractionLayer.BT_STATE_ON) { 679 mAdapterStateMachine.sendMessage(AdapterState.BLE_STARTED); 680 } else { 681 Log.e(TAG, "Incorrect status " + status + " in stateChangeCallback"); 682 } 683 } 684 685 /** 686 * Sets the Bluetooth CoD value of the local adapter if there exists a config value for it. 687 */ setBluetoothClassFromConfig()688 void setBluetoothClassFromConfig() { 689 int bluetoothClassConfig = retrieveBluetoothClassConfig(); 690 if (bluetoothClassConfig != 0) { 691 mAdapterProperties.setBluetoothClass(new BluetoothClass(bluetoothClassConfig)); 692 } 693 } 694 retrieveBluetoothClassConfig()695 private int retrieveBluetoothClassConfig() { 696 return Settings.Global.getInt( 697 getContentResolver(), Settings.Global.BLUETOOTH_CLASS_OF_DEVICE, 0); 698 } 699 startProfileServices()700 void startProfileServices() { 701 debugLog("startCoreServices()"); 702 Class[] supportedProfileServices = Config.getSupportedProfiles(); 703 // TODO(b/228875190): GATT is assumed supported. If we support no other profiles then just 704 // move on to BREDR_STARTED. Note that configuring GATT to NOT supported will cause adapter 705 // initialization failures 706 if (supportedProfileServices.length == 1 && GattService.class.getSimpleName() 707 .equals(supportedProfileServices[0].getSimpleName())) { 708 mAdapterProperties.onBluetoothReady(); 709 updateUuids(); 710 setBluetoothClassFromConfig(); 711 mAdapterStateMachine.sendMessage(AdapterState.BREDR_STARTED); 712 } else { 713 setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_ON); 714 } 715 } 716 stopProfileServices()717 void stopProfileServices() { 718 // Make sure to stop classic background tasks now 719 cancelDiscoveryNative(); 720 mAdapterProperties.setScanMode(BluetoothAdapter.SCAN_MODE_NONE); 721 722 Class[] supportedProfileServices = Config.getSupportedProfiles(); 723 // TODO(b/228875190): GATT is assumed supported. If we support no profiles then just move on 724 // to BREDR_STOPPED 725 if (supportedProfileServices.length == 1 && (mRunningProfiles.size() == 1 726 && GattService.class.getSimpleName().equals(mRunningProfiles.get(0).getName()))) { 727 debugLog("stopProfileServices() - No profiles services to stop or already stopped."); 728 mAdapterStateMachine.sendMessage(AdapterState.BREDR_STOPPED); 729 } else { 730 setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_OFF); 731 } 732 } 733 stopGattProfileService()734 private void stopGattProfileService() { 735 mAdapterProperties.onBleDisable(); 736 if (mRunningProfiles.size() == 0) { 737 debugLog("stopGattProfileService() - No profiles services to stop."); 738 mAdapterStateMachine.sendMessage(AdapterState.BLE_STOPPED); 739 } 740 setProfileServiceState(GattService.class, BluetoothAdapter.STATE_OFF); 741 } 742 invalidateBluetoothGetStateCache()743 private void invalidateBluetoothGetStateCache() { 744 BluetoothAdapter.invalidateBluetoothGetStateCache(); 745 } 746 updateLeAudioProfileServiceState()747 void updateLeAudioProfileServiceState() { 748 HashSet<Class> nonSupportedProfiles = new HashSet<>(); 749 750 if (!isLeConnectedIsochronousStreamCentralSupported()) { 751 nonSupportedProfiles.addAll(Config.geLeAudioUnicastProfiles()); 752 } 753 754 if (!isLeAudioBroadcastAssistantSupported()) { 755 nonSupportedProfiles.add(BassClientService.class); 756 } 757 758 if (!isLeAudioBroadcastSourceSupported()) { 759 Config.updateSupportedProfileMask( 760 false, LeAudioService.class, BluetoothProfile.LE_AUDIO_BROADCAST); 761 } 762 763 if (!nonSupportedProfiles.isEmpty()) { 764 // Remove non-supported profiles from the supported list 765 // since the controller doesn't support 766 Config.removeProfileFromSupportedList(nonSupportedProfiles); 767 768 // Disable the non-supported profiles service 769 for (Class profileService : nonSupportedProfiles) { 770 if (isStartedProfile(profileService.getSimpleName())) { 771 setProfileServiceState(profileService, BluetoothAdapter.STATE_OFF); 772 } 773 } 774 } 775 } 776 updateAdapterState(int prevState, int newState)777 void updateAdapterState(int prevState, int newState) { 778 mAdapterProperties.setState(newState); 779 invalidateBluetoothGetStateCache(); 780 if (mCallbacks != null) { 781 int n = mCallbacks.beginBroadcast(); 782 debugLog("updateAdapterState() - Broadcasting state " + BluetoothAdapter.nameForState( 783 newState) + " to " + n + " receivers."); 784 for (int i = 0; i < n; i++) { 785 try { 786 mCallbacks.getBroadcastItem(i).onBluetoothStateChange(prevState, newState); 787 } catch (RemoteException e) { 788 debugLog("updateAdapterState() - Callback #" + i + " failed (" + e + ")"); 789 } 790 } 791 mCallbacks.finishBroadcast(); 792 } 793 794 // Turn the Adapter all the way off if we are disabling and the snoop log setting changed. 795 if (newState == BluetoothAdapter.STATE_BLE_TURNING_ON) { 796 mSnoopLogSettingAtEnable = 797 SystemProperties.get(BLUETOOTH_BTSNOOP_LOG_MODE_PROPERTY, "empty"); 798 mDefaultSnoopLogSettingAtEnable = 799 Settings.Global.getString(getContentResolver(), 800 Settings.Global.BLUETOOTH_BTSNOOP_DEFAULT_MODE); 801 BluetoothProperties.snoop_default_mode( 802 BluetoothProperties.snoop_default_mode_values.DISABLED); 803 for (BluetoothProperties.snoop_default_mode_values value : 804 BluetoothProperties.snoop_default_mode_values.values()) { 805 if (value.getPropValue().equals(mDefaultSnoopLogSettingAtEnable)) { 806 BluetoothProperties.snoop_default_mode(value); 807 } 808 } 809 } else if (newState == BluetoothAdapter.STATE_BLE_ON 810 && prevState != BluetoothAdapter.STATE_OFF) { 811 String snoopLogSetting = 812 SystemProperties.get(BLUETOOTH_BTSNOOP_LOG_MODE_PROPERTY, "empty"); 813 String snoopDefaultModeSetting = 814 Settings.Global.getString(getContentResolver(), 815 Settings.Global.BLUETOOTH_BTSNOOP_DEFAULT_MODE); 816 817 if (!TextUtils.equals(mSnoopLogSettingAtEnable, snoopLogSetting) 818 || !TextUtils.equals(mDefaultSnoopLogSettingAtEnable, 819 snoopDefaultModeSetting)) { 820 mAdapterStateMachine.sendMessage(AdapterState.BLE_TURN_OFF); 821 } 822 } 823 } 824 linkQualityReportCallback( long timestamp, int reportId, int rssi, int snr, int retransmissionCount, int packetsNotReceiveCount, int negativeAcknowledgementCount)825 void linkQualityReportCallback( 826 long timestamp, 827 int reportId, 828 int rssi, 829 int snr, 830 int retransmissionCount, 831 int packetsNotReceiveCount, 832 int negativeAcknowledgementCount) { 833 BluetoothInCallService bluetoothInCallService = BluetoothInCallService.getInstance(); 834 835 if (reportId == BqrQualityReportId.QUALITY_REPORT_ID_SCO_VOICE_CHOPPY.getValue()) { 836 if (bluetoothInCallService == null) { 837 Log.w(TAG, "No BluetoothInCallService while trying to send BQR." 838 + " timestamp: " + timestamp + " reportId: " + reportId 839 + " rssi: " + rssi + " snr: " + snr 840 + " retransmissionCount: " + retransmissionCount 841 + " packetsNotReceiveCount: " + packetsNotReceiveCount 842 + " negativeAcknowledgementCount: " + negativeAcknowledgementCount); 843 return; 844 } 845 bluetoothInCallService.sendBluetoothCallQualityReport( 846 timestamp, rssi, snr, retransmissionCount, 847 packetsNotReceiveCount, negativeAcknowledgementCount); 848 } 849 } 850 switchBufferSizeCallback(boolean isLowLatencyBufferSize)851 void switchBufferSizeCallback(boolean isLowLatencyBufferSize) { 852 List<BluetoothDevice> activeDevices = getActiveDevices(BluetoothProfile.A2DP); 853 if (activeDevices.size() != 1) { 854 errorLog( 855 "Cannot switch buffer size. The number of A2DP active devices is " 856 + activeDevices.size()); 857 } 858 859 // Send intent to fastpair 860 Intent switchBufferSizeIntent = new Intent(BluetoothDevice.ACTION_SWITCH_BUFFER_SIZE); 861 switchBufferSizeIntent.setClassName( 862 getString(com.android.bluetooth.R.string.peripheral_link_package), 863 getString(com.android.bluetooth.R.string.peripheral_link_package) 864 + getString(com.android.bluetooth.R.string.peripheral_link_service)); 865 switchBufferSizeIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, activeDevices.get(0)); 866 switchBufferSizeIntent.putExtra( 867 BluetoothDevice.EXTRA_LOW_LATENCY_BUFFER_SIZE, isLowLatencyBufferSize); 868 sendBroadcast(switchBufferSizeIntent); 869 } 870 switchCodecCallback(boolean isLowLatencyBufferSize)871 void switchCodecCallback(boolean isLowLatencyBufferSize) { 872 List<BluetoothDevice> activeDevices = getActiveDevices(BluetoothProfile.A2DP); 873 if (activeDevices.size() != 1) { 874 errorLog( 875 "Cannot switch buffer size. The number of A2DP active devices is " 876 + activeDevices.size()); 877 return; 878 } 879 mA2dpService.switchCodecByBufferSize(activeDevices.get(0), isLowLatencyBufferSize); 880 } 881 cleanup()882 void cleanup() { 883 debugLog("cleanup()"); 884 if (mCleaningUp) { 885 errorLog("cleanup() - Service already starting to cleanup, ignoring request..."); 886 return; 887 } 888 889 closeMetricsLogger(); 890 891 clearAdapterService(this); 892 893 mCleaningUp = true; 894 invalidateBluetoothCaches(); 895 896 unregisterReceiver(mAlarmBroadcastReceiver); 897 898 stopRfcommServerSockets(); 899 900 if (mPendingAlarm != null) { 901 mAlarmManager.cancel(mPendingAlarm); 902 mPendingAlarm = null; 903 } 904 905 // This wake lock release may also be called concurrently by 906 // {@link #releaseWakeLock(String lockName)}, so a synchronization is needed here. 907 synchronized (this) { 908 if (mWakeLock != null) { 909 if (mWakeLock.isHeld()) { 910 mWakeLock.release(); 911 } 912 mWakeLock = null; 913 } 914 } 915 916 if (mDatabaseManager != null) { 917 mDatabaseManager.cleanup(); 918 } 919 920 if (mAdapterStateMachine != null) { 921 mAdapterStateMachine.doQuit(); 922 } 923 924 if (mBondStateMachine != null) { 925 mBondStateMachine.doQuit(); 926 } 927 928 if (mRemoteDevices != null) { 929 mRemoteDevices.cleanup(); 930 } 931 932 if (mSdpManager != null) { 933 mSdpManager.cleanup(); 934 mSdpManager = null; 935 } 936 937 if (mActivityAttributionService != null) { 938 mActivityAttributionService.cleanup(); 939 } 940 941 if (mNativeAvailable) { 942 debugLog("cleanup() - Cleaning up adapter native"); 943 cleanupNative(); 944 mNativeAvailable = false; 945 } 946 947 if (mAdapterProperties != null) { 948 mAdapterProperties.cleanup(); 949 } 950 951 if (mJniCallbacks != null) { 952 mJniCallbacks.cleanup(); 953 } 954 955 if (mBluetoothKeystoreService != null) { 956 debugLog("cleanup(): mBluetoothKeystoreService.cleanup()"); 957 mBluetoothKeystoreService.cleanup(); 958 } 959 960 if (mPhonePolicy != null) { 961 mPhonePolicy.cleanup(); 962 } 963 964 if (mSilenceDeviceManager != null) { 965 mSilenceDeviceManager.cleanup(); 966 } 967 968 if (mActiveDeviceManager != null) { 969 mActiveDeviceManager.cleanup(); 970 } 971 972 if (mProfileServicesState != null) { 973 mProfileServicesState.clear(); 974 } 975 976 if (mBluetoothSocketManagerBinder != null) { 977 mBluetoothSocketManagerBinder.cleanUp(); 978 mBluetoothSocketManagerBinder = null; 979 } 980 981 if (mBinder != null) { 982 mBinder.cleanup(); 983 mBinder = null; //Do not remove. Otherwise Binder leak! 984 } 985 986 if (mCallbacks != null) { 987 mCallbacks.kill(); 988 } 989 } 990 invalidateBluetoothCaches()991 private void invalidateBluetoothCaches() { 992 BluetoothAdapter.invalidateGetProfileConnectionStateCache(); 993 BluetoothAdapter.invalidateIsOffloadedFilteringSupportedCache(); 994 BluetoothDevice.invalidateBluetoothGetBondStateCache(); 995 BluetoothAdapter.invalidateBluetoothGetStateCache(); 996 BluetoothAdapter.invalidateGetAdapterConnectionStateCache(); 997 BluetoothMap.invalidateBluetoothGetConnectionStateCache(); 998 BluetoothSap.invalidateBluetoothGetConnectionStateCache(); 999 } 1000 setProfileServiceState(Class service, int state)1001 private void setProfileServiceState(Class service, int state) { 1002 if (state == BluetoothAdapter.STATE_ON) { 1003 mStartedProfiles.add(service.getSimpleName()); 1004 } else if (state == BluetoothAdapter.STATE_OFF) { 1005 mStartedProfiles.remove(service.getSimpleName()); 1006 } 1007 Intent intent = new Intent(this, service); 1008 intent.putExtra(EXTRA_ACTION, ACTION_SERVICE_STATE_CHANGED); 1009 intent.putExtra(BluetoothAdapter.EXTRA_STATE, state); 1010 startService(intent); 1011 } 1012 setAllProfileServiceStates(Class[] services, int state)1013 private void setAllProfileServiceStates(Class[] services, int state) { 1014 for (Class service : services) { 1015 // TODO(b/228875190): GATT is assumed supported and treated differently as part of the 1016 // "BLE ON" state, despite GATT not being BLE specific. 1017 if (GattService.class.getSimpleName().equals(service.getSimpleName())) { 1018 continue; 1019 } 1020 setProfileServiceState(service, state); 1021 } 1022 } 1023 1024 /** 1025 * Verifies whether the profile is supported by the local bluetooth adapter by checking a 1026 * bitmask of its supported profiles 1027 * 1028 * @param remoteDeviceUuids is an array of all supported profiles by the remote device 1029 * @param localDeviceUuids is an array of all supported profiles by the local device 1030 * @param profile is the profile we are checking for support 1031 * @param device is the remote device we wish to connect to 1032 * @return true if the profile is supported by both the local and remote device, false otherwise 1033 */ 1034 @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) isSupported(ParcelUuid[] localDeviceUuids, ParcelUuid[] remoteDeviceUuids, int profile, BluetoothDevice device)1035 private boolean isSupported(ParcelUuid[] localDeviceUuids, ParcelUuid[] remoteDeviceUuids, 1036 int profile, BluetoothDevice device) { 1037 if (remoteDeviceUuids == null || remoteDeviceUuids.length == 0) { 1038 Log.e(TAG, "isSupported: Remote Device Uuids Empty"); 1039 } 1040 1041 if (profile == BluetoothProfile.HEADSET) { 1042 return (Utils.arrayContains(localDeviceUuids, BluetoothUuid.HSP_AG) 1043 && Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HSP)) 1044 || (Utils.arrayContains(localDeviceUuids, BluetoothUuid.HFP_AG) 1045 && Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HFP)); 1046 } 1047 if (profile == BluetoothProfile.HEADSET_CLIENT) { 1048 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HFP_AG) 1049 && Utils.arrayContains(localDeviceUuids, BluetoothUuid.HFP); 1050 } 1051 if (profile == BluetoothProfile.A2DP) { 1052 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.ADV_AUDIO_DIST) 1053 || Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.A2DP_SINK); 1054 } 1055 if (profile == BluetoothProfile.A2DP_SINK) { 1056 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.ADV_AUDIO_DIST) 1057 || Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.A2DP_SOURCE); 1058 } 1059 if (profile == BluetoothProfile.OPP) { 1060 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.OBEX_OBJECT_PUSH); 1061 } 1062 if (profile == BluetoothProfile.HID_HOST) { 1063 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HID) 1064 || Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HOGP); 1065 } 1066 if (profile == BluetoothProfile.HID_DEVICE) { 1067 return mHidDeviceService.getConnectionState(device) 1068 == BluetoothProfile.STATE_DISCONNECTED; 1069 } 1070 if (profile == BluetoothProfile.PAN) { 1071 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.NAP); 1072 } 1073 if (profile == BluetoothProfile.MAP) { 1074 return mMapService.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED; 1075 } 1076 if (profile == BluetoothProfile.PBAP) { 1077 return mPbapService.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED; 1078 } 1079 if (profile == BluetoothProfile.MAP_CLIENT) { 1080 return true; 1081 } 1082 if (profile == BluetoothProfile.PBAP_CLIENT) { 1083 return Utils.arrayContains(localDeviceUuids, BluetoothUuid.PBAP_PCE) 1084 && Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.PBAP_PSE); 1085 } 1086 if (profile == BluetoothProfile.HEARING_AID) { 1087 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HEARING_AID); 1088 } 1089 if (profile == BluetoothProfile.SAP) { 1090 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.SAP); 1091 } 1092 if (profile == BluetoothProfile.VOLUME_CONTROL) { 1093 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.VOLUME_CONTROL); 1094 } 1095 if (profile == BluetoothProfile.CSIP_SET_COORDINATOR) { 1096 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.COORDINATED_SET); 1097 } 1098 if (profile == BluetoothProfile.LE_AUDIO) { 1099 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.LE_AUDIO); 1100 } 1101 if (profile == BluetoothProfile.HAP_CLIENT) { 1102 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HAS); 1103 } 1104 if (profile == BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT) { 1105 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.BASS); 1106 } 1107 if (profile == BluetoothProfile.BATTERY) { 1108 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.BATTERY); 1109 } 1110 1111 Log.e(TAG, "isSupported: Unexpected profile passed in to function: " + profile); 1112 return false; 1113 } 1114 1115 /** 1116 * Checks if any profile is enabled for the given device 1117 * 1118 * @param device is the device for which we are checking if any profiles are enabled 1119 * @return true if any profile is enabled, false otherwise 1120 */ 1121 @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) isAnyProfileEnabled(BluetoothDevice device)1122 boolean isAnyProfileEnabled(BluetoothDevice device) { 1123 if (mA2dpService != null && mA2dpService.getConnectionPolicy(device) 1124 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1125 return true; 1126 } 1127 if (mA2dpSinkService != null && mA2dpSinkService.getConnectionPolicy(device) 1128 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1129 return true; 1130 } 1131 if (mHeadsetService != null && mHeadsetService.getConnectionPolicy(device) 1132 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1133 return true; 1134 } 1135 if (mHeadsetClientService != null && mHeadsetClientService.getConnectionPolicy(device) 1136 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1137 return true; 1138 } 1139 if (mMapClientService != null && mMapClientService.getConnectionPolicy(device) 1140 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1141 return true; 1142 } 1143 if (mHidHostService != null && mHidHostService.getConnectionPolicy(device) 1144 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1145 return true; 1146 } 1147 if (mPanService != null && mPanService.getConnectionPolicy(device) 1148 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1149 return true; 1150 } 1151 if (mPbapClientService != null && mPbapClientService.getConnectionPolicy(device) 1152 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1153 return true; 1154 } 1155 if (mHearingAidService != null && mHearingAidService.getConnectionPolicy(device) 1156 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1157 return true; 1158 } 1159 if (mHapClientService != null && mHapClientService.getConnectionPolicy(device) 1160 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1161 return true; 1162 } 1163 if (mVolumeControlService != null && mVolumeControlService.getConnectionPolicy(device) 1164 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1165 return true; 1166 } 1167 if (mCsipSetCoordinatorService != null 1168 && mCsipSetCoordinatorService.getConnectionPolicy(device) 1169 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1170 return true; 1171 } 1172 if (mLeAudioService != null && mLeAudioService.getConnectionPolicy(device) 1173 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1174 return true; 1175 } 1176 if (mBassClientService != null && mBassClientService.getConnectionPolicy(device) 1177 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1178 return true; 1179 } 1180 if (mBatteryService != null && mBatteryService.getConnectionPolicy(device) 1181 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1182 return true; 1183 } 1184 return false; 1185 } 1186 1187 /** 1188 * Connects only available profiles 1189 * (those with {@link BluetoothProfile#CONNECTION_POLICY_ALLOWED}) 1190 * 1191 * @param device is the device with which we are connecting the profiles 1192 * @return {@link BluetoothStatusCodes#SUCCESS} 1193 */ 1194 @RequiresPermission(allOf = { 1195 android.Manifest.permission.BLUETOOTH_PRIVILEGED, 1196 android.Manifest.permission.MODIFY_PHONE_STATE, 1197 }) connectEnabledProfiles(BluetoothDevice device)1198 private int connectEnabledProfiles(BluetoothDevice device) { 1199 ParcelUuid[] remoteDeviceUuids = getRemoteUuids(device); 1200 ParcelUuid[] localDeviceUuids = mAdapterProperties.getUuids(); 1201 1202 if (mA2dpService != null && isSupported(localDeviceUuids, remoteDeviceUuids, 1203 BluetoothProfile.A2DP, device) && mA2dpService.getConnectionPolicy(device) 1204 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1205 Log.i(TAG, "connectEnabledProfiles: Connecting A2dp"); 1206 mA2dpService.connect(device); 1207 } 1208 if (mA2dpSinkService != null && isSupported(localDeviceUuids, remoteDeviceUuids, 1209 BluetoothProfile.A2DP_SINK, device) && mA2dpSinkService.getConnectionPolicy(device) 1210 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1211 Log.i(TAG, "connectEnabledProfiles: Connecting A2dp Sink"); 1212 mA2dpSinkService.connect(device); 1213 } 1214 if (mHeadsetService != null && isSupported(localDeviceUuids, remoteDeviceUuids, 1215 BluetoothProfile.HEADSET, device) && mHeadsetService.getConnectionPolicy(device) 1216 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1217 Log.i(TAG, "connectEnabledProfiles: Connecting Headset Profile"); 1218 mHeadsetService.connect(device); 1219 } 1220 if (mHeadsetClientService != null && isSupported(localDeviceUuids, remoteDeviceUuids, 1221 BluetoothProfile.HEADSET_CLIENT, device) 1222 && mHeadsetClientService.getConnectionPolicy(device) 1223 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1224 Log.i(TAG, "connectEnabledProfiles: Connecting HFP"); 1225 mHeadsetClientService.connect(device); 1226 } 1227 if (mMapClientService != null && isSupported(localDeviceUuids, remoteDeviceUuids, 1228 BluetoothProfile.MAP_CLIENT, device) 1229 && mMapClientService.getConnectionPolicy(device) 1230 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1231 Log.i(TAG, "connectEnabledProfiles: Connecting MAP"); 1232 mMapClientService.connect(device); 1233 } 1234 if (mHidHostService != null && isSupported(localDeviceUuids, remoteDeviceUuids, 1235 BluetoothProfile.HID_HOST, device) && mHidHostService.getConnectionPolicy(device) 1236 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1237 Log.i(TAG, "connectEnabledProfiles: Connecting Hid Host Profile"); 1238 mHidHostService.connect(device); 1239 } 1240 if (mPanService != null && isSupported(localDeviceUuids, remoteDeviceUuids, 1241 BluetoothProfile.PAN, device) && mPanService.getConnectionPolicy(device) 1242 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1243 Log.i(TAG, "connectEnabledProfiles: Connecting Pan Profile"); 1244 mPanService.connect(device); 1245 } 1246 if (mPbapClientService != null && isSupported(localDeviceUuids, remoteDeviceUuids, 1247 BluetoothProfile.PBAP_CLIENT, device) 1248 && mPbapClientService.getConnectionPolicy(device) 1249 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1250 Log.i(TAG, "connectEnabledProfiles: Connecting Pbap"); 1251 mPbapClientService.connect(device); 1252 } 1253 if (mHearingAidService != null && isSupported(localDeviceUuids, remoteDeviceUuids, 1254 BluetoothProfile.HEARING_AID, device) 1255 && mHearingAidService.getConnectionPolicy(device) 1256 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1257 Log.i(TAG, "connectEnabledProfiles: Connecting Hearing Aid Profile"); 1258 mHearingAidService.connect(device); 1259 } 1260 if (mHapClientService != null && isSupported(localDeviceUuids, remoteDeviceUuids, 1261 BluetoothProfile.HAP_CLIENT, device) 1262 && mHapClientService.getConnectionPolicy(device) 1263 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1264 Log.i(TAG, "connectEnabledProfiles: Connecting HAS Profile"); 1265 mHapClientService.connect(device); 1266 } 1267 if (mVolumeControlService != null && isSupported(localDeviceUuids, remoteDeviceUuids, 1268 BluetoothProfile.VOLUME_CONTROL, device) 1269 && mVolumeControlService.getConnectionPolicy(device) 1270 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1271 Log.i(TAG, "connectEnabledProfiles: Connecting Volume Control Profile"); 1272 mVolumeControlService.connect(device); 1273 } 1274 if (mCsipSetCoordinatorService != null 1275 && isSupported(localDeviceUuids, remoteDeviceUuids, 1276 BluetoothProfile.CSIP_SET_COORDINATOR, device) 1277 && mCsipSetCoordinatorService.getConnectionPolicy(device) 1278 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1279 Log.i(TAG, "connectEnabledProfiles: Connecting Coordinated Set Profile"); 1280 mCsipSetCoordinatorService.connect(device); 1281 } 1282 if (mLeAudioService != null && isSupported(localDeviceUuids, remoteDeviceUuids, 1283 BluetoothProfile.LE_AUDIO, device) 1284 && mLeAudioService.getConnectionPolicy(device) 1285 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1286 Log.i(TAG, "connectEnabledProfiles: Connecting LeAudio profile (BAP)"); 1287 mLeAudioService.connect(device); 1288 } 1289 if (mBassClientService != null && isSupported(localDeviceUuids, remoteDeviceUuids, 1290 BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT, device) 1291 && mBassClientService.getConnectionPolicy(device) 1292 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1293 Log.i(TAG, "connectEnabledProfiles: Connecting LE Broadcast Assistant Profile"); 1294 mBassClientService.connect(device); 1295 } 1296 if (mBatteryService != null 1297 && isSupported( 1298 localDeviceUuids, remoteDeviceUuids, BluetoothProfile.BATTERY, device) 1299 && mBatteryService.getConnectionPolicy(device) 1300 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1301 Log.i(TAG, "connectEnabledProfiles: Connecting Battery Service"); 1302 mBatteryService.connect(device); 1303 } 1304 return BluetoothStatusCodes.SUCCESS; 1305 } 1306 1307 /** 1308 * Verifies that all bluetooth profile services are running 1309 * 1310 * @return true if all bluetooth profile services running, false otherwise 1311 */ profileServicesRunning()1312 private boolean profileServicesRunning() { 1313 if (mRegisteredProfiles.size() == Config.getSupportedProfiles().length 1314 && mRegisteredProfiles.size() == mRunningProfiles.size()) { 1315 return true; 1316 } 1317 1318 Log.e(TAG, "profileServicesRunning: One or more supported services not running"); 1319 return false; 1320 } 1321 1322 /** 1323 * Initializes all the profile services fields 1324 */ initProfileServices()1325 private void initProfileServices() { 1326 Log.i(TAG, "initProfileServices: Initializing all bluetooth profile services"); 1327 mA2dpService = A2dpService.getA2dpService(); 1328 mA2dpSinkService = A2dpSinkService.getA2dpSinkService(); 1329 mHeadsetService = HeadsetService.getHeadsetService(); 1330 mHeadsetClientService = HeadsetClientService.getHeadsetClientService(); 1331 mMapService = BluetoothMapService.getBluetoothMapService(); 1332 mMapClientService = MapClientService.getMapClientService(); 1333 mHidDeviceService = HidDeviceService.getHidDeviceService(); 1334 mHidHostService = HidHostService.getHidHostService(); 1335 mPanService = PanService.getPanService(); 1336 mPbapService = BluetoothPbapService.getBluetoothPbapService(); 1337 mPbapClientService = PbapClientService.getPbapClientService(); 1338 mHearingAidService = HearingAidService.getHearingAidService(); 1339 mHapClientService = HapClientService.getHapClientService(); 1340 mSapService = SapService.getSapService(); 1341 mVolumeControlService = VolumeControlService.getVolumeControlService(); 1342 mCsipSetCoordinatorService = CsipSetCoordinatorService.getCsipSetCoordinatorService(); 1343 mLeAudioService = LeAudioService.getLeAudioService(); 1344 mBassClientService = BassClientService.getBassClientService(); 1345 mBatteryService = BatteryService.getBatteryService(); 1346 } 1347 1348 @BluetoothAdapter.RfcommListenerResult startRfcommListener( String name, ParcelUuid uuid, PendingIntent pendingIntent, AttributionSource attributionSource)1349 private int startRfcommListener( 1350 String name, 1351 ParcelUuid uuid, 1352 PendingIntent pendingIntent, 1353 AttributionSource attributionSource) { 1354 if (mBluetoothServerSockets.containsKey(uuid.getUuid())) { 1355 Log.d(TAG, String.format( 1356 "Cannot start RFCOMM listener: UUID %s already in use.", uuid.getUuid())); 1357 return BluetoothStatusCodes.RFCOMM_LISTENER_START_FAILED_UUID_IN_USE; 1358 } 1359 1360 try { 1361 startRfcommListenerInternal(name, uuid.getUuid(), pendingIntent, attributionSource); 1362 } catch (IOException e) { 1363 return BluetoothStatusCodes.RFCOMM_LISTENER_FAILED_TO_CREATE_SERVER_SOCKET; 1364 } 1365 1366 return BluetoothStatusCodes.SUCCESS; 1367 } 1368 1369 @BluetoothAdapter.RfcommListenerResult 1370 @VisibleForTesting stopRfcommListener(ParcelUuid uuid, AttributionSource attributionSource)1371 int stopRfcommListener(ParcelUuid uuid, AttributionSource attributionSource) { 1372 RfcommListenerData listenerData = mBluetoothServerSockets.get(uuid.getUuid()); 1373 1374 if (listenerData == null) { 1375 Log.d(TAG, String.format( 1376 "Cannot stop RFCOMM listener: UUID %s is not registered.", uuid.getUuid())); 1377 return BluetoothStatusCodes.RFCOMM_LISTENER_OPERATION_FAILED_NO_MATCHING_SERVICE_RECORD; 1378 } 1379 1380 if (attributionSource.getUid() != listenerData.mAttributionSource.getUid()) { 1381 return BluetoothStatusCodes.RFCOMM_LISTENER_OPERATION_FAILED_DIFFERENT_APP; 1382 } 1383 1384 // Remove the entry so that it does not try and restart the server socket. 1385 mBluetoothServerSockets.remove(uuid.getUuid()); 1386 1387 return listenerData.closeServerAndPendingSockets(mHandler); 1388 } 1389 1390 @VisibleForTesting retrievePendingSocketForServiceRecord( ParcelUuid uuid, AttributionSource attributionSource)1391 IncomingRfcommSocketInfo retrievePendingSocketForServiceRecord( 1392 ParcelUuid uuid, AttributionSource attributionSource) { 1393 IncomingRfcommSocketInfo socketInfo = new IncomingRfcommSocketInfo(); 1394 1395 RfcommListenerData listenerData = mBluetoothServerSockets.get(uuid.getUuid()); 1396 1397 if (listenerData == null) { 1398 socketInfo.status = 1399 BluetoothStatusCodes 1400 .RFCOMM_LISTENER_OPERATION_FAILED_NO_MATCHING_SERVICE_RECORD; 1401 return socketInfo; 1402 } 1403 1404 if (attributionSource.getUid() != listenerData.mAttributionSource.getUid()) { 1405 socketInfo.status = BluetoothStatusCodes.RFCOMM_LISTENER_OPERATION_FAILED_DIFFERENT_APP; 1406 return socketInfo; 1407 } 1408 1409 BluetoothSocket socket = listenerData.mPendingSockets.poll(); 1410 1411 if (socket == null) { 1412 socketInfo.status = BluetoothStatusCodes.RFCOMM_LISTENER_NO_SOCKET_AVAILABLE; 1413 return socketInfo; 1414 } 1415 1416 mHandler.removeCallbacksAndMessages(socket); 1417 1418 socketInfo.bluetoothDevice = socket.getRemoteDevice(); 1419 socketInfo.pfd = socket.getParcelFileDescriptor(); 1420 socketInfo.status = BluetoothStatusCodes.SUCCESS; 1421 1422 return socketInfo; 1423 } 1424 handleIncomingRfcommConnections(UUID uuid)1425 private void handleIncomingRfcommConnections(UUID uuid) { 1426 RfcommListenerData listenerData = mBluetoothServerSockets.get(uuid); 1427 for (;;) { 1428 BluetoothSocket socket; 1429 try { 1430 socket = listenerData.mServerSocket.accept(); 1431 } catch (IOException e) { 1432 if (mBluetoothServerSockets.containsKey(uuid)) { 1433 // The uuid still being in the map indicates that the accept failure is 1434 // unexpected. Try and restart the listener. 1435 Log.e(TAG, "Failed to accept socket on " + listenerData.mServerSocket, e); 1436 restartRfcommListener(listenerData, uuid); 1437 } 1438 return; 1439 } 1440 1441 listenerData.mPendingSockets.add(socket); 1442 try { 1443 listenerData.mPendingIntent.send(); 1444 } catch (PendingIntent.CanceledException e) { 1445 Log.e(TAG, "PendingIntent for RFCOMM socket notifications cancelled.", e); 1446 // The pending intent was cancelled, close the server as there is no longer any way 1447 // to notify the app that registered the listener. 1448 listenerData.closeServerAndPendingSockets(mHandler); 1449 mBluetoothServerSockets.remove(uuid); 1450 return; 1451 } 1452 mHandler.postDelayed( 1453 () -> pendingSocketTimeoutRunnable(listenerData, socket), 1454 socket, 1455 PENDING_SOCKET_HANDOFF_TIMEOUT.toMillis()); 1456 } 1457 } 1458 1459 // Tries to restart the rfcomm listener for the given UUID restartRfcommListener(RfcommListenerData listenerData, UUID uuid)1460 private void restartRfcommListener(RfcommListenerData listenerData, UUID uuid) { 1461 listenerData.closeServerAndPendingSockets(mHandler); 1462 try { 1463 startRfcommListenerInternal( 1464 listenerData.mName, 1465 uuid, 1466 listenerData.mPendingIntent, 1467 listenerData.mAttributionSource); 1468 } catch (IOException e) { 1469 Log.e(TAG, "Failed to recreate rfcomm server socket", e); 1470 1471 mBluetoothServerSockets.remove(uuid); 1472 } 1473 } 1474 pendingSocketTimeoutRunnable( RfcommListenerData listenerData, BluetoothSocket socket)1475 private void pendingSocketTimeoutRunnable( 1476 RfcommListenerData listenerData, BluetoothSocket socket) { 1477 boolean socketFound = listenerData.mPendingSockets.remove(socket); 1478 if (socketFound) { 1479 try { 1480 socket.close(); 1481 } catch (IOException e) { 1482 Log.e(TAG, "Failed to close bt socket", e); 1483 // We don't care if closing the socket failed, just continue on. 1484 } 1485 } 1486 } 1487 startRfcommListenerInternal( String name, UUID uuid, PendingIntent intent, AttributionSource attributionSource)1488 private void startRfcommListenerInternal( 1489 String name, UUID uuid, PendingIntent intent, AttributionSource attributionSource) 1490 throws IOException { 1491 BluetoothServerSocket bluetoothServerSocket = 1492 mAdapter.listenUsingRfcommWithServiceRecord(name, uuid); 1493 1494 RfcommListenerData listenerData = 1495 new RfcommListenerData(bluetoothServerSocket, name, intent, attributionSource); 1496 1497 mBluetoothServerSockets.put(uuid, listenerData); 1498 1499 mSocketServersExecutor.execute(() -> handleIncomingRfcommConnections(uuid)); 1500 } 1501 stopRfcommServerSockets()1502 private void stopRfcommServerSockets() { 1503 Iterator<Map.Entry<UUID, RfcommListenerData>> socketsIterator = 1504 mBluetoothServerSockets.entrySet().iterator(); 1505 while (socketsIterator.hasNext()) { 1506 socketsIterator.next().getValue().closeServerAndPendingSockets(mHandler); 1507 socketsIterator.remove(); 1508 } 1509 } 1510 1511 private static class RfcommListenerData { 1512 final BluetoothServerSocket mServerSocket; 1513 // Service record name 1514 final String mName; 1515 // The Intent which contains the Service info to which the incoming socket connections are 1516 // handed off to. 1517 final PendingIntent mPendingIntent; 1518 // AttributionSource for the requester of the RFCOMM listener 1519 final AttributionSource mAttributionSource; 1520 // Contains the connected sockets which are pending transfer to the app which requested the 1521 // listener. 1522 final ConcurrentLinkedQueue<BluetoothSocket> mPendingSockets = 1523 new ConcurrentLinkedQueue<>(); 1524 RfcommListenerData( BluetoothServerSocket serverSocket, String name, PendingIntent pendingIntent, AttributionSource attributionSource)1525 RfcommListenerData( 1526 BluetoothServerSocket serverSocket, 1527 String name, 1528 PendingIntent pendingIntent, 1529 AttributionSource attributionSource) { 1530 mServerSocket = serverSocket; 1531 mName = name; 1532 mPendingIntent = pendingIntent; 1533 mAttributionSource = attributionSource; 1534 } 1535 closeServerAndPendingSockets(Handler handler)1536 int closeServerAndPendingSockets(Handler handler) { 1537 int result = BluetoothStatusCodes.SUCCESS; 1538 try { 1539 mServerSocket.close(); 1540 } catch (IOException e) { 1541 Log.e(TAG, "Failed to call close on rfcomm server socket", e); 1542 result = BluetoothStatusCodes.RFCOMM_LISTENER_FAILED_TO_CLOSE_SERVER_SOCKET; 1543 } 1544 mPendingSockets.forEach( 1545 pendingSocket -> { 1546 handler.removeCallbacksAndMessages(pendingSocket); 1547 try { 1548 pendingSocket.close(); 1549 } catch (IOException e) { 1550 Log.e(TAG, "Failed to close socket", e); 1551 } 1552 }); 1553 mPendingSockets.clear(); 1554 1555 return result; 1556 } 1557 } 1558 1559 @VisibleForTesting isAvailable()1560 boolean isAvailable() { 1561 return !mCleaningUp; 1562 } 1563 1564 /** 1565 * Get an metadata of given device and key 1566 * 1567 * @param device Bluetooth device 1568 * @param key Metadata key 1569 * @param value Metadata value 1570 * @return if metadata is set successfully 1571 */ setMetadata(BluetoothDevice device, int key, byte[] value)1572 public boolean setMetadata(BluetoothDevice device, int key, byte[] value) { 1573 if (value == null || value.length > BluetoothDevice.METADATA_MAX_LENGTH) { 1574 return false; 1575 } 1576 return mDatabaseManager.setCustomMeta(device, key, value); 1577 } 1578 1579 /** 1580 * Get an metadata of given device and key 1581 * 1582 * @param device Bluetooth device 1583 * @param key Metadata key 1584 * @return value of given device and key combination 1585 */ getMetadata(BluetoothDevice device, int key)1586 public byte[] getMetadata(BluetoothDevice device, int key) { 1587 return mDatabaseManager.getCustomMeta(device, key); 1588 } 1589 1590 /** 1591 * Handlers for incoming service calls 1592 */ 1593 private AdapterServiceBinder mBinder; 1594 1595 /** 1596 * The Binder implementation must be declared to be a static class, with 1597 * the AdapterService instance passed in the constructor. Furthermore, 1598 * when the AdapterService shuts down, the reference to the AdapterService 1599 * must be explicitly removed. 1600 * 1601 * Otherwise, a memory leak can occur from repeated starting/stopping the 1602 * service...Please refer to android.os.Binder for further details on 1603 * why an inner instance class should be avoided. 1604 * 1605 */ 1606 @VisibleForTesting 1607 public static class AdapterServiceBinder extends IBluetooth.Stub { 1608 private AdapterService mService; 1609 AdapterServiceBinder(AdapterService svc)1610 AdapterServiceBinder(AdapterService svc) { 1611 mService = svc; 1612 mService.invalidateBluetoothGetStateCache(); 1613 BluetoothAdapter.getDefaultAdapter().disableBluetoothGetStateCache(); 1614 } 1615 cleanup()1616 public void cleanup() { 1617 mService = null; 1618 } 1619 getService()1620 public AdapterService getService() { 1621 if (mService != null && mService.isAvailable()) { 1622 return mService; 1623 } 1624 return null; 1625 } 1626 1627 @Override getState(SynchronousResultReceiver receiver)1628 public void getState(SynchronousResultReceiver receiver) { 1629 try { 1630 receiver.send(getState()); 1631 } catch (RuntimeException e) { 1632 receiver.propagateException(e); 1633 } 1634 } getState()1635 private int getState() { 1636 // don't check caller, may be called from system UI 1637 AdapterService service = getService(); 1638 if (service == null) { 1639 return BluetoothAdapter.STATE_OFF; 1640 } 1641 1642 return service.getState(); 1643 } 1644 1645 @Override enable(boolean quietMode, AttributionSource source, SynchronousResultReceiver receiver)1646 public void enable(boolean quietMode, AttributionSource source, 1647 SynchronousResultReceiver receiver) { 1648 try { 1649 receiver.send(enable(quietMode, source)); 1650 } catch (RuntimeException e) { 1651 receiver.propagateException(e); 1652 } 1653 } enable(boolean quietMode, AttributionSource attributionSource)1654 private boolean enable(boolean quietMode, AttributionSource attributionSource) { 1655 AdapterService service = getService(); 1656 if (service == null || !callerIsSystemOrActiveOrManagedUser(service, TAG, "enable") 1657 || !Utils.checkConnectPermissionForDataDelivery( 1658 service, attributionSource, "AdapterService enable")) { 1659 return false; 1660 } 1661 1662 return service.enable(quietMode); 1663 } 1664 1665 @Override disable(AttributionSource source, SynchronousResultReceiver receiver)1666 public void disable(AttributionSource source, SynchronousResultReceiver receiver) { 1667 try { 1668 receiver.send(disable(source)); 1669 } catch (RuntimeException e) { 1670 receiver.propagateException(e); 1671 } 1672 } disable(AttributionSource attributionSource)1673 private boolean disable(AttributionSource attributionSource) { 1674 AdapterService service = getService(); 1675 if (service == null || !callerIsSystemOrActiveOrManagedUser(service, TAG, "disable") 1676 || !Utils.checkConnectPermissionForDataDelivery( 1677 service, attributionSource, "AdapterService disable")) { 1678 return false; 1679 } 1680 1681 return service.disable(); 1682 } 1683 1684 @Override getAddress()1685 public String getAddress() { 1686 if (mService == null) { 1687 return null; 1688 } 1689 return getAddressWithAttribution(Utils.getCallingAttributionSource(mService)); 1690 } 1691 1692 @Override getAddressWithAttribution(AttributionSource source, SynchronousResultReceiver receiver)1693 public void getAddressWithAttribution(AttributionSource source, 1694 SynchronousResultReceiver receiver) { 1695 try { 1696 receiver.send(getAddressWithAttribution(source)); 1697 } catch (RuntimeException e) { 1698 receiver.propagateException(e); 1699 } 1700 } getAddressWithAttribution(AttributionSource attributionSource)1701 private String getAddressWithAttribution(AttributionSource attributionSource) { 1702 AdapterService service = getService(); 1703 if (service == null || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getAddress") 1704 || !Utils.checkConnectPermissionForDataDelivery( 1705 service, attributionSource, "AdapterService getAddress")) { 1706 return null; 1707 } 1708 1709 enforceLocalMacAddressPermission(service); 1710 1711 return Utils.getAddressStringFromByte(service.mAdapterProperties.getAddress()); 1712 } 1713 1714 @Override getUuids(AttributionSource source, SynchronousResultReceiver receiver)1715 public void getUuids(AttributionSource source, SynchronousResultReceiver receiver) { 1716 try { 1717 receiver.send(getUuids(source)); 1718 } catch (RuntimeException e) { 1719 receiver.propagateException(e); 1720 } 1721 } getUuids(AttributionSource attributionSource)1722 private List<ParcelUuid> getUuids(AttributionSource attributionSource) { 1723 AdapterService service = getService(); 1724 if (service == null || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getUuids") 1725 || !Utils.checkConnectPermissionForDataDelivery( 1726 service, attributionSource, "AdapterService getUuids")) { 1727 return new ArrayList<>(); 1728 } 1729 1730 ParcelUuid[] parcels = service.mAdapterProperties.getUuids(); 1731 if (parcels == null) { 1732 parcels = new ParcelUuid[0]; 1733 } 1734 return Arrays.asList(parcels); 1735 } 1736 1737 @Override getIdentityAddress(String address, SynchronousResultReceiver receiver)1738 public void getIdentityAddress(String address, SynchronousResultReceiver receiver) { 1739 try { 1740 receiver.send(getIdentityAddress(address)); 1741 } catch (RuntimeException e) { 1742 receiver.propagateException(e); 1743 } 1744 } getIdentityAddress(String address)1745 public String getIdentityAddress(String address) { 1746 AdapterService service = getService(); 1747 if (service == null 1748 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getIdentityAddress") 1749 || !Utils.checkConnectPermissionForDataDelivery( 1750 service, Utils.getCallingAttributionSource(mService), 1751 "AdapterService getIdentityAddress")) { 1752 return null; 1753 } 1754 enforceBluetoothPrivilegedPermission(service); 1755 return service.getIdentityAddress(address); 1756 } 1757 1758 @Override getName(AttributionSource source, SynchronousResultReceiver receiver)1759 public void getName(AttributionSource source, SynchronousResultReceiver receiver) { 1760 try { 1761 receiver.send(getName(source)); 1762 } catch (RuntimeException e) { 1763 receiver.propagateException(e); 1764 } 1765 } getName(AttributionSource attributionSource)1766 private String getName(AttributionSource attributionSource) { 1767 AdapterService service = getService(); 1768 if (service == null || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getName") 1769 || !Utils.checkConnectPermissionForDataDelivery( 1770 service, attributionSource, "AdapterService getName")) { 1771 return null; 1772 } 1773 1774 return service.getName(); 1775 } 1776 1777 @Override getNameLengthForAdvertise(AttributionSource source, SynchronousResultReceiver receiver)1778 public void getNameLengthForAdvertise(AttributionSource source, 1779 SynchronousResultReceiver receiver) { 1780 try { 1781 receiver.send(getNameLengthForAdvertise(source)); 1782 } catch (RuntimeException e) { 1783 receiver.propagateException(e); 1784 } 1785 } getNameLengthForAdvertise(AttributionSource attributionSource)1786 private int getNameLengthForAdvertise(AttributionSource attributionSource) { 1787 AdapterService service = getService(); 1788 if (service == null 1789 || !callerIsSystemOrActiveOrManagedUser(service, 1790 TAG, "getNameLengthForAdvertise") 1791 || !Utils.checkAdvertisePermissionForDataDelivery( 1792 service, attributionSource, TAG)) { 1793 return -1; 1794 } 1795 1796 return service.getNameLengthForAdvertise(); 1797 } 1798 1799 @Override setName(String name, AttributionSource source, SynchronousResultReceiver receiver)1800 public void setName(String name, AttributionSource source, 1801 SynchronousResultReceiver receiver) { 1802 try { 1803 receiver.send(setName(name, source)); 1804 } catch (RuntimeException e) { 1805 receiver.propagateException(e); 1806 } 1807 } setName(String name, AttributionSource attributionSource)1808 private boolean setName(String name, AttributionSource attributionSource) { 1809 AdapterService service = getService(); 1810 if (service == null || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setName") 1811 || !Utils.checkConnectPermissionForDataDelivery( 1812 service, attributionSource, "AdapterService setName")) { 1813 return false; 1814 } 1815 1816 return service.mAdapterProperties.setName(name); 1817 } 1818 1819 @Override getBluetoothClass(AttributionSource source, SynchronousResultReceiver receiver)1820 public void getBluetoothClass(AttributionSource source, 1821 SynchronousResultReceiver receiver) { 1822 try { 1823 receiver.send(getBluetoothClass(source)); 1824 } catch (RuntimeException e) { 1825 receiver.propagateException(e); 1826 } 1827 } getBluetoothClass(AttributionSource attributionSource)1828 private BluetoothClass getBluetoothClass(AttributionSource attributionSource) { 1829 AdapterService service = getService(); 1830 if (service == null 1831 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getBluetoothClass") 1832 || !Utils.checkConnectPermissionForDataDelivery( 1833 service, attributionSource, "AdapterSource getBluetoothClass")) { 1834 return null; 1835 } 1836 1837 return service.mAdapterProperties.getBluetoothClass(); 1838 } 1839 1840 @Override setBluetoothClass(BluetoothClass bluetoothClass, AttributionSource source, SynchronousResultReceiver receiver)1841 public void setBluetoothClass(BluetoothClass bluetoothClass, AttributionSource source, 1842 SynchronousResultReceiver receiver) { 1843 try { 1844 receiver.send(setBluetoothClass(bluetoothClass, source)); 1845 } catch (RuntimeException e) { 1846 receiver.propagateException(e); 1847 } 1848 } setBluetoothClass(BluetoothClass bluetoothClass, AttributionSource source)1849 private boolean setBluetoothClass(BluetoothClass bluetoothClass, AttributionSource source) { 1850 AdapterService service = getService(); 1851 if (service == null 1852 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setBluetoothClass") 1853 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 1854 return false; 1855 } 1856 1857 enforceBluetoothPrivilegedPermission(service); 1858 1859 if (!service.mAdapterProperties.setBluetoothClass(bluetoothClass)) { 1860 return false; 1861 } 1862 1863 return Settings.Global.putInt( 1864 service.getContentResolver(), 1865 Settings.Global.BLUETOOTH_CLASS_OF_DEVICE, 1866 bluetoothClass.getClassOfDevice()); 1867 } 1868 1869 @Override getIoCapability(AttributionSource source, SynchronousResultReceiver receiver)1870 public void getIoCapability(AttributionSource source, SynchronousResultReceiver receiver) { 1871 try { 1872 receiver.send(getIoCapability(source)); 1873 } catch (RuntimeException e) { 1874 receiver.propagateException(e); 1875 } 1876 } getIoCapability(AttributionSource attributionSource)1877 private int getIoCapability(AttributionSource attributionSource) { 1878 AdapterService service = getService(); 1879 if (service == null 1880 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getIoCapability") 1881 || !Utils.checkConnectPermissionForDataDelivery( 1882 service, attributionSource, "AdapterService getIoCapability")) { 1883 return BluetoothAdapter.IO_CAPABILITY_UNKNOWN; 1884 } 1885 1886 return service.mAdapterProperties.getIoCapability(); 1887 } 1888 1889 @Override setIoCapability(int capability, AttributionSource source, SynchronousResultReceiver receiver)1890 public void setIoCapability(int capability, AttributionSource source, 1891 SynchronousResultReceiver receiver) { 1892 try { 1893 receiver.send(setIoCapability(capability, source)); 1894 } catch (RuntimeException e) { 1895 receiver.propagateException(e); 1896 } 1897 } setIoCapability(int capability, AttributionSource source)1898 private boolean setIoCapability(int capability, AttributionSource source) { 1899 AdapterService service = getService(); 1900 if (service == null 1901 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setIoCapability") 1902 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 1903 return false; 1904 } 1905 1906 enforceBluetoothPrivilegedPermission(service); 1907 1908 if (!isValidIoCapability(capability)) { 1909 return false; 1910 } 1911 1912 return service.mAdapterProperties.setIoCapability(capability); 1913 } 1914 1915 @Override getLeIoCapability(AttributionSource source, SynchronousResultReceiver receiver)1916 public void getLeIoCapability(AttributionSource source, 1917 SynchronousResultReceiver receiver) { 1918 try { 1919 receiver.send(getLeIoCapability(source)); 1920 } catch (RuntimeException e) { 1921 receiver.propagateException(e); 1922 } 1923 } getLeIoCapability(AttributionSource attributionSource)1924 private int getLeIoCapability(AttributionSource attributionSource) { 1925 AdapterService service = getService(); 1926 if (service == null 1927 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getLeIoCapability") 1928 || !Utils.checkConnectPermissionForDataDelivery( 1929 service, attributionSource, "AdapterService getLeIoCapability")) { 1930 return BluetoothAdapter.IO_CAPABILITY_UNKNOWN; 1931 } 1932 1933 return service.mAdapterProperties.getLeIoCapability(); 1934 } 1935 1936 @Override setLeIoCapability(int capability, AttributionSource source, SynchronousResultReceiver receiver)1937 public void setLeIoCapability(int capability, AttributionSource source, 1938 SynchronousResultReceiver receiver) { 1939 try { 1940 receiver.send(setLeIoCapability(capability, source)); 1941 } catch (RuntimeException e) { 1942 receiver.propagateException(e); 1943 } 1944 } setLeIoCapability(int capability, AttributionSource source)1945 private boolean setLeIoCapability(int capability, AttributionSource source) { 1946 AdapterService service = getService(); 1947 if (service == null 1948 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setLeIoCapability") 1949 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 1950 return false; 1951 } 1952 1953 enforceBluetoothPrivilegedPermission(service); 1954 1955 if (!isValidIoCapability(capability)) { 1956 return false; 1957 } 1958 1959 return service.mAdapterProperties.setLeIoCapability(capability); 1960 } 1961 1962 @Override getScanMode(AttributionSource source, SynchronousResultReceiver receiver)1963 public void getScanMode(AttributionSource source, SynchronousResultReceiver receiver) { 1964 try { 1965 receiver.send(getScanMode(source)); 1966 } catch (RuntimeException e) { 1967 receiver.propagateException(e); 1968 } 1969 } 1970 @VisibleForTesting getScanMode(AttributionSource attributionSource)1971 int getScanMode(AttributionSource attributionSource) { 1972 AdapterService service = getService(); 1973 if (service == null || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getScanMode") 1974 || !Utils.checkScanPermissionForDataDelivery( 1975 service, attributionSource, "AdapterService getScanMode")) { 1976 return BluetoothAdapter.SCAN_MODE_NONE; 1977 } 1978 1979 return service.mAdapterProperties.getScanMode(); 1980 } 1981 1982 @Override setScanMode(int mode, AttributionSource source, SynchronousResultReceiver receiver)1983 public void setScanMode(int mode, AttributionSource source, 1984 SynchronousResultReceiver receiver) { 1985 try { 1986 receiver.send(setScanMode(mode, source)); 1987 } catch (RuntimeException e) { 1988 receiver.propagateException(e); 1989 } 1990 } setScanMode(int mode, AttributionSource attributionSource)1991 private int setScanMode(int mode, AttributionSource attributionSource) { 1992 AdapterService service = getService(); 1993 if (service == null 1994 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setScanMode") 1995 || !Utils.checkScanPermissionForDataDelivery( 1996 service, attributionSource, "AdapterService setScanMode")) { 1997 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_SCAN_PERMISSION; 1998 } 1999 enforceBluetoothPrivilegedPermission(service); 2000 2001 return service.mAdapterProperties.setScanMode(mode) 2002 ? BluetoothStatusCodes.SUCCESS : BluetoothStatusCodes.ERROR_UNKNOWN; 2003 } 2004 2005 @Override getDiscoverableTimeout(AttributionSource source, SynchronousResultReceiver receiver)2006 public void getDiscoverableTimeout(AttributionSource source, 2007 SynchronousResultReceiver receiver) { 2008 try { 2009 receiver.send(getDiscoverableTimeout(source)); 2010 } catch (RuntimeException e) { 2011 receiver.propagateException(e); 2012 } 2013 } getDiscoverableTimeout(AttributionSource attributionSource)2014 private long getDiscoverableTimeout(AttributionSource attributionSource) { 2015 AdapterService service = getService(); 2016 if (service == null 2017 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getDiscoverableTimeout") 2018 || !Utils.checkScanPermissionForDataDelivery( 2019 service, attributionSource, "AdapterService getDiscoverableTimeout")) { 2020 return -1; 2021 } 2022 2023 return service.mAdapterProperties.getDiscoverableTimeout(); 2024 } 2025 2026 @Override setDiscoverableTimeout(long timeout, AttributionSource source, SynchronousResultReceiver receiver)2027 public void setDiscoverableTimeout(long timeout, AttributionSource source, 2028 SynchronousResultReceiver receiver) { 2029 try { 2030 receiver.send(setDiscoverableTimeout(timeout, source)); 2031 } catch (RuntimeException e) { 2032 receiver.propagateException(e); 2033 } 2034 } setDiscoverableTimeout(long timeout, AttributionSource attributionSource)2035 private int setDiscoverableTimeout(long timeout, AttributionSource attributionSource) { 2036 AdapterService service = getService(); 2037 if (service == null 2038 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setDiscoverableTimeout") 2039 || !Utils.checkScanPermissionForDataDelivery( 2040 service, attributionSource, "AdapterService setDiscoverableTimeout")) { 2041 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_SCAN_PERMISSION; 2042 } 2043 enforceBluetoothPrivilegedPermission(service); 2044 2045 return service.mAdapterProperties.setDiscoverableTimeout((int) timeout) 2046 ? BluetoothStatusCodes.SUCCESS : BluetoothStatusCodes.ERROR_UNKNOWN; 2047 } 2048 2049 @Override startDiscovery(AttributionSource source, SynchronousResultReceiver receiver)2050 public void startDiscovery(AttributionSource source, SynchronousResultReceiver receiver) { 2051 try { 2052 receiver.send(startDiscovery(source)); 2053 } catch (RuntimeException e) { 2054 receiver.propagateException(e); 2055 } 2056 } startDiscovery(AttributionSource attributionSource)2057 private boolean startDiscovery(AttributionSource attributionSource) { 2058 AdapterService service = getService(); 2059 if (service == null 2060 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "startDiscovery")) { 2061 return false; 2062 } 2063 2064 if (!Utils.checkScanPermissionForDataDelivery( 2065 service, attributionSource, "Starting discovery.")) { 2066 return false; 2067 } 2068 2069 return service.startDiscovery(attributionSource); 2070 } 2071 2072 @Override cancelDiscovery(AttributionSource source, SynchronousResultReceiver receiver)2073 public void cancelDiscovery(AttributionSource source, SynchronousResultReceiver receiver) { 2074 try { 2075 receiver.send(cancelDiscovery(source)); 2076 } catch (RuntimeException e) { 2077 receiver.propagateException(e); 2078 } 2079 } cancelDiscovery(AttributionSource attributionSource)2080 private boolean cancelDiscovery(AttributionSource attributionSource) { 2081 AdapterService service = getService(); 2082 if (service == null 2083 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "cancelDiscovery") 2084 || !Utils.checkScanPermissionForDataDelivery( 2085 service, attributionSource, "AdapterService cancelDiscovery")) { 2086 return false; 2087 } 2088 2089 service.debugLog("cancelDiscovery"); 2090 return service.cancelDiscoveryNative(); 2091 } 2092 2093 @Override isDiscovering(AttributionSource source, SynchronousResultReceiver receiver)2094 public void isDiscovering(AttributionSource source, SynchronousResultReceiver receiver) { 2095 try { 2096 receiver.send(isDiscovering(source)); 2097 } catch (RuntimeException e) { 2098 receiver.propagateException(e); 2099 } 2100 } isDiscovering(AttributionSource attributionSource)2101 private boolean isDiscovering(AttributionSource attributionSource) { 2102 AdapterService service = getService(); 2103 if (service == null 2104 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "isDiscovering") 2105 || !Utils.checkScanPermissionForDataDelivery( 2106 service, attributionSource, "AdapterService isDiscovering")) { 2107 return false; 2108 } 2109 2110 return service.mAdapterProperties.isDiscovering(); 2111 } 2112 2113 @Override getDiscoveryEndMillis(AttributionSource source, SynchronousResultReceiver receiver)2114 public void getDiscoveryEndMillis(AttributionSource source, 2115 SynchronousResultReceiver receiver) { 2116 try { 2117 receiver.send(getDiscoveryEndMillis(source)); 2118 } catch (RuntimeException e) { 2119 receiver.propagateException(e); 2120 } 2121 } getDiscoveryEndMillis(AttributionSource source)2122 private long getDiscoveryEndMillis(AttributionSource source) { 2123 AdapterService service = getService(); 2124 if (service == null 2125 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getDiscoveryEndMillis") 2126 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 2127 return -1; 2128 } 2129 2130 enforceBluetoothPrivilegedPermission(service); 2131 2132 return service.mAdapterProperties.discoveryEndMillis(); 2133 } 2134 2135 @Override getMostRecentlyConnectedDevices(AttributionSource source, SynchronousResultReceiver receiver)2136 public void getMostRecentlyConnectedDevices(AttributionSource source, 2137 SynchronousResultReceiver receiver) { 2138 try { 2139 receiver.send(getMostRecentlyConnectedDevices(source)); 2140 } catch (RuntimeException e) { 2141 receiver.propagateException(e); 2142 } 2143 } getMostRecentlyConnectedDevices( AttributionSource attributionSource)2144 private List<BluetoothDevice> getMostRecentlyConnectedDevices( 2145 AttributionSource attributionSource) { 2146 // don't check caller, may be called from system UI 2147 AdapterService service = getService(); 2148 if (service == null || !Utils.checkConnectPermissionForDataDelivery( 2149 service, attributionSource, "AdapterService getMostRecentlyConnectedDevices")) { 2150 return new ArrayList<>(); 2151 } 2152 2153 enforceBluetoothPrivilegedPermission(service); 2154 2155 return service.mDatabaseManager.getMostRecentlyConnectedDevices(); 2156 } 2157 2158 @Override getBondedDevices(AttributionSource source, SynchronousResultReceiver receiver)2159 public void getBondedDevices(AttributionSource source, SynchronousResultReceiver receiver) { 2160 try { 2161 receiver.send(getBondedDevices(source)); 2162 } catch (RuntimeException e) { 2163 receiver.propagateException(e); 2164 } 2165 } getBondedDevices(AttributionSource attributionSource)2166 private List<BluetoothDevice> getBondedDevices(AttributionSource attributionSource) { 2167 // don't check caller, may be called from system UI 2168 AdapterService service = getService(); 2169 if (service == null || !Utils.checkConnectPermissionForDataDelivery( 2170 service, attributionSource, "AdapterService getBondedDevices")) { 2171 return new ArrayList<>(); 2172 } 2173 2174 return Arrays.asList(service.getBondedDevices()); 2175 } 2176 2177 @Override getAdapterConnectionState(SynchronousResultReceiver receiver)2178 public void getAdapterConnectionState(SynchronousResultReceiver receiver) { 2179 try { 2180 receiver.send(getAdapterConnectionState()); 2181 } catch (RuntimeException e) { 2182 receiver.propagateException(e); 2183 } 2184 } getAdapterConnectionState()2185 private int getAdapterConnectionState() { 2186 // don't check caller, may be called from system UI 2187 AdapterService service = getService(); 2188 if (service == null) { 2189 return BluetoothAdapter.STATE_DISCONNECTED; 2190 } 2191 2192 return service.mAdapterProperties.getConnectionState(); 2193 } 2194 2195 /** 2196 * This method has an associated binder cache. The invalidation 2197 * methods must be changed if the logic behind this method changes. 2198 */ 2199 @Override getProfileConnectionState(int profile, SynchronousResultReceiver receiver)2200 public void getProfileConnectionState(int profile, SynchronousResultReceiver receiver) { 2201 try { 2202 receiver.send(getProfileConnectionState(profile)); 2203 } catch (RuntimeException e) { 2204 receiver.propagateException(e); 2205 } 2206 } getProfileConnectionState(int profile)2207 private int getProfileConnectionState(int profile) { 2208 AdapterService service = getService(); 2209 if (service == null 2210 || !callerIsSystemOrActiveOrManagedUser( 2211 service, TAG, "getProfileConnectionState")) { 2212 return BluetoothProfile.STATE_DISCONNECTED; 2213 } 2214 2215 return service.mAdapterProperties.getProfileConnectionState(profile); 2216 } 2217 2218 @Override createBond(BluetoothDevice device, int transport, OobData remoteP192Data, OobData remoteP256Data, AttributionSource source, SynchronousResultReceiver receiver)2219 public void createBond(BluetoothDevice device, int transport, OobData remoteP192Data, 2220 OobData remoteP256Data, AttributionSource source, 2221 SynchronousResultReceiver receiver) { 2222 try { 2223 receiver.send(createBond(device, transport, remoteP192Data, remoteP256Data, 2224 source)); 2225 } catch (RuntimeException e) { 2226 receiver.propagateException(e); 2227 } 2228 } createBond(BluetoothDevice device, int transport, OobData remoteP192Data, OobData remoteP256Data, AttributionSource attributionSource)2229 private boolean createBond(BluetoothDevice device, int transport, OobData remoteP192Data, 2230 OobData remoteP256Data, AttributionSource attributionSource) { 2231 AdapterService service = getService(); 2232 if (service == null || !callerIsSystemOrActiveOrManagedUser(service, TAG, "createBond") 2233 || !Utils.checkConnectPermissionForDataDelivery( 2234 service, attributionSource, "AdapterService createBond")) { 2235 return false; 2236 } 2237 2238 // This conditional is required to satisfy permission dependencies 2239 // since createBond calls createBondOutOfBand with null value passed as data. 2240 // BluetoothDevice#createBond requires BLUETOOTH_ADMIN only. 2241 service.enforceBluetoothPrivilegedPermissionIfNeeded(remoteP192Data, remoteP256Data); 2242 2243 return service.createBond(device, transport, remoteP192Data, remoteP256Data, 2244 attributionSource.getPackageName()); 2245 } 2246 2247 @Override cancelBondProcess(BluetoothDevice device, AttributionSource source, SynchronousResultReceiver receiver)2248 public void cancelBondProcess(BluetoothDevice device, AttributionSource source, 2249 SynchronousResultReceiver receiver) { 2250 try { 2251 receiver.send(cancelBondProcess(device, source)); 2252 } catch (RuntimeException e) { 2253 receiver.propagateException(e); 2254 } 2255 } cancelBondProcess( BluetoothDevice device, AttributionSource attributionSource)2256 private boolean cancelBondProcess( 2257 BluetoothDevice device, AttributionSource attributionSource) { 2258 AdapterService service = getService(); 2259 if (service == null 2260 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "cancelBondProcess") 2261 || !Utils.checkConnectPermissionForDataDelivery( 2262 service, attributionSource, "AdapterService cancelBondProcess")) { 2263 return false; 2264 } 2265 2266 enforceBluetoothPrivilegedPermission(service); 2267 2268 DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device); 2269 if (deviceProp != null) { 2270 deviceProp.setBondingInitiatedLocally(false); 2271 } 2272 2273 return service.cancelBondNative(getBytesFromAddress(device.getAddress())); 2274 } 2275 2276 @Override removeBond(BluetoothDevice device, AttributionSource source, SynchronousResultReceiver receiver)2277 public void removeBond(BluetoothDevice device, AttributionSource source, 2278 SynchronousResultReceiver receiver) { 2279 try { 2280 receiver.send(removeBond(device, source)); 2281 } catch (RuntimeException e) { 2282 receiver.propagateException(e); 2283 } 2284 } removeBond(BluetoothDevice device, AttributionSource attributionSource)2285 private boolean removeBond(BluetoothDevice device, AttributionSource attributionSource) { 2286 AdapterService service = getService(); 2287 if (service == null 2288 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "removeBond") 2289 || !Utils.checkConnectPermissionForDataDelivery( 2290 service, attributionSource, "AdapterService removeBond")) { 2291 return false; 2292 } 2293 2294 DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device); 2295 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDED) { 2296 return false; 2297 } 2298 service.mBondAttemptCallerInfo.remove(device.getAddress()); 2299 deviceProp.setBondingInitiatedLocally(false); 2300 2301 Message msg = service.mBondStateMachine.obtainMessage(BondStateMachine.REMOVE_BOND); 2302 msg.obj = device; 2303 service.mBondStateMachine.sendMessage(msg); 2304 return true; 2305 } 2306 2307 @Override getBondState(BluetoothDevice device, AttributionSource source, SynchronousResultReceiver receiver)2308 public void getBondState(BluetoothDevice device, AttributionSource source, 2309 SynchronousResultReceiver receiver) { 2310 try { 2311 receiver.send(getBondState(device, source)); 2312 } catch (RuntimeException e) { 2313 receiver.propagateException(e); 2314 } 2315 } getBondState(BluetoothDevice device, AttributionSource attributionSource)2316 private int getBondState(BluetoothDevice device, AttributionSource attributionSource) { 2317 // don't check caller, may be called from system UI 2318 AdapterService service = getService(); 2319 if (service == null || !Utils.checkConnectPermissionForDataDelivery( 2320 service, attributionSource, "AdapterService getBondState")) { 2321 return BluetoothDevice.BOND_NONE; 2322 } 2323 2324 return service.getBondState(device); 2325 } 2326 2327 @Override isBondingInitiatedLocally(BluetoothDevice device, AttributionSource source, SynchronousResultReceiver receiver)2328 public void isBondingInitiatedLocally(BluetoothDevice device, AttributionSource source, 2329 SynchronousResultReceiver receiver) { 2330 try { 2331 receiver.send(isBondingInitiatedLocally(device, source)); 2332 } catch (RuntimeException e) { 2333 receiver.propagateException(e); 2334 } 2335 } isBondingInitiatedLocally( BluetoothDevice device, AttributionSource attributionSource)2336 private boolean isBondingInitiatedLocally( 2337 BluetoothDevice device, AttributionSource attributionSource) { 2338 // don't check caller, may be called from system UI 2339 AdapterService service = getService(); 2340 if (service == null || !Utils.checkConnectPermissionForDataDelivery( 2341 service, attributionSource, "AdapterService isBondingInitiatedLocally")) { 2342 return false; 2343 } 2344 2345 DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device); 2346 return deviceProp != null && deviceProp.isBondingInitiatedLocally(); 2347 } 2348 2349 @Override generateLocalOobData(int transport, IBluetoothOobDataCallback callback, AttributionSource source, SynchronousResultReceiver receiver)2350 public void generateLocalOobData(int transport, IBluetoothOobDataCallback callback, 2351 AttributionSource source, SynchronousResultReceiver receiver) { 2352 try { 2353 generateLocalOobData(transport, callback, source); 2354 receiver.send(null); 2355 } catch (RuntimeException e) { 2356 receiver.propagateException(e); 2357 } 2358 } generateLocalOobData(int transport, IBluetoothOobDataCallback callback, AttributionSource source)2359 private void generateLocalOobData(int transport, IBluetoothOobDataCallback callback, 2360 AttributionSource source) { 2361 AdapterService service = getService(); 2362 if (service == null 2363 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "generateLocalOobData") 2364 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 2365 return; 2366 } 2367 enforceBluetoothPrivilegedPermission(service); 2368 service.generateLocalOobData(transport, callback); 2369 } 2370 2371 @Override getSupportedProfiles(AttributionSource source, SynchronousResultReceiver receiver)2372 public void getSupportedProfiles(AttributionSource source, 2373 SynchronousResultReceiver receiver) { 2374 try { 2375 receiver.send(getSupportedProfiles(source)); 2376 } catch (RuntimeException e) { 2377 receiver.propagateException(e); 2378 } 2379 } getSupportedProfiles(AttributionSource source)2380 private long getSupportedProfiles(AttributionSource source) { 2381 AdapterService service = getService(); 2382 if (service == null 2383 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 2384 return 0; 2385 } 2386 enforceBluetoothPrivilegedPermission(service); 2387 2388 return Config.getSupportedProfilesBitMask(); 2389 } 2390 2391 @Override getConnectionState(BluetoothDevice device)2392 public int getConnectionState(BluetoothDevice device) { 2393 if (mService == null) { 2394 return BluetoothProfile.STATE_DISCONNECTED; 2395 } 2396 return getConnectionStateWithAttribution(device, 2397 Utils.getCallingAttributionSource(mService)); 2398 } 2399 2400 @Override getConnectionStateWithAttribution(BluetoothDevice device, AttributionSource source, SynchronousResultReceiver receiver)2401 public void getConnectionStateWithAttribution(BluetoothDevice device, 2402 AttributionSource source, SynchronousResultReceiver receiver) { 2403 try { 2404 receiver.send(getConnectionStateWithAttribution(device, source)); 2405 } catch (RuntimeException e) { 2406 receiver.propagateException(e); 2407 } 2408 } getConnectionStateWithAttribution( BluetoothDevice device, AttributionSource attributionSource)2409 public int getConnectionStateWithAttribution( 2410 BluetoothDevice device, AttributionSource attributionSource) { 2411 AdapterService service = getService(); 2412 if (service == null || !Utils.checkConnectPermissionForDataDelivery( 2413 service, attributionSource, "AdapterService getConnectionState")) { 2414 return BluetoothProfile.STATE_DISCONNECTED; 2415 } 2416 2417 return service.getConnectionState(device); 2418 } 2419 2420 @Override canBondWithoutDialog(BluetoothDevice device, AttributionSource source, SynchronousResultReceiver receiver)2421 public void canBondWithoutDialog(BluetoothDevice device, AttributionSource source, 2422 SynchronousResultReceiver receiver) { 2423 try { 2424 receiver.send(canBondWithoutDialog(device, source)); 2425 } catch (RuntimeException e) { 2426 receiver.propagateException(e); 2427 } 2428 } canBondWithoutDialog(BluetoothDevice device, AttributionSource source)2429 private boolean canBondWithoutDialog(BluetoothDevice device, AttributionSource source) { 2430 AdapterService service = getService(); 2431 if (service == null 2432 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 2433 return false; 2434 } 2435 2436 enforceBluetoothPrivilegedPermission(service); 2437 2438 return service.canBondWithoutDialog(device); 2439 } 2440 2441 @Override removeActiveDevice(@ctiveDeviceUse int profiles, AttributionSource source, SynchronousResultReceiver receiver)2442 public void removeActiveDevice(@ActiveDeviceUse int profiles, 2443 AttributionSource source, SynchronousResultReceiver receiver) { 2444 try { 2445 receiver.send(removeActiveDevice(profiles, source)); 2446 } catch (RuntimeException e) { 2447 receiver.propagateException(e); 2448 } 2449 } removeActiveDevice(@ctiveDeviceUse int profiles, AttributionSource source)2450 private boolean removeActiveDevice(@ActiveDeviceUse int profiles, 2451 AttributionSource source) { 2452 AdapterService service = getService(); 2453 if (service == null 2454 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "removeActiveDevice") 2455 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 2456 return false; 2457 } 2458 return service.setActiveDevice(null, profiles); 2459 } 2460 2461 @Override setActiveDevice(BluetoothDevice device, @ActiveDeviceUse int profiles, AttributionSource source, SynchronousResultReceiver receiver)2462 public void setActiveDevice(BluetoothDevice device, @ActiveDeviceUse int profiles, 2463 AttributionSource source, SynchronousResultReceiver receiver) { 2464 try { 2465 receiver.send(setActiveDevice(device, profiles, source)); 2466 } catch (RuntimeException e) { 2467 receiver.propagateException(e); 2468 } 2469 } setActiveDevice(BluetoothDevice device, @ActiveDeviceUse int profiles, AttributionSource source)2470 private boolean setActiveDevice(BluetoothDevice device, @ActiveDeviceUse int profiles, 2471 AttributionSource source) { 2472 AdapterService service = getService(); 2473 if (service == null 2474 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setActiveDevice") 2475 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 2476 return false; 2477 } 2478 2479 enforceBluetoothPrivilegedPermission(service); 2480 2481 return service.setActiveDevice(device, profiles); 2482 } 2483 2484 @Override getActiveDevices(@ctiveDeviceProfile int profile, AttributionSource source, SynchronousResultReceiver receiver)2485 public void getActiveDevices(@ActiveDeviceProfile int profile, 2486 AttributionSource source, SynchronousResultReceiver receiver) { 2487 try { 2488 receiver.send(getActiveDevices(profile, source)); 2489 } catch (RuntimeException e) { 2490 receiver.propagateException(e); 2491 } 2492 } getActiveDevices(@ctiveDeviceProfile int profile, AttributionSource source)2493 private List<BluetoothDevice> getActiveDevices(@ActiveDeviceProfile int profile, 2494 AttributionSource source) { 2495 AdapterService service = getService(); 2496 if (service == null 2497 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getActiveDevices") 2498 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 2499 return new ArrayList<>(); 2500 } 2501 2502 enforceBluetoothPrivilegedPermission(service); 2503 2504 return service.getActiveDevices(profile); 2505 } 2506 2507 @Override connectAllEnabledProfiles(BluetoothDevice device, AttributionSource source, SynchronousResultReceiver receiver)2508 public void connectAllEnabledProfiles(BluetoothDevice device, 2509 AttributionSource source, SynchronousResultReceiver receiver) { 2510 try { 2511 receiver.send(connectAllEnabledProfiles(device, source)); 2512 } catch (RuntimeException e) { 2513 receiver.propagateException(e); 2514 } 2515 } connectAllEnabledProfiles(BluetoothDevice device, AttributionSource source)2516 private int connectAllEnabledProfiles(BluetoothDevice device, 2517 AttributionSource source) { 2518 AdapterService service = getService(); 2519 if (service == null) { 2520 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; 2521 } 2522 if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "connectAllEnabledProfiles")) { 2523 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; 2524 } 2525 if (device == null) { 2526 throw new IllegalArgumentException("device cannot be null"); 2527 } 2528 if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { 2529 throw new IllegalArgumentException("device cannot have an invalid address"); 2530 } 2531 if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 2532 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; 2533 } 2534 2535 enforceBluetoothPrivilegedPermission(service); 2536 2537 try { 2538 return service.connectAllEnabledProfiles(device); 2539 } catch (Exception e) { 2540 Log.v(TAG, "connectAllEnabledProfiles() failed", e); 2541 SneakyThrow.sneakyThrow(e); 2542 throw new RuntimeException(e); 2543 } 2544 } 2545 2546 @Override disconnectAllEnabledProfiles(BluetoothDevice device, AttributionSource source, SynchronousResultReceiver receiver)2547 public void disconnectAllEnabledProfiles(BluetoothDevice device, 2548 AttributionSource source, SynchronousResultReceiver receiver) { 2549 try { 2550 receiver.send(disconnectAllEnabledProfiles(device, source)); 2551 } catch (RuntimeException e) { 2552 receiver.propagateException(e); 2553 } 2554 } disconnectAllEnabledProfiles(BluetoothDevice device, AttributionSource source)2555 private int disconnectAllEnabledProfiles(BluetoothDevice device, 2556 AttributionSource source) { 2557 AdapterService service = getService(); 2558 if (service == null) { 2559 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; 2560 } 2561 if (!callerIsSystemOrActiveOrManagedUser(service, 2562 TAG, "disconnectAllEnabledProfiles")) { 2563 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; 2564 } 2565 if (device == null) { 2566 throw new IllegalArgumentException("device cannot be null"); 2567 } 2568 if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { 2569 throw new IllegalArgumentException("device cannot have an invalid address"); 2570 } 2571 if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 2572 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; 2573 } 2574 2575 enforceBluetoothPrivilegedPermission(service); 2576 2577 try { 2578 return service.disconnectAllEnabledProfiles(device); 2579 } catch (Exception e) { 2580 Log.v(TAG, "disconnectAllEnabledProfiles() failed", e); 2581 SneakyThrow.sneakyThrow(e); 2582 throw new RuntimeException(e); 2583 } 2584 } 2585 2586 @Override getRemoteName(BluetoothDevice device, AttributionSource source, SynchronousResultReceiver receiver)2587 public void getRemoteName(BluetoothDevice device, AttributionSource source, 2588 SynchronousResultReceiver receiver) { 2589 try { 2590 receiver.send(getRemoteName(device, source)); 2591 } catch (RuntimeException e) { 2592 receiver.propagateException(e); 2593 } 2594 } getRemoteName(BluetoothDevice device, AttributionSource attributionSource)2595 private String getRemoteName(BluetoothDevice device, AttributionSource attributionSource) { 2596 AdapterService service = getService(); 2597 if (service == null 2598 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getRemoteName") 2599 || !Utils.checkConnectPermissionForDataDelivery( 2600 service, attributionSource, "AdapterService getRemoteName")) { 2601 return null; 2602 } 2603 2604 return service.getRemoteName(device); 2605 } 2606 2607 @Override getRemoteType(BluetoothDevice device, AttributionSource source, SynchronousResultReceiver receiver)2608 public void getRemoteType(BluetoothDevice device, AttributionSource source, 2609 SynchronousResultReceiver receiver) { 2610 try { 2611 receiver.send(getRemoteType(device, source)); 2612 } catch (RuntimeException e) { 2613 receiver.propagateException(e); 2614 } 2615 } getRemoteType(BluetoothDevice device, AttributionSource attributionSource)2616 private int getRemoteType(BluetoothDevice device, AttributionSource attributionSource) { 2617 AdapterService service = getService(); 2618 if (service == null 2619 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getRemoteType") 2620 || !Utils.checkConnectPermissionForDataDelivery( 2621 service, attributionSource, "AdapterService getRemoteType")) { 2622 return BluetoothDevice.DEVICE_TYPE_UNKNOWN; 2623 } 2624 2625 DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device); 2626 return deviceProp != null 2627 ? deviceProp.getDeviceType() : BluetoothDevice.DEVICE_TYPE_UNKNOWN; 2628 } 2629 2630 @Override getRemoteAlias(BluetoothDevice device)2631 public String getRemoteAlias(BluetoothDevice device) { 2632 if (mService == null) { 2633 return null; 2634 } 2635 return getRemoteAliasWithAttribution(device, 2636 Utils.getCallingAttributionSource(mService)); 2637 } 2638 2639 @Override getRemoteAliasWithAttribution(BluetoothDevice device, AttributionSource source, SynchronousResultReceiver receiver)2640 public void getRemoteAliasWithAttribution(BluetoothDevice device, AttributionSource source, 2641 SynchronousResultReceiver receiver) { 2642 try { 2643 receiver.send(getRemoteAliasWithAttribution(device, source)); 2644 } catch (RuntimeException e) { 2645 receiver.propagateException(e); 2646 } 2647 } getRemoteAliasWithAttribution( BluetoothDevice device, AttributionSource attributionSource)2648 private String getRemoteAliasWithAttribution( 2649 BluetoothDevice device, AttributionSource attributionSource) { 2650 AdapterService service = getService(); 2651 if (service == null 2652 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getRemoteAlias") 2653 || !Utils.checkConnectPermissionForDataDelivery( 2654 service, attributionSource, "AdapterService getRemoteAlias")) { 2655 return null; 2656 } 2657 2658 DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device); 2659 return deviceProp != null ? deviceProp.getAlias() : null; 2660 } 2661 2662 @Override setRemoteAlias(BluetoothDevice device, String name, AttributionSource source, SynchronousResultReceiver receiver)2663 public void setRemoteAlias(BluetoothDevice device, String name, AttributionSource source, 2664 SynchronousResultReceiver receiver) { 2665 try { 2666 receiver.send(setRemoteAlias(device, name, source)); 2667 } catch (RuntimeException e) { 2668 receiver.propagateException(e); 2669 } 2670 } setRemoteAlias(BluetoothDevice device, String name, AttributionSource attributionSource)2671 private int setRemoteAlias(BluetoothDevice device, String name, 2672 AttributionSource attributionSource) { 2673 AdapterService service = getService(); 2674 if (service == null) { 2675 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; 2676 } 2677 if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "setRemoteAlias")) { 2678 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; 2679 } 2680 if (name != null && name.isEmpty()) { 2681 throw new IllegalArgumentException("alias cannot be the empty string"); 2682 } 2683 2684 if (!hasBluetoothPrivilegedPermission(service)) { 2685 if (!Utils.checkConnectPermissionForDataDelivery( 2686 service, attributionSource, "AdapterService setRemoteAlias")) { 2687 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; 2688 } 2689 enforceCdmAssociation(service.mCompanionDeviceManager, service, 2690 attributionSource.getPackageName(), Binder.getCallingUid(), device); 2691 } 2692 2693 DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device); 2694 if (deviceProp == null) { 2695 return BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED; 2696 } 2697 deviceProp.setAlias(device, name); 2698 return BluetoothStatusCodes.SUCCESS; 2699 } 2700 2701 @Override getRemoteClass(BluetoothDevice device, AttributionSource source, SynchronousResultReceiver receiver)2702 public void getRemoteClass(BluetoothDevice device, AttributionSource source, 2703 SynchronousResultReceiver receiver) { 2704 try { 2705 receiver.send(getRemoteClass(device, source)); 2706 } catch (RuntimeException e) { 2707 receiver.propagateException(e); 2708 } 2709 } getRemoteClass(BluetoothDevice device, AttributionSource attributionSource)2710 private int getRemoteClass(BluetoothDevice device, AttributionSource attributionSource) { 2711 AdapterService service = getService(); 2712 if (service == null 2713 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getRemoteClass") 2714 || !Utils.checkConnectPermissionForDataDelivery( 2715 service, attributionSource, "AdapterService getRemoteClass")) { 2716 return 0; 2717 } 2718 2719 DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device); 2720 return deviceProp != null ? deviceProp.getBluetoothClass() : 0; 2721 } 2722 2723 @Override getRemoteUuids(BluetoothDevice device, AttributionSource source, SynchronousResultReceiver receiver)2724 public void getRemoteUuids(BluetoothDevice device, AttributionSource source, 2725 SynchronousResultReceiver receiver) { 2726 try { 2727 receiver.send(getRemoteUuids(device, source)); 2728 } catch (RuntimeException e) { 2729 receiver.propagateException(e); 2730 } 2731 } getRemoteUuids( BluetoothDevice device, AttributionSource attributionSource)2732 private List<ParcelUuid> getRemoteUuids( 2733 BluetoothDevice device, AttributionSource attributionSource) { 2734 AdapterService service = getService(); 2735 if (service == null 2736 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getRemoteUuids") 2737 || !Utils.checkConnectPermissionForDataDelivery( 2738 service, attributionSource, "AdapterService getRemoteUuids")) { 2739 return new ArrayList<>(); 2740 } 2741 2742 ParcelUuid[] parcels = service.getRemoteUuids(device); 2743 if (parcels == null) { 2744 return null; 2745 } 2746 return Arrays.asList(parcels); 2747 } 2748 2749 @Override fetchRemoteUuids(BluetoothDevice device)2750 public boolean fetchRemoteUuids(BluetoothDevice device) { 2751 if (mService == null) { 2752 return false; 2753 } 2754 return fetchRemoteUuidsWithAttribution(device, TRANSPORT_AUTO, 2755 Utils.getCallingAttributionSource(mService)); 2756 } 2757 2758 @Override fetchRemoteUuidsWithAttribution(BluetoothDevice device, int transport, AttributionSource source, SynchronousResultReceiver receiver)2759 public void fetchRemoteUuidsWithAttribution(BluetoothDevice device, int transport, 2760 AttributionSource source, SynchronousResultReceiver receiver) { 2761 try { 2762 receiver.send(fetchRemoteUuidsWithAttribution(device, transport, source)); 2763 } catch (RuntimeException e) { 2764 receiver.propagateException(e); 2765 } 2766 } fetchRemoteUuidsWithAttribution( BluetoothDevice device, int transport, AttributionSource attributionSource)2767 private boolean fetchRemoteUuidsWithAttribution( 2768 BluetoothDevice device, int transport, AttributionSource attributionSource) { 2769 AdapterService service = getService(); 2770 if (service == null 2771 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "fetchRemoteUuids") 2772 || !Utils.checkConnectPermissionForDataDelivery( 2773 service, attributionSource, "AdapterService fetchRemoteUuids")) { 2774 return false; 2775 } 2776 if (transport != TRANSPORT_AUTO) { 2777 enforceBluetoothPrivilegedPermission(service); 2778 } 2779 2780 service.mRemoteDevices.fetchUuids(device, transport); 2781 return true; 2782 } 2783 2784 @Override setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode, AttributionSource source, SynchronousResultReceiver receiver)2785 public void setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode, 2786 AttributionSource source, SynchronousResultReceiver receiver) { 2787 try { 2788 receiver.send(setPin(device, accept, len, pinCode, source)); 2789 } catch (RuntimeException e) { 2790 receiver.propagateException(e); 2791 } 2792 } setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode, AttributionSource attributionSource)2793 private boolean setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode, 2794 AttributionSource attributionSource) { 2795 AdapterService service = getService(); 2796 if (service == null 2797 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setPin") 2798 || !Utils.checkConnectPermissionForDataDelivery( 2799 service, attributionSource, "AdapterService setPin")) { 2800 return false; 2801 } 2802 2803 DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device); 2804 // Only allow setting a pin in bonding state, or bonded state in case of security 2805 // upgrade. 2806 if (deviceProp == null || !deviceProp.isBondingOrBonded()) { 2807 return false; 2808 } 2809 if (pinCode.length != len) { 2810 android.util.EventLog.writeEvent(0x534e4554, "139287605", -1, 2811 "PIN code length mismatch"); 2812 return false; 2813 } 2814 service.logUserBondResponse(device, accept, 2815 BluetoothProtoEnums.BOND_SUB_STATE_LOCAL_PIN_REPLIED); 2816 return service.pinReplyNative( 2817 getBytesFromAddress(device.getAddress()), accept, len, pinCode); 2818 } 2819 2820 @Override setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey, AttributionSource source, SynchronousResultReceiver receiver)2821 public void setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey, 2822 AttributionSource source, SynchronousResultReceiver receiver) { 2823 try { 2824 receiver.send(setPasskey(device, accept, len, passkey, source)); 2825 } catch (RuntimeException e) { 2826 receiver.propagateException(e); 2827 } 2828 } setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey, AttributionSource attributionSource)2829 private boolean setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey, 2830 AttributionSource attributionSource) { 2831 AdapterService service = getService(); 2832 if (service == null 2833 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setPasskey") 2834 || !Utils.checkConnectPermissionForDataDelivery( 2835 service, attributionSource, "AdapterService setPasskey")) { 2836 return false; 2837 } 2838 2839 DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device); 2840 if (deviceProp == null || !deviceProp.isBonding()) { 2841 return false; 2842 } 2843 if (passkey.length != len) { 2844 android.util.EventLog.writeEvent(0x534e4554, "139287605", -1, 2845 "Passkey length mismatch"); 2846 return false; 2847 } 2848 service.logUserBondResponse(device, accept, BluetoothProtoEnums.BOND_SUB_STATE_LOCAL_SSP_REPLIED); 2849 return service.sspReplyNative( 2850 getBytesFromAddress(device.getAddress()), 2851 AbstractionLayer.BT_SSP_VARIANT_PASSKEY_ENTRY, 2852 accept, 2853 Utils.byteArrayToInt(passkey)); 2854 } 2855 2856 @Override setPairingConfirmation(BluetoothDevice device, boolean accept, AttributionSource source, SynchronousResultReceiver receiver)2857 public void setPairingConfirmation(BluetoothDevice device, boolean accept, 2858 AttributionSource source, SynchronousResultReceiver receiver) { 2859 try { 2860 receiver.send(setPairingConfirmation(device, accept, source)); 2861 } catch (RuntimeException e) { 2862 receiver.propagateException(e); 2863 } 2864 } setPairingConfirmation(BluetoothDevice device, boolean accept, AttributionSource source)2865 private boolean setPairingConfirmation(BluetoothDevice device, boolean accept, 2866 AttributionSource source) { 2867 AdapterService service = getService(); 2868 if (service == null 2869 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setPairingConfirmation") 2870 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 2871 return false; 2872 } 2873 2874 enforceBluetoothPrivilegedPermission(service); 2875 2876 DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device); 2877 if (deviceProp == null || !deviceProp.isBonding()) { 2878 return false; 2879 } 2880 service.logUserBondResponse(device, accept, BluetoothProtoEnums.BOND_SUB_STATE_LOCAL_SSP_REPLIED); 2881 return service.sspReplyNative( 2882 getBytesFromAddress(device.getAddress()), 2883 AbstractionLayer.BT_SSP_VARIANT_PASSKEY_CONFIRMATION, 2884 accept, 2885 0); 2886 } 2887 2888 @Override getSilenceMode(BluetoothDevice device, AttributionSource source, SynchronousResultReceiver receiver)2889 public void getSilenceMode(BluetoothDevice device, AttributionSource source, 2890 SynchronousResultReceiver receiver) { 2891 try { 2892 receiver.send(getSilenceMode(device, source)); 2893 } catch (RuntimeException e) { 2894 receiver.propagateException(e); 2895 } 2896 } getSilenceMode(BluetoothDevice device, AttributionSource source)2897 private boolean getSilenceMode(BluetoothDevice device, AttributionSource source) { 2898 AdapterService service = getService(); 2899 if (service == null 2900 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getSilenceMode") 2901 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 2902 return false; 2903 } 2904 2905 enforceBluetoothPrivilegedPermission(service); 2906 2907 return service.mSilenceDeviceManager.getSilenceMode(device); 2908 } 2909 2910 @Override setSilenceMode(BluetoothDevice device, boolean silence, AttributionSource source, SynchronousResultReceiver receiver)2911 public void setSilenceMode(BluetoothDevice device, boolean silence, 2912 AttributionSource source, SynchronousResultReceiver receiver) { 2913 try { 2914 receiver.send(setSilenceMode(device, silence, source)); 2915 } catch (RuntimeException e) { 2916 receiver.propagateException(e); 2917 } 2918 } setSilenceMode(BluetoothDevice device, boolean silence, AttributionSource source)2919 private boolean setSilenceMode(BluetoothDevice device, boolean silence, 2920 AttributionSource source) { 2921 AdapterService service = getService(); 2922 if (service == null 2923 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setSilenceMode") 2924 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 2925 return false; 2926 } 2927 2928 enforceBluetoothPrivilegedPermission(service); 2929 2930 service.mSilenceDeviceManager.setSilenceMode(device, silence); 2931 return true; 2932 } 2933 2934 @Override getPhonebookAccessPermission(BluetoothDevice device, AttributionSource source, SynchronousResultReceiver receiver)2935 public void getPhonebookAccessPermission(BluetoothDevice device, AttributionSource source, 2936 SynchronousResultReceiver receiver) { 2937 try { 2938 receiver.send(getPhonebookAccessPermission(device, source)); 2939 } catch (RuntimeException e) { 2940 receiver.propagateException(e); 2941 } 2942 } getPhonebookAccessPermission( BluetoothDevice device, AttributionSource attributionSource)2943 private int getPhonebookAccessPermission( 2944 BluetoothDevice device, AttributionSource attributionSource) { 2945 AdapterService service = getService(); 2946 if (service == null 2947 || !callerIsSystemOrActiveOrManagedUser( 2948 service, TAG, "getPhonebookAccessPermission") 2949 || !Utils.checkConnectPermissionForDataDelivery( 2950 service, attributionSource, "AdapterService getPhonebookAccessPermission")) { 2951 return BluetoothDevice.ACCESS_UNKNOWN; 2952 } 2953 2954 return service.getDeviceAccessFromPrefs(device, PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE); 2955 } 2956 2957 @Override setPhonebookAccessPermission(BluetoothDevice device, int value, AttributionSource source, SynchronousResultReceiver receiver)2958 public void setPhonebookAccessPermission(BluetoothDevice device, int value, 2959 AttributionSource source, SynchronousResultReceiver receiver) { 2960 try { 2961 receiver.send(setPhonebookAccessPermission(device, value, source)); 2962 } catch (RuntimeException e) { 2963 receiver.propagateException(e); 2964 } 2965 } setPhonebookAccessPermission(BluetoothDevice device, int value, AttributionSource source)2966 private boolean setPhonebookAccessPermission(BluetoothDevice device, int value, 2967 AttributionSource source) { 2968 AdapterService service = getService(); 2969 if (service == null 2970 || !callerIsSystemOrActiveOrManagedUser(service, 2971 TAG, "setPhonebookAccessPermission") 2972 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 2973 return false; 2974 } 2975 2976 enforceBluetoothPrivilegedPermission(service); 2977 2978 service.setPhonebookAccessPermission(device, value); 2979 return true; 2980 } 2981 2982 @Override getMessageAccessPermission(BluetoothDevice device, AttributionSource source, SynchronousResultReceiver receiver)2983 public void getMessageAccessPermission(BluetoothDevice device, AttributionSource source, 2984 SynchronousResultReceiver receiver) { 2985 try { 2986 receiver.send(getMessageAccessPermission(device, source)); 2987 } catch (RuntimeException e) { 2988 receiver.propagateException(e); 2989 } 2990 } getMessageAccessPermission( BluetoothDevice device, AttributionSource attributionSource)2991 private int getMessageAccessPermission( 2992 BluetoothDevice device, AttributionSource attributionSource) { 2993 AdapterService service = getService(); 2994 if (service == null 2995 || !callerIsSystemOrActiveOrManagedUser(service, 2996 TAG, "getMessageAccessPermission") 2997 || !Utils.checkConnectPermissionForDataDelivery( 2998 service, attributionSource, "AdapterService getMessageAccessPermission")) { 2999 return BluetoothDevice.ACCESS_UNKNOWN; 3000 } 3001 3002 return service.getDeviceAccessFromPrefs(device, MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE); 3003 } 3004 3005 @Override setMessageAccessPermission(BluetoothDevice device, int value, AttributionSource source, SynchronousResultReceiver receiver)3006 public void setMessageAccessPermission(BluetoothDevice device, int value, 3007 AttributionSource source, SynchronousResultReceiver receiver) { 3008 try { 3009 receiver.send(setMessageAccessPermission(device, value, source)); 3010 } catch (RuntimeException e) { 3011 receiver.propagateException(e); 3012 } 3013 } setMessageAccessPermission(BluetoothDevice device, int value, AttributionSource source)3014 private boolean setMessageAccessPermission(BluetoothDevice device, int value, 3015 AttributionSource source) { 3016 AdapterService service = getService(); 3017 if (service == null 3018 || !callerIsSystemOrActiveOrManagedUser(service, 3019 TAG, "setMessageAccessPermission") 3020 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3021 return false; 3022 } 3023 3024 enforceBluetoothPrivilegedPermission(service); 3025 3026 service.setMessageAccessPermission(device, value); 3027 return true; 3028 } 3029 3030 @Override getSimAccessPermission(BluetoothDevice device, AttributionSource source, SynchronousResultReceiver receiver)3031 public void getSimAccessPermission(BluetoothDevice device, AttributionSource source, 3032 SynchronousResultReceiver receiver) { 3033 try { 3034 receiver.send(getSimAccessPermission(device, source)); 3035 } catch (RuntimeException e) { 3036 receiver.propagateException(e); 3037 } 3038 } getSimAccessPermission( BluetoothDevice device, AttributionSource attributionSource)3039 private int getSimAccessPermission( 3040 BluetoothDevice device, AttributionSource attributionSource) { 3041 AdapterService service = getService(); 3042 if (service == null 3043 || !callerIsSystemOrActiveOrManagedUser(service, 3044 TAG, "getSimAccessPermission") 3045 || !Utils.checkConnectPermissionForDataDelivery( 3046 service, attributionSource, "AdapterService getSimAccessPermission")) { 3047 return BluetoothDevice.ACCESS_UNKNOWN; 3048 } 3049 3050 return service.getDeviceAccessFromPrefs(device, SIM_ACCESS_PERMISSION_PREFERENCE_FILE); 3051 } 3052 3053 @Override setSimAccessPermission(BluetoothDevice device, int value, AttributionSource source, SynchronousResultReceiver receiver)3054 public void setSimAccessPermission(BluetoothDevice device, int value, 3055 AttributionSource source, SynchronousResultReceiver receiver) { 3056 try { 3057 receiver.send(setSimAccessPermission(device, value, source)); 3058 } catch (RuntimeException e) { 3059 receiver.propagateException(e); 3060 } 3061 } setSimAccessPermission(BluetoothDevice device, int value, AttributionSource source)3062 private boolean setSimAccessPermission(BluetoothDevice device, int value, 3063 AttributionSource source) { 3064 AdapterService service = getService(); 3065 if (service == null 3066 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setSimAccessPermission") 3067 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3068 return false; 3069 } 3070 3071 enforceBluetoothPrivilegedPermission(service); 3072 3073 service.setSimAccessPermission(device, value); 3074 return true; 3075 } 3076 3077 @Override getSocketManager()3078 public IBluetoothSocketManager getSocketManager() { 3079 AdapterService service = getService(); 3080 if (service == null) { 3081 return null; 3082 } 3083 3084 return IBluetoothSocketManager.Stub.asInterface(service.mBluetoothSocketManagerBinder); 3085 } 3086 3087 @Override sdpSearch(BluetoothDevice device, ParcelUuid uuid, AttributionSource source, SynchronousResultReceiver receiver)3088 public void sdpSearch(BluetoothDevice device, ParcelUuid uuid, AttributionSource source, 3089 SynchronousResultReceiver receiver) { 3090 try { 3091 receiver.send(sdpSearch(device, uuid, source)); 3092 } catch (RuntimeException e) { 3093 receiver.propagateException(e); 3094 } 3095 } sdpSearch( BluetoothDevice device, ParcelUuid uuid, AttributionSource attributionSource)3096 private boolean sdpSearch( 3097 BluetoothDevice device, ParcelUuid uuid, AttributionSource attributionSource) { 3098 AdapterService service = getService(); 3099 if (service == null 3100 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "sdpSearch") 3101 || !Utils.checkConnectPermissionForDataDelivery( 3102 service, attributionSource, "AdapterService sdpSearch")) { 3103 return false; 3104 } 3105 3106 if (service.mSdpManager == null) { 3107 return false; 3108 } 3109 service.mSdpManager.sdpSearch(device, uuid); 3110 return true; 3111 } 3112 3113 @Override getBatteryLevel(BluetoothDevice device, AttributionSource source, SynchronousResultReceiver receiver)3114 public void getBatteryLevel(BluetoothDevice device, AttributionSource source, 3115 SynchronousResultReceiver receiver) { 3116 try { 3117 receiver.send(getBatteryLevel(device, source)); 3118 } catch (RuntimeException e) { 3119 receiver.propagateException(e); 3120 } 3121 } getBatteryLevel(BluetoothDevice device, AttributionSource attributionSource)3122 private int getBatteryLevel(BluetoothDevice device, AttributionSource attributionSource) { 3123 AdapterService service = getService(); 3124 if (service == null 3125 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getBatteryLevel") 3126 || !Utils.checkConnectPermissionForDataDelivery( 3127 service, attributionSource, "AdapterService getBatteryLevel")) { 3128 return BluetoothDevice.BATTERY_LEVEL_UNKNOWN; 3129 } 3130 3131 DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device); 3132 if (deviceProp == null) { 3133 return BluetoothDevice.BATTERY_LEVEL_UNKNOWN; 3134 } 3135 return deviceProp.getBatteryLevel(); 3136 } 3137 3138 @Override getMaxConnectedAudioDevices(AttributionSource source, SynchronousResultReceiver receiver)3139 public void getMaxConnectedAudioDevices(AttributionSource source, 3140 SynchronousResultReceiver receiver) { 3141 try { 3142 receiver.send(getMaxConnectedAudioDevices(source)); 3143 } catch (RuntimeException e) { 3144 receiver.propagateException(e); 3145 } 3146 } getMaxConnectedAudioDevices(AttributionSource attributionSource)3147 private int getMaxConnectedAudioDevices(AttributionSource attributionSource) { 3148 // don't check caller, may be called from system UI 3149 AdapterService service = getService(); 3150 if (service == null || !Utils.checkConnectPermissionForDataDelivery( 3151 service, attributionSource, "AdapterService getMaxConnectedAudioDevices")) { 3152 return -1; 3153 } 3154 3155 return service.getMaxConnectedAudioDevices(); 3156 } 3157 3158 //@Override 3159 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) isA2dpOffloadEnabled(AttributionSource source, SynchronousResultReceiver receiver)3160 public void isA2dpOffloadEnabled(AttributionSource source, 3161 SynchronousResultReceiver receiver) { 3162 try { 3163 receiver.send(isA2dpOffloadEnabled(source)); 3164 } catch (RuntimeException e) { 3165 receiver.propagateException(e); 3166 } 3167 } isA2dpOffloadEnabled(AttributionSource attributionSource)3168 private boolean isA2dpOffloadEnabled(AttributionSource attributionSource) { 3169 // don't check caller, may be called from system UI 3170 AdapterService service = getService(); 3171 if (service == null || !Utils.checkConnectPermissionForDataDelivery( 3172 service, attributionSource, "AdapterService isA2dpOffloadEnabled")) { 3173 return false; 3174 } 3175 3176 return service.isA2dpOffloadEnabled(); 3177 } 3178 3179 @Override factoryReset(AttributionSource source, SynchronousResultReceiver receiver)3180 public void factoryReset(AttributionSource source, SynchronousResultReceiver receiver) { 3181 try { 3182 receiver.send(factoryReset(source)); 3183 } catch (RuntimeException e) { 3184 receiver.propagateException(e); 3185 } 3186 } 3187 @VisibleForTesting factoryReset(AttributionSource source)3188 boolean factoryReset(AttributionSource source) { 3189 AdapterService service = getService(); 3190 if (service == null 3191 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3192 return false; 3193 } 3194 3195 enforceBluetoothPrivilegedPermission(service); 3196 3197 if (service.mDatabaseManager != null) { 3198 service.mDatabaseManager.factoryReset(); 3199 } 3200 3201 if (service.mBluetoothKeystoreService != null) { 3202 service.mBluetoothKeystoreService.factoryReset(); 3203 } 3204 3205 if (service.mBtCompanionManager != null) { 3206 service.mBtCompanionManager.factoryReset(); 3207 } 3208 3209 return service.factoryResetNative(); 3210 } 3211 3212 @Override registerBluetoothConnectionCallback(IBluetoothConnectionCallback callback, AttributionSource source, SynchronousResultReceiver receiver)3213 public void registerBluetoothConnectionCallback(IBluetoothConnectionCallback callback, 3214 AttributionSource source, SynchronousResultReceiver receiver) { 3215 try { 3216 receiver.send(registerBluetoothConnectionCallback(callback, source)); 3217 } catch (RuntimeException e) { 3218 receiver.propagateException(e); 3219 } 3220 } registerBluetoothConnectionCallback(IBluetoothConnectionCallback callback, AttributionSource source)3221 private boolean registerBluetoothConnectionCallback(IBluetoothConnectionCallback callback, 3222 AttributionSource source) { 3223 AdapterService service = getService(); 3224 if (service == null 3225 || !callerIsSystemOrActiveOrManagedUser(service, 3226 TAG, "registerBluetoothConnectionCallback") 3227 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3228 return false; 3229 } 3230 enforceBluetoothPrivilegedPermission(service); 3231 service.mBluetoothConnectionCallbacks.add(callback); 3232 return true; 3233 } 3234 3235 @Override unregisterBluetoothConnectionCallback(IBluetoothConnectionCallback callback, AttributionSource source, SynchronousResultReceiver receiver)3236 public void unregisterBluetoothConnectionCallback(IBluetoothConnectionCallback callback, 3237 AttributionSource source, SynchronousResultReceiver receiver) { 3238 try { 3239 receiver.send(unregisterBluetoothConnectionCallback(callback, source)); 3240 } catch (RuntimeException e) { 3241 receiver.propagateException(e); 3242 } 3243 } unregisterBluetoothConnectionCallback( IBluetoothConnectionCallback callback, AttributionSource source)3244 private boolean unregisterBluetoothConnectionCallback( 3245 IBluetoothConnectionCallback callback, AttributionSource source) { 3246 AdapterService service = getService(); 3247 if (service == null 3248 || !callerIsSystemOrActiveOrManagedUser(service, 3249 TAG, "unregisterBluetoothConnectionCallback") 3250 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3251 return false; 3252 } 3253 enforceBluetoothPrivilegedPermission(service); 3254 return service.mBluetoothConnectionCallbacks.remove(callback); 3255 } 3256 3257 @Override registerCallback(IBluetoothCallback callback, AttributionSource source, SynchronousResultReceiver receiver)3258 public void registerCallback(IBluetoothCallback callback, AttributionSource source, 3259 SynchronousResultReceiver receiver) { 3260 try { 3261 registerCallback(callback, source); 3262 receiver.send(null); 3263 } catch (RuntimeException e) { 3264 receiver.propagateException(e); 3265 } 3266 } 3267 @VisibleForTesting registerCallback(IBluetoothCallback callback, AttributionSource source)3268 void registerCallback(IBluetoothCallback callback, AttributionSource source) { 3269 AdapterService service = getService(); 3270 if (service == null 3271 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "registerCallback") 3272 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3273 return; 3274 } 3275 3276 enforceBluetoothPrivilegedPermission(service); 3277 3278 service.mCallbacks.register(callback); 3279 } 3280 3281 @Override unregisterCallback(IBluetoothCallback callback, AttributionSource source, SynchronousResultReceiver receiver)3282 public void unregisterCallback(IBluetoothCallback callback, AttributionSource source, 3283 SynchronousResultReceiver receiver) { 3284 try { 3285 unregisterCallback(callback, source); 3286 receiver.send(null); 3287 } catch (RuntimeException e) { 3288 receiver.propagateException(e); 3289 } 3290 } 3291 @VisibleForTesting unregisterCallback(IBluetoothCallback callback, AttributionSource source)3292 void unregisterCallback(IBluetoothCallback callback, AttributionSource source) { 3293 AdapterService service = getService(); 3294 if (service == null || service.mCallbacks == null 3295 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "unregisterCallback") 3296 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3297 return; 3298 } 3299 3300 enforceBluetoothPrivilegedPermission(service); 3301 3302 service.mCallbacks.unregister(callback); 3303 } 3304 3305 @Override isMultiAdvertisementSupported(SynchronousResultReceiver receiver)3306 public void isMultiAdvertisementSupported(SynchronousResultReceiver receiver) { 3307 try { 3308 receiver.send(isMultiAdvertisementSupported()); 3309 } catch (RuntimeException e) { 3310 receiver.propagateException(e); 3311 } 3312 } isMultiAdvertisementSupported()3313 private boolean isMultiAdvertisementSupported() { 3314 AdapterService service = getService(); 3315 if (service == null) { 3316 return false; 3317 } 3318 3319 int val = service.mAdapterProperties.getNumOfAdvertisementInstancesSupported(); 3320 return val >= MIN_ADVT_INSTANCES_FOR_MA; 3321 } 3322 3323 /** 3324 * This method has an associated binder cache. The invalidation 3325 * methods must be changed if the logic behind this method changes. 3326 */ 3327 @Override isOffloadedFilteringSupported(SynchronousResultReceiver receiver)3328 public void isOffloadedFilteringSupported(SynchronousResultReceiver receiver) { 3329 try { 3330 receiver.send(isOffloadedFilteringSupported()); 3331 } catch (RuntimeException e) { 3332 receiver.propagateException(e); 3333 } 3334 } isOffloadedFilteringSupported()3335 private boolean isOffloadedFilteringSupported() { 3336 AdapterService service = getService(); 3337 if (service == null) { 3338 return false; 3339 } 3340 3341 int val = service.getNumOfOffloadedScanFilterSupported(); 3342 return val >= MIN_OFFLOADED_FILTERS; 3343 } 3344 3345 @Override isOffloadedScanBatchingSupported(SynchronousResultReceiver receiver)3346 public void isOffloadedScanBatchingSupported(SynchronousResultReceiver receiver) { 3347 try { 3348 receiver.send(isOffloadedScanBatchingSupported()); 3349 } catch (RuntimeException e) { 3350 receiver.propagateException(e); 3351 } 3352 } isOffloadedScanBatchingSupported()3353 private boolean isOffloadedScanBatchingSupported() { 3354 AdapterService service = getService(); 3355 if (service == null) { 3356 return false; 3357 } 3358 3359 int val = service.getOffloadedScanResultStorage(); 3360 return val >= MIN_OFFLOADED_SCAN_STORAGE_BYTES; 3361 } 3362 3363 @Override isLe2MPhySupported(SynchronousResultReceiver receiver)3364 public void isLe2MPhySupported(SynchronousResultReceiver receiver) { 3365 try { 3366 receiver.send(isLe2MPhySupported()); 3367 } catch (RuntimeException e) { 3368 receiver.propagateException(e); 3369 } 3370 } isLe2MPhySupported()3371 private boolean isLe2MPhySupported() { 3372 AdapterService service = getService(); 3373 if (service == null) { 3374 return false; 3375 } 3376 3377 return service.isLe2MPhySupported(); 3378 } 3379 3380 @Override isLeCodedPhySupported(SynchronousResultReceiver receiver)3381 public void isLeCodedPhySupported(SynchronousResultReceiver receiver) { 3382 try { 3383 receiver.send(isLeCodedPhySupported()); 3384 } catch (RuntimeException e) { 3385 receiver.propagateException(e); 3386 } 3387 } isLeCodedPhySupported()3388 private boolean isLeCodedPhySupported() { 3389 AdapterService service = getService(); 3390 if (service == null) { 3391 return false; 3392 } 3393 3394 return service.isLeCodedPhySupported(); 3395 } 3396 3397 @Override isLeExtendedAdvertisingSupported(SynchronousResultReceiver receiver)3398 public void isLeExtendedAdvertisingSupported(SynchronousResultReceiver receiver) { 3399 try { 3400 receiver.send(isLeExtendedAdvertisingSupported()); 3401 } catch (RuntimeException e) { 3402 receiver.propagateException(e); 3403 } 3404 } isLeExtendedAdvertisingSupported()3405 private boolean isLeExtendedAdvertisingSupported() { 3406 AdapterService service = getService(); 3407 if (service == null) { 3408 return false; 3409 } 3410 3411 return service.isLeExtendedAdvertisingSupported(); 3412 } 3413 3414 @Override isLePeriodicAdvertisingSupported(SynchronousResultReceiver receiver)3415 public void isLePeriodicAdvertisingSupported(SynchronousResultReceiver receiver) { 3416 try { 3417 receiver.send(isLePeriodicAdvertisingSupported()); 3418 } catch (RuntimeException e) { 3419 receiver.propagateException(e); 3420 } 3421 } isLePeriodicAdvertisingSupported()3422 private boolean isLePeriodicAdvertisingSupported() { 3423 AdapterService service = getService(); 3424 if (service == null) { 3425 return false; 3426 } 3427 3428 return service.isLePeriodicAdvertisingSupported(); 3429 } 3430 3431 @Override isLeAudioSupported(SynchronousResultReceiver receiver)3432 public void isLeAudioSupported(SynchronousResultReceiver receiver) { 3433 try { 3434 receiver.send(isLeAudioSupported()); 3435 } catch (RuntimeException e) { 3436 receiver.propagateException(e); 3437 } 3438 } isLeAudioSupported()3439 private int isLeAudioSupported() { 3440 AdapterService service = getService(); 3441 if (service == null) { 3442 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; 3443 } 3444 3445 HashSet<Class> supportedProfileServices = 3446 new HashSet<Class>(Arrays.asList(Config.getSupportedProfiles())); 3447 HashSet<Class> leAudioUnicastProfiles = Config.geLeAudioUnicastProfiles(); 3448 3449 if (supportedProfileServices.containsAll(leAudioUnicastProfiles)) { 3450 return BluetoothStatusCodes.FEATURE_SUPPORTED; 3451 } 3452 3453 return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED; 3454 } 3455 3456 @Override isLeAudioBroadcastSourceSupported(SynchronousResultReceiver receiver)3457 public void isLeAudioBroadcastSourceSupported(SynchronousResultReceiver receiver) { 3458 try { 3459 receiver.send(isLeAudioBroadcastSourceSupported()); 3460 } catch (RuntimeException e) { 3461 receiver.propagateException(e); 3462 } 3463 } isLeAudioBroadcastSourceSupported()3464 private int isLeAudioBroadcastSourceSupported() { 3465 AdapterService service = getService(); 3466 if (service == null) { 3467 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; 3468 } 3469 3470 long supportBitMask = Config.getSupportedProfilesBitMask(); 3471 if ((supportBitMask & (1 << BluetoothProfile.LE_AUDIO_BROADCAST)) != 0) { 3472 return BluetoothStatusCodes.FEATURE_SUPPORTED; 3473 } 3474 3475 return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED; 3476 } 3477 3478 @Override isLeAudioBroadcastAssistantSupported(SynchronousResultReceiver receiver)3479 public void isLeAudioBroadcastAssistantSupported(SynchronousResultReceiver receiver) { 3480 try { 3481 receiver.send(isLeAudioBroadcastAssistantSupported()); 3482 } catch (RuntimeException e) { 3483 receiver.propagateException(e); 3484 } 3485 } isLeAudioBroadcastAssistantSupported()3486 public int isLeAudioBroadcastAssistantSupported() { 3487 AdapterService service = getService(); 3488 if (service == null) { 3489 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; 3490 } 3491 3492 HashSet<Class> supportedProfileServices = 3493 new HashSet<Class>(Arrays.asList(Config.getSupportedProfiles())); 3494 3495 if (supportedProfileServices.contains(BassClientService.class)) { 3496 return BluetoothStatusCodes.FEATURE_SUPPORTED; 3497 } 3498 3499 return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED; 3500 } 3501 3502 @Override getLeMaximumAdvertisingDataLength(SynchronousResultReceiver receiver)3503 public void getLeMaximumAdvertisingDataLength(SynchronousResultReceiver receiver) { 3504 try { 3505 receiver.send(getLeMaximumAdvertisingDataLength()); 3506 } catch (RuntimeException e) { 3507 receiver.propagateException(e); 3508 } 3509 } getLeMaximumAdvertisingDataLength()3510 private int getLeMaximumAdvertisingDataLength() { 3511 AdapterService service = getService(); 3512 if (service == null) { 3513 return 0; 3514 } 3515 3516 return service.getLeMaximumAdvertisingDataLength(); 3517 } 3518 3519 @Override isActivityAndEnergyReportingSupported(SynchronousResultReceiver receiver)3520 public void isActivityAndEnergyReportingSupported(SynchronousResultReceiver receiver) { 3521 try { 3522 receiver.send(isActivityAndEnergyReportingSupported()); 3523 } catch (RuntimeException e) { 3524 receiver.propagateException(e); 3525 } 3526 } isActivityAndEnergyReportingSupported()3527 private boolean isActivityAndEnergyReportingSupported() { 3528 AdapterService service = getService(); 3529 if (service == null) { 3530 return false; 3531 } 3532 3533 return service.mAdapterProperties.isActivityAndEnergyReportingSupported(); 3534 } 3535 3536 @Override reportActivityInfo(AttributionSource source, SynchronousResultReceiver receiver)3537 public void reportActivityInfo(AttributionSource source, 3538 SynchronousResultReceiver receiver) { 3539 try { 3540 receiver.send(reportActivityInfo(source)); 3541 } catch (RuntimeException e) { 3542 receiver.propagateException(e); 3543 } 3544 } reportActivityInfo(AttributionSource source)3545 private BluetoothActivityEnergyInfo reportActivityInfo(AttributionSource source) { 3546 AdapterService service = getService(); 3547 if (service == null 3548 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3549 return null; 3550 } 3551 3552 enforceBluetoothPrivilegedPermission(service); 3553 3554 return service.reportActivityInfo(); 3555 } 3556 3557 @Override registerMetadataListener(IBluetoothMetadataListener listener, BluetoothDevice device, AttributionSource source, SynchronousResultReceiver receiver)3558 public void registerMetadataListener(IBluetoothMetadataListener listener, 3559 BluetoothDevice device, AttributionSource source, 3560 SynchronousResultReceiver receiver) { 3561 try { 3562 receiver.send(registerMetadataListener(listener, device, source)); 3563 } catch (RuntimeException e) { 3564 receiver.propagateException(e); 3565 } 3566 } registerMetadataListener(IBluetoothMetadataListener listener, BluetoothDevice device, AttributionSource source)3567 private boolean registerMetadataListener(IBluetoothMetadataListener listener, 3568 BluetoothDevice device, AttributionSource source) { 3569 AdapterService service = getService(); 3570 if (service == null 3571 || !callerIsSystemOrActiveOrManagedUser(service, 3572 TAG, "registerMetadataListener") 3573 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3574 return false; 3575 } 3576 3577 enforceBluetoothPrivilegedPermission(service); 3578 3579 if (service.mMetadataListeners == null) { 3580 return false; 3581 } 3582 ArrayList<IBluetoothMetadataListener> list = service.mMetadataListeners.get(device); 3583 if (list == null) { 3584 list = new ArrayList<>(); 3585 } else if (list.contains(listener)) { 3586 // The device is already registered with this listener 3587 return true; 3588 } 3589 list.add(listener); 3590 service.mMetadataListeners.put(device, list); 3591 return true; 3592 } 3593 3594 @Override unregisterMetadataListener(BluetoothDevice device, AttributionSource source, SynchronousResultReceiver receiver)3595 public void unregisterMetadataListener(BluetoothDevice device, AttributionSource source, 3596 SynchronousResultReceiver receiver) { 3597 try { 3598 receiver.send(unregisterMetadataListener(device, source)); 3599 } catch (RuntimeException e) { 3600 receiver.propagateException(e); 3601 } 3602 } unregisterMetadataListener(BluetoothDevice device, AttributionSource source)3603 private boolean unregisterMetadataListener(BluetoothDevice device, 3604 AttributionSource source) { 3605 AdapterService service = getService(); 3606 if (service == null 3607 || !callerIsSystemOrActiveOrManagedUser(service, 3608 TAG, "unregisterMetadataListener") 3609 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3610 return false; 3611 } 3612 3613 enforceBluetoothPrivilegedPermission(service); 3614 3615 if (service.mMetadataListeners == null) { 3616 return false; 3617 } 3618 if (service.mMetadataListeners.containsKey(device)) { 3619 service.mMetadataListeners.remove(device); 3620 } 3621 return true; 3622 } 3623 3624 @Override setMetadata(BluetoothDevice device, int key, byte[] value, AttributionSource source, SynchronousResultReceiver receiver)3625 public void setMetadata(BluetoothDevice device, int key, byte[] value, 3626 AttributionSource source, SynchronousResultReceiver receiver) { 3627 try { 3628 receiver.send(setMetadata(device, key, value, source)); 3629 } catch (RuntimeException e) { 3630 receiver.propagateException(e); 3631 } 3632 } setMetadata(BluetoothDevice device, int key, byte[] value, AttributionSource source)3633 private boolean setMetadata(BluetoothDevice device, int key, byte[] value, 3634 AttributionSource source) { 3635 AdapterService service = getService(); 3636 if (service == null 3637 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setMetadata") 3638 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3639 return false; 3640 } 3641 3642 enforceBluetoothPrivilegedPermission(service); 3643 3644 if (value.length > BluetoothDevice.METADATA_MAX_LENGTH) { 3645 return false; 3646 } 3647 return service.mDatabaseManager.setCustomMeta(device, key, value); 3648 } 3649 3650 @Override getMetadata(BluetoothDevice device, int key, AttributionSource source, SynchronousResultReceiver receiver)3651 public void getMetadata(BluetoothDevice device, int key, AttributionSource source, 3652 SynchronousResultReceiver receiver) { 3653 try { 3654 receiver.send(getMetadata(device, key, source)); 3655 } catch (RuntimeException e) { 3656 receiver.propagateException(e); 3657 } 3658 } getMetadata(BluetoothDevice device, int key, AttributionSource source)3659 private byte[] getMetadata(BluetoothDevice device, int key, 3660 AttributionSource source) { 3661 AdapterService service = getService(); 3662 if (service == null 3663 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getMetadata") 3664 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3665 return null; 3666 } 3667 3668 enforceBluetoothPrivilegedPermission(service); 3669 3670 return service.mDatabaseManager.getCustomMeta(device, key); 3671 } 3672 3673 @Override isRequestAudioPolicyAsSinkSupported(BluetoothDevice device, AttributionSource source, SynchronousResultReceiver receiver)3674 public void isRequestAudioPolicyAsSinkSupported(BluetoothDevice device, 3675 AttributionSource source, SynchronousResultReceiver receiver) { 3676 try { 3677 receiver.send(isRequestAudioPolicyAsSinkSupported(device, source)); 3678 } catch (RuntimeException e) { 3679 receiver.propagateException(e); 3680 } 3681 } isRequestAudioPolicyAsSinkSupported(BluetoothDevice device, AttributionSource source)3682 private int isRequestAudioPolicyAsSinkSupported(BluetoothDevice device, 3683 AttributionSource source) { 3684 AdapterService service = getService(); 3685 if (service == null 3686 || !callerIsSystemOrActiveOrManagedUser(service, TAG, 3687 "isRequestAudioPolicyAsSinkSupported") 3688 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3689 return BluetoothStatusCodes.FEATURE_NOT_CONFIGURED; 3690 } 3691 enforceBluetoothPrivilegedPermission(service); 3692 return service.isRequestAudioPolicyAsSinkSupported(device); 3693 } 3694 3695 @Override requestAudioPolicyAsSink(BluetoothDevice device, BluetoothSinkAudioPolicy policies, AttributionSource source, SynchronousResultReceiver receiver)3696 public void requestAudioPolicyAsSink(BluetoothDevice device, 3697 BluetoothSinkAudioPolicy policies, AttributionSource source, 3698 SynchronousResultReceiver receiver) { 3699 try { 3700 receiver.send(requestAudioPolicyAsSink(device, policies, source)); 3701 } catch (RuntimeException e) { 3702 receiver.propagateException(e); 3703 } 3704 } requestAudioPolicyAsSink(BluetoothDevice device, BluetoothSinkAudioPolicy policies, AttributionSource source)3705 private int requestAudioPolicyAsSink(BluetoothDevice device, 3706 BluetoothSinkAudioPolicy policies, AttributionSource source) { 3707 AdapterService service = getService(); 3708 if (service == null) { 3709 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; 3710 } else if (!callerIsSystemOrActiveOrManagedUser(service, 3711 TAG, "requestAudioPolicyAsSink")) { 3712 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; 3713 } else if (!Utils.checkConnectPermissionForDataDelivery( 3714 service, source, TAG)) { 3715 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; 3716 } 3717 enforceBluetoothPrivilegedPermission(service); 3718 return service.requestAudioPolicyAsSink(device, policies); 3719 } 3720 3721 @Override getRequestedAudioPolicyAsSink(BluetoothDevice device, AttributionSource source, SynchronousResultReceiver receiver)3722 public void getRequestedAudioPolicyAsSink(BluetoothDevice device, 3723 AttributionSource source, SynchronousResultReceiver receiver) { 3724 try { 3725 receiver.send(getRequestedAudioPolicyAsSink(device, source)); 3726 } catch (RuntimeException e) { 3727 receiver.propagateException(e); 3728 } 3729 } getRequestedAudioPolicyAsSink(BluetoothDevice device, AttributionSource source)3730 private BluetoothSinkAudioPolicy getRequestedAudioPolicyAsSink(BluetoothDevice device, 3731 AttributionSource source) { 3732 AdapterService service = getService(); 3733 if (service == null 3734 || !callerIsSystemOrActiveOrManagedUser(service, 3735 TAG, "getRequestedAudioPolicyAsSink") 3736 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3737 return null; 3738 } 3739 enforceBluetoothPrivilegedPermission(service); 3740 return service.getRequestedAudioPolicyAsSink(device); 3741 } 3742 3743 @Override requestActivityInfo(IBluetoothActivityEnergyInfoListener listener, AttributionSource source)3744 public void requestActivityInfo(IBluetoothActivityEnergyInfoListener listener, 3745 AttributionSource source) { 3746 BluetoothActivityEnergyInfo info = reportActivityInfo(source); 3747 try { 3748 listener.onBluetoothActivityEnergyInfoAvailable(info); 3749 } catch (RemoteException e) { 3750 Log.e(TAG, "onBluetoothActivityEnergyInfo: RemoteException", e); 3751 } 3752 } 3753 3754 @Override onLeServiceUp(AttributionSource source, SynchronousResultReceiver receiver)3755 public void onLeServiceUp(AttributionSource source, SynchronousResultReceiver receiver) { 3756 try { 3757 onLeServiceUp(source); 3758 receiver.send(null); 3759 } catch (RuntimeException e) { 3760 receiver.propagateException(e); 3761 } 3762 } 3763 @VisibleForTesting onLeServiceUp(AttributionSource source)3764 void onLeServiceUp(AttributionSource source) { 3765 AdapterService service = getService(); 3766 if (service == null 3767 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "onLeServiceUp") 3768 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3769 return; 3770 } 3771 3772 enforceBluetoothPrivilegedPermission(service); 3773 3774 service.mAdapterStateMachine.sendMessage(AdapterState.USER_TURN_ON); 3775 } 3776 3777 @Override onBrEdrDown(AttributionSource source, SynchronousResultReceiver receiver)3778 public void onBrEdrDown(AttributionSource source, SynchronousResultReceiver receiver) { 3779 try { 3780 onBrEdrDown(source); 3781 receiver.send(null); 3782 } catch (RuntimeException e) { 3783 receiver.propagateException(e); 3784 } 3785 } 3786 @VisibleForTesting onBrEdrDown(AttributionSource source)3787 void onBrEdrDown(AttributionSource source) { 3788 AdapterService service = getService(); 3789 if (service == null 3790 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "onBrEdrDown") 3791 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3792 return; 3793 } 3794 3795 enforceBluetoothPrivilegedPermission(service); 3796 3797 service.mAdapterStateMachine.sendMessage(AdapterState.BLE_TURN_OFF); 3798 } 3799 3800 @Override dump(FileDescriptor fd, String[] args)3801 public void dump(FileDescriptor fd, String[] args) { 3802 PrintWriter writer = new PrintWriter(new FileOutputStream(fd)); 3803 AdapterService service = getService(); 3804 if (service == null) { 3805 return; 3806 } 3807 3808 enforceDumpPermission(service); 3809 3810 service.dump(fd, writer, args); 3811 writer.close(); 3812 } 3813 3814 @Override allowLowLatencyAudio(boolean allowed, BluetoothDevice device, SynchronousResultReceiver receiver)3815 public void allowLowLatencyAudio(boolean allowed, BluetoothDevice device, 3816 SynchronousResultReceiver receiver) { 3817 try { 3818 receiver.send(allowLowLatencyAudio(allowed, device)); 3819 } catch (RuntimeException e) { 3820 receiver.propagateException(e); 3821 } 3822 } 3823 @RequiresPermission(allOf = { 3824 android.Manifest.permission.BLUETOOTH_CONNECT, 3825 android.Manifest.permission.BLUETOOTH_PRIVILEGED, 3826 }) allowLowLatencyAudio(boolean allowed, BluetoothDevice device)3827 private boolean allowLowLatencyAudio(boolean allowed, BluetoothDevice device) { 3828 AdapterService service = getService(); 3829 if (service == null 3830 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "allowLowLatencyAudio") 3831 || !Utils.checkConnectPermissionForDataDelivery( 3832 service, Utils.getCallingAttributionSource(service), 3833 "AdapterService allowLowLatencyAudio")) { 3834 return false; 3835 } 3836 enforceBluetoothPrivilegedPermission(service); 3837 return service.allowLowLatencyAudio(allowed, device); 3838 } 3839 3840 @Override startRfcommListener(String name, ParcelUuid uuid, PendingIntent pendingIntent, AttributionSource attributionSource, SynchronousResultReceiver receiver)3841 public void startRfcommListener(String name, ParcelUuid uuid, PendingIntent pendingIntent, 3842 AttributionSource attributionSource, SynchronousResultReceiver receiver) { 3843 try { 3844 receiver.send(startRfcommListener(name, uuid, pendingIntent, attributionSource)); 3845 } catch (RuntimeException e) { 3846 receiver.propagateException(e); 3847 } 3848 } 3849 @RequiresPermission(allOf = { 3850 android.Manifest.permission.BLUETOOTH_CONNECT, 3851 android.Manifest.permission.BLUETOOTH_PRIVILEGED, 3852 }) startRfcommListener( String name, ParcelUuid uuid, PendingIntent pendingIntent, AttributionSource attributionSource)3853 private int startRfcommListener( 3854 String name, 3855 ParcelUuid uuid, 3856 PendingIntent pendingIntent, 3857 AttributionSource attributionSource) { 3858 AdapterService service = getService(); 3859 if (service == null 3860 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "startRfcommListener") 3861 || !Utils.checkConnectPermissionForDataDelivery( 3862 service, attributionSource, "AdapterService startRfcommListener")) { 3863 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; 3864 } 3865 enforceBluetoothPrivilegedPermission(service); 3866 return service.startRfcommListener(name, uuid, pendingIntent, attributionSource); 3867 } 3868 3869 @Override stopRfcommListener(ParcelUuid uuid, AttributionSource attributionSource, SynchronousResultReceiver receiver)3870 public void stopRfcommListener(ParcelUuid uuid, AttributionSource attributionSource, 3871 SynchronousResultReceiver receiver) { 3872 try { 3873 receiver.send(stopRfcommListener(uuid, attributionSource)); 3874 } catch (RuntimeException e) { 3875 receiver.propagateException(e); 3876 } 3877 } 3878 @RequiresPermission(allOf = { 3879 android.Manifest.permission.BLUETOOTH_CONNECT, 3880 android.Manifest.permission.BLUETOOTH_PRIVILEGED, 3881 }) stopRfcommListener(ParcelUuid uuid, AttributionSource attributionSource)3882 private int stopRfcommListener(ParcelUuid uuid, AttributionSource attributionSource) { 3883 AdapterService service = getService(); 3884 if (service == null 3885 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "stopRfcommListener") 3886 || !Utils.checkConnectPermissionForDataDelivery( 3887 service, attributionSource, "AdapterService stopRfcommListener")) { 3888 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; 3889 } 3890 enforceBluetoothPrivilegedPermission(service); 3891 return service.stopRfcommListener(uuid, attributionSource); 3892 } 3893 3894 @Override retrievePendingSocketForServiceRecord(ParcelUuid uuid, AttributionSource attributionSource, SynchronousResultReceiver receiver)3895 public void retrievePendingSocketForServiceRecord(ParcelUuid uuid, 3896 AttributionSource attributionSource, SynchronousResultReceiver receiver) { 3897 try { 3898 receiver.send(retrievePendingSocketForServiceRecord(uuid, attributionSource)); 3899 } catch (RuntimeException e) { 3900 receiver.propagateException(e); 3901 } 3902 } 3903 @RequiresPermission(allOf = { 3904 android.Manifest.permission.BLUETOOTH_CONNECT, 3905 android.Manifest.permission.BLUETOOTH_PRIVILEGED, 3906 }) retrievePendingSocketForServiceRecord( ParcelUuid uuid, AttributionSource attributionSource)3907 private IncomingRfcommSocketInfo retrievePendingSocketForServiceRecord( 3908 ParcelUuid uuid, AttributionSource attributionSource) { 3909 AdapterService service = getService(); 3910 if (service == null 3911 || !callerIsSystemOrActiveOrManagedUser(service, 3912 TAG, "retrievePendingSocketForServiceRecord") 3913 || !Utils.checkConnectPermissionForDataDelivery( 3914 service, attributionSource, 3915 "AdapterService retrievePendingSocketForServiceRecord")) { 3916 return null; 3917 } 3918 enforceBluetoothPrivilegedPermission(service); 3919 return service.retrievePendingSocketForServiceRecord(uuid, attributionSource); 3920 } 3921 3922 @Override setForegroundUserId(int userId, AttributionSource attributionSource)3923 public void setForegroundUserId(int userId, AttributionSource attributionSource) { 3924 AdapterService service = getService(); 3925 if (service == null || !Utils.checkConnectPermissionForDataDelivery( 3926 service, Utils.getCallingAttributionSource(mService), 3927 "AdapterService setForegroundUserId")) { 3928 return; 3929 } 3930 enforceBluetoothPrivilegedPermission(service); 3931 Utils.setForegroundUserId(userId); 3932 } 3933 } 3934 3935 // ----API Methods-------- 3936 isEnabled()3937 public boolean isEnabled() { 3938 return getState() == BluetoothAdapter.STATE_ON; 3939 } 3940 getState()3941 public int getState() { 3942 if (mAdapterProperties != null) { 3943 return mAdapterProperties.getState(); 3944 } 3945 return BluetoothAdapter.STATE_OFF; 3946 } 3947 enable(boolean quietMode)3948 public synchronized boolean enable(boolean quietMode) { 3949 // Enforce the user restriction for disallowing Bluetooth if it was set. 3950 if (mUserManager.hasUserRestrictionForUser(UserManager.DISALLOW_BLUETOOTH, 3951 UserHandle.SYSTEM)) { 3952 debugLog("enable() called when Bluetooth was disallowed"); 3953 return false; 3954 } 3955 3956 debugLog("enable() - Enable called with quiet mode status = " + quietMode); 3957 mQuietmode = quietMode; 3958 mAdapterStateMachine.sendMessage(AdapterState.BLE_TURN_ON); 3959 return true; 3960 } 3961 disable()3962 boolean disable() { 3963 debugLog("disable() called with mRunningProfiles.size() = " + mRunningProfiles.size()); 3964 mAdapterStateMachine.sendMessage(AdapterState.USER_TURN_OFF); 3965 return true; 3966 } 3967 getName()3968 public String getName() { 3969 return mAdapterProperties.getName(); 3970 } 3971 getNameLengthForAdvertise()3972 public int getNameLengthForAdvertise() { 3973 return mAdapterProperties.getName().length(); 3974 } 3975 3976 @VisibleForTesting isValidIoCapability(int capability)3977 static boolean isValidIoCapability(int capability) { 3978 if (capability < 0 || capability >= BluetoothAdapter.IO_CAPABILITY_MAX) { 3979 Log.e(TAG, "Invalid IO capability value - " + capability); 3980 return false; 3981 } 3982 3983 return true; 3984 } 3985 getDiscoveringPackages()3986 ArrayList<DiscoveringPackage> getDiscoveringPackages() { 3987 return mDiscoveringPackages; 3988 } 3989 clearDiscoveringPackages()3990 void clearDiscoveringPackages() { 3991 synchronized (mDiscoveringPackages) { 3992 mDiscoveringPackages.clear(); 3993 } 3994 } 3995 startDiscovery(AttributionSource attributionSource)3996 boolean startDiscovery(AttributionSource attributionSource) { 3997 UserHandle callingUser = Binder.getCallingUserHandle(); 3998 debugLog("startDiscovery"); 3999 String callingPackage = attributionSource.getPackageName(); 4000 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); 4001 boolean isQApp = Utils.checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.Q); 4002 boolean hasDisavowedLocation = 4003 Utils.hasDisavowedLocationForScan(this, attributionSource, mTestModeEnabled); 4004 String permission = null; 4005 if (Utils.checkCallerHasNetworkSettingsPermission(this)) { 4006 permission = android.Manifest.permission.NETWORK_SETTINGS; 4007 } else if (Utils.checkCallerHasNetworkSetupWizardPermission(this)) { 4008 permission = android.Manifest.permission.NETWORK_SETUP_WIZARD; 4009 } else if (!hasDisavowedLocation) { 4010 if (isQApp) { 4011 if (!Utils.checkCallerHasFineLocation(this, attributionSource, callingUser)) { 4012 return false; 4013 } 4014 permission = android.Manifest.permission.ACCESS_FINE_LOCATION; 4015 } else { 4016 if (!Utils.checkCallerHasCoarseLocation(this, attributionSource, callingUser)) { 4017 return false; 4018 } 4019 permission = android.Manifest.permission.ACCESS_COARSE_LOCATION; 4020 } 4021 } 4022 4023 synchronized (mDiscoveringPackages) { 4024 mDiscoveringPackages.add( 4025 new DiscoveringPackage(callingPackage, permission, hasDisavowedLocation)); 4026 } 4027 return startDiscoveryNative(); 4028 } 4029 4030 /** 4031 * Same as API method {@link BluetoothAdapter#getBondedDevices()} 4032 * 4033 * @return array of bonded {@link BluetoothDevice} or null on error 4034 */ getBondedDevices()4035 public BluetoothDevice[] getBondedDevices() { 4036 return mAdapterProperties.getBondedDevices(); 4037 } 4038 4039 /** 4040 * Get the database manager to access Bluetooth storage 4041 * 4042 * @return {@link DatabaseManager} or null on error 4043 */ 4044 @VisibleForTesting getDatabase()4045 public DatabaseManager getDatabase() { 4046 return mDatabaseManager; 4047 } 4048 getByteIdentityAddress(BluetoothDevice device)4049 public byte[] getByteIdentityAddress(BluetoothDevice device) { 4050 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 4051 if (deviceProp != null && deviceProp.getIdentityAddress() != null) { 4052 return Utils.getBytesFromAddress(deviceProp.getIdentityAddress()); 4053 } else { 4054 return Utils.getByteAddress(device); 4055 } 4056 } 4057 getDeviceFromByte(byte[] address)4058 public BluetoothDevice getDeviceFromByte(byte[] address) { 4059 BluetoothDevice device = mRemoteDevices.getDevice(address); 4060 if (device == null) { 4061 device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address); 4062 } 4063 return device; 4064 } 4065 getIdentityAddress(String address)4066 public String getIdentityAddress(String address) { 4067 BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address.toUpperCase()); 4068 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 4069 if (deviceProp != null && deviceProp.getIdentityAddress() != null) { 4070 return deviceProp.getIdentityAddress(); 4071 } else { 4072 return address; 4073 } 4074 } 4075 4076 private class CallerInfo { 4077 public String callerPackageName; 4078 public UserHandle user; 4079 } 4080 createBond(BluetoothDevice device, int transport, OobData remoteP192Data, OobData remoteP256Data, String callingPackage)4081 boolean createBond(BluetoothDevice device, int transport, OobData remoteP192Data, 4082 OobData remoteP256Data, String callingPackage) { 4083 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 4084 if (deviceProp != null && deviceProp.getBondState() != BluetoothDevice.BOND_NONE) { 4085 return false; 4086 } 4087 4088 if (!isPackageNameAccurate(this, callingPackage, Binder.getCallingUid())) { 4089 return false; 4090 } 4091 4092 CallerInfo createBondCaller = new CallerInfo(); 4093 createBondCaller.callerPackageName = callingPackage; 4094 createBondCaller.user = Binder.getCallingUserHandle(); 4095 mBondAttemptCallerInfo.put(device.getAddress(), createBondCaller); 4096 4097 mRemoteDevices.setBondingInitiatedLocally(Utils.getByteAddress(device)); 4098 4099 // Pairing is unreliable while scanning, so cancel discovery 4100 // Note, remove this when native stack improves 4101 cancelDiscoveryNative(); 4102 4103 Message msg = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND); 4104 msg.obj = device; 4105 msg.arg1 = transport; 4106 4107 Bundle remoteOobDatasBundle = new Bundle(); 4108 boolean setData = false; 4109 if (remoteP192Data != null) { 4110 remoteOobDatasBundle.putParcelable(BondStateMachine.OOBDATAP192, remoteP192Data); 4111 setData = true; 4112 } 4113 if (remoteP256Data != null) { 4114 remoteOobDatasBundle.putParcelable(BondStateMachine.OOBDATAP256, remoteP256Data); 4115 setData = true; 4116 } 4117 if (setData) { 4118 msg.setData(remoteOobDatasBundle); 4119 } 4120 mBondStateMachine.sendMessage(msg); 4121 return true; 4122 } 4123 4124 private final ArrayDeque<IBluetoothOobDataCallback> mOobDataCallbackQueue = 4125 new ArrayDeque<>(); 4126 4127 /** 4128 * Fetches the local OOB data to give out to remote. 4129 * 4130 * @param transport - specify data transport. 4131 * @param callback - callback used to receive the requested {@link OobData}; null will be 4132 * ignored silently. 4133 * 4134 * @hide 4135 */ generateLocalOobData(int transport, IBluetoothOobDataCallback callback)4136 public synchronized void generateLocalOobData(int transport, 4137 IBluetoothOobDataCallback callback) { 4138 if (callback == null) { 4139 Log.e(TAG, "'callback' argument must not be null!"); 4140 return; 4141 } 4142 if (mOobDataCallbackQueue.peek() != null) { 4143 try { 4144 callback.onError(BluetoothStatusCodes.ERROR_ANOTHER_ACTIVE_OOB_REQUEST); 4145 } catch (RemoteException e) { 4146 Log.e(TAG, "Failed to make callback", e); 4147 } 4148 return; 4149 } 4150 mOobDataCallbackQueue.offer(callback); 4151 mHandler.postDelayed(() -> removeFromOobDataCallbackQueue(callback), 4152 GENERATE_LOCAL_OOB_DATA_TIMEOUT.toMillis()); 4153 generateLocalOobDataNative(transport); 4154 } 4155 removeFromOobDataCallbackQueue(IBluetoothOobDataCallback callback)4156 private synchronized void removeFromOobDataCallbackQueue(IBluetoothOobDataCallback callback) { 4157 if (callback == null) { 4158 return; 4159 } 4160 4161 if (mOobDataCallbackQueue.peek() == callback) { 4162 try { 4163 mOobDataCallbackQueue.poll().onError(BluetoothStatusCodes.ERROR_UNKNOWN); 4164 } catch (RemoteException e) { 4165 Log.e(TAG, "Failed to make OobDataCallback to remove callback from queue", e); 4166 } 4167 } 4168 } 4169 notifyOobDataCallback(int transport, OobData oobData)4170 /* package */ synchronized void notifyOobDataCallback(int transport, OobData oobData) { 4171 if (mOobDataCallbackQueue.peek() == null) { 4172 Log.e(TAG, "Failed to make callback, no callback exists"); 4173 return; 4174 } 4175 if (oobData == null) { 4176 try { 4177 mOobDataCallbackQueue.poll().onError(BluetoothStatusCodes.ERROR_UNKNOWN); 4178 } catch (RemoteException e) { 4179 Log.e(TAG, "Failed to make callback", e); 4180 } 4181 } else { 4182 try { 4183 mOobDataCallbackQueue.poll().onOobData(transport, oobData); 4184 } catch (RemoteException e) { 4185 Log.e(TAG, "Failed to make callback", e); 4186 } 4187 } 4188 } 4189 isQuietModeEnabled()4190 public boolean isQuietModeEnabled() { 4191 debugLog("isQuietModeEnabled() - Enabled = " + mQuietmode); 4192 return mQuietmode; 4193 } 4194 updateUuids()4195 public void updateUuids() { 4196 debugLog("updateUuids() - Updating UUIDs for bonded devices"); 4197 BluetoothDevice[] bondedDevices = getBondedDevices(); 4198 if (bondedDevices == null) { 4199 return; 4200 } 4201 4202 for (BluetoothDevice device : bondedDevices) { 4203 mRemoteDevices.updateUuids(device); 4204 } 4205 } 4206 4207 /** 4208 * Update device UUID changed to {@link BondStateMachine} 4209 * 4210 * @param device remote device of interest 4211 */ deviceUuidUpdated(BluetoothDevice device)4212 public void deviceUuidUpdated(BluetoothDevice device) { 4213 // Notify BondStateMachine for SDP complete / UUID changed. 4214 Message msg = mBondStateMachine.obtainMessage(BondStateMachine.UUID_UPDATE); 4215 msg.obj = device; 4216 mBondStateMachine.sendMessage(msg); 4217 } 4218 4219 /** 4220 * Get the bond state of a particular {@link BluetoothDevice} 4221 * 4222 * @param device remote device of interest 4223 * @return bond state <p>Possible values are 4224 * {@link BluetoothDevice#BOND_NONE}, 4225 * {@link BluetoothDevice#BOND_BONDING}, 4226 * {@link BluetoothDevice#BOND_BONDED}. 4227 */ 4228 @VisibleForTesting getBondState(BluetoothDevice device)4229 public int getBondState(BluetoothDevice device) { 4230 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 4231 if (deviceProp == null) { 4232 return BluetoothDevice.BOND_NONE; 4233 } 4234 return deviceProp.getBondState(); 4235 } 4236 getConnectionState(BluetoothDevice device)4237 int getConnectionState(BluetoothDevice device) { 4238 return getConnectionStateNative(getBytesFromAddress(device.getAddress())); 4239 } 4240 4241 /** 4242 * Checks whether the device was recently associated with the comapnion app that called 4243 * {@link BluetoothDevice#createBond}. This allows these devices to skip the pairing dialog if 4244 * their pairing variant is {@link BluetoothDevice#PAIRING_VARIANT_CONSENT}. 4245 * 4246 * @param device the bluetooth device that is being bonded 4247 * @return true if it was recently associated and we can bypass the dialog, false otherwise 4248 */ canBondWithoutDialog(BluetoothDevice device)4249 public boolean canBondWithoutDialog(BluetoothDevice device) { 4250 if (mBondAttemptCallerInfo.containsKey(device.getAddress())) { 4251 CallerInfo bondCallerInfo = mBondAttemptCallerInfo.get(device.getAddress()); 4252 4253 return mCompanionDeviceManager.canPairWithoutPrompt(bondCallerInfo.callerPackageName, 4254 device.getAddress(), bondCallerInfo.user); 4255 } 4256 return false; 4257 } 4258 4259 /** 4260 * Sets device as the active devices for the profiles passed into the function 4261 * 4262 * @param device is the remote bluetooth device 4263 * @param profiles is a constant that references for which profiles we'll be setting the remote 4264 * device as our active device. One of the following: 4265 * {@link BluetoothAdapter#ACTIVE_DEVICE_AUDIO}, 4266 * {@link BluetoothAdapter#ACTIVE_DEVICE_PHONE_CALL} 4267 * {@link BluetoothAdapter#ACTIVE_DEVICE_ALL} 4268 * @return false if profiles value is not one of the constants we accept, true otherwise 4269 */ 4270 @RequiresPermission(allOf = { 4271 android.Manifest.permission.BLUETOOTH_PRIVILEGED, 4272 android.Manifest.permission.MODIFY_PHONE_STATE, 4273 }) setActiveDevice(BluetoothDevice device, @ActiveDeviceUse int profiles)4274 public boolean setActiveDevice(BluetoothDevice device, @ActiveDeviceUse int profiles) { 4275 boolean setA2dp = false; 4276 boolean setHeadset = false; 4277 4278 // Determine for which profiles we want to set device as our active device 4279 switch(profiles) { 4280 case BluetoothAdapter.ACTIVE_DEVICE_AUDIO: 4281 setA2dp = true; 4282 break; 4283 case BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL: 4284 setHeadset = true; 4285 break; 4286 case BluetoothAdapter.ACTIVE_DEVICE_ALL: 4287 setA2dp = true; 4288 setHeadset = true; 4289 break; 4290 default: 4291 return false; 4292 } 4293 4294 if (mLeAudioService != null && (device == null 4295 || mLeAudioService.getConnectionPolicy(device) 4296 == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) { 4297 Log.i(TAG, "setActiveDevice: Setting active Le Audio device " + device); 4298 mLeAudioService.setActiveDevice(device); 4299 } 4300 4301 if (setA2dp && mA2dpService != null && (device == null 4302 || mA2dpService.getConnectionPolicy(device) 4303 == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) { 4304 Log.i(TAG, "setActiveDevice: Setting active A2dp device " + device); 4305 mA2dpService.setActiveDevice(device); 4306 } 4307 4308 if (mHearingAidService != null && (device == null 4309 || mHearingAidService.getConnectionPolicy(device) 4310 == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) { 4311 Log.i(TAG, "setActiveDevice: Setting active Hearing Aid " + device); 4312 mHearingAidService.setActiveDevice(device); 4313 } 4314 4315 if (setHeadset && mHeadsetService != null && (device == null 4316 || mHeadsetService.getConnectionPolicy(device) 4317 == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) { 4318 Log.i(TAG, "setActiveDevice: Setting active Headset " + device); 4319 mHeadsetService.setActiveDevice(device); 4320 } 4321 4322 return true; 4323 } 4324 4325 /** 4326 * Get the active devices for the BluetoothProfile specified 4327 * 4328 * @param profile is the profile from which we want the active devices. 4329 * Possible values are: 4330 * {@link BluetoothProfile#HEADSET}, 4331 * {@link BluetoothProfile#A2DP}, 4332 * {@link BluetoothProfile#HEARING_AID} 4333 * {@link BluetoothProfile#LE_AUDIO} 4334 * @return A list of active bluetooth devices 4335 */ 4336 @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) getActiveDevices(@ctiveDeviceProfile int profile)4337 public List<BluetoothDevice> getActiveDevices(@ActiveDeviceProfile int profile) { 4338 List<BluetoothDevice> activeDevices = new ArrayList<>(); 4339 4340 switch (profile) { 4341 case BluetoothProfile.HEADSET: 4342 if (mHeadsetService == null) { 4343 Log.e(TAG, "getActiveDevices: HeadsetService is null"); 4344 } else { 4345 BluetoothDevice device = mHeadsetService.getActiveDevice(); 4346 if (device != null) { 4347 activeDevices.add(device); 4348 } 4349 Log.i(TAG, "getActiveDevices: Headset device: " + device); 4350 } 4351 break; 4352 case BluetoothProfile.A2DP: 4353 if (mA2dpService == null) { 4354 Log.e(TAG, "getActiveDevices: A2dpService is null"); 4355 } else { 4356 BluetoothDevice device = mA2dpService.getActiveDevice(); 4357 if (device != null) { 4358 activeDevices.add(device); 4359 } 4360 Log.i(TAG, "getActiveDevices: A2dp device: " + device); 4361 } 4362 break; 4363 case BluetoothProfile.HEARING_AID: 4364 if (mHearingAidService == null) { 4365 Log.e(TAG, "getActiveDevices: HearingAidService is null"); 4366 } else { 4367 activeDevices = mHearingAidService.getActiveDevices(); 4368 Log.i(TAG, "getActiveDevices: Hearing Aid devices: Left[" 4369 + activeDevices.get(0) + "] - Right[" + activeDevices.get(1) + "]"); 4370 } 4371 break; 4372 case BluetoothProfile.LE_AUDIO: 4373 if (mLeAudioService == null) { 4374 Log.e(TAG, "getActiveDevices: LeAudioService is null"); 4375 } else { 4376 activeDevices = mLeAudioService.getActiveDevices(); 4377 Log.i(TAG, "getActiveDevices: LeAudio devices: Lead[" 4378 + activeDevices.get(0) + "] - member_1[" + activeDevices.get(1) + "]"); 4379 } 4380 break; 4381 default: 4382 Log.e(TAG, "getActiveDevices: profile value is not valid"); 4383 } 4384 return activeDevices; 4385 } 4386 4387 /** 4388 * Attempts connection to all enabled and supported bluetooth profiles between the local and 4389 * remote device 4390 * 4391 * @param device is the remote device with which to connect these profiles 4392 * @return {@link BluetoothStatusCodes#SUCCESS} if all profiles connections are attempted, false 4393 * if an error occurred 4394 */ 4395 @RequiresPermission(allOf = { 4396 android.Manifest.permission.BLUETOOTH_PRIVILEGED, 4397 android.Manifest.permission.MODIFY_PHONE_STATE, 4398 }) connectAllEnabledProfiles(BluetoothDevice device)4399 public int connectAllEnabledProfiles(BluetoothDevice device) { 4400 if (!profileServicesRunning()) { 4401 Log.e(TAG, "connectAllEnabledProfiles: Not all profile services running"); 4402 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; 4403 } 4404 4405 // Checks if any profiles are enabled and if so, only connect enabled profiles 4406 if (isAnyProfileEnabled(device)) { 4407 return connectEnabledProfiles(device); 4408 } 4409 4410 int numProfilesConnected = 0; 4411 ParcelUuid[] remoteDeviceUuids = getRemoteUuids(device); 4412 ParcelUuid[] localDeviceUuids = mAdapterProperties.getUuids(); 4413 4414 // All profile toggles disabled, so connects all supported profiles 4415 if (mA2dpService != null && isSupported(localDeviceUuids, remoteDeviceUuids, 4416 BluetoothProfile.A2DP, device)) { 4417 Log.i(TAG, "connectAllEnabledProfiles: Connecting A2dp"); 4418 // Set connection policy also connects the profile with CONNECTION_POLICY_ALLOWED 4419 mA2dpService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); 4420 numProfilesConnected++; 4421 } 4422 if (mA2dpSinkService != null && isSupported(localDeviceUuids, remoteDeviceUuids, 4423 BluetoothProfile.A2DP_SINK, device)) { 4424 Log.i(TAG, "connectAllEnabledProfiles: Connecting A2dp Sink"); 4425 mA2dpSinkService.setConnectionPolicy(device, 4426 BluetoothProfile.CONNECTION_POLICY_ALLOWED); 4427 numProfilesConnected++; 4428 } 4429 if (mHeadsetService != null && isSupported(localDeviceUuids, remoteDeviceUuids, 4430 BluetoothProfile.HEADSET, device)) { 4431 Log.i(TAG, "connectAllEnabledProfiles: Connecting Headset Profile"); 4432 mHeadsetService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); 4433 numProfilesConnected++; 4434 } 4435 if (mHeadsetClientService != null && isSupported(localDeviceUuids, remoteDeviceUuids, 4436 BluetoothProfile.HEADSET_CLIENT, device)) { 4437 Log.i(TAG, "connectAllEnabledProfiles: Connecting HFP"); 4438 mHeadsetClientService.setConnectionPolicy(device, 4439 BluetoothProfile.CONNECTION_POLICY_ALLOWED); 4440 numProfilesConnected++; 4441 } 4442 if (mMapClientService != null && isSupported(localDeviceUuids, remoteDeviceUuids, 4443 BluetoothProfile.MAP_CLIENT, device)) { 4444 Log.i(TAG, "connectAllEnabledProfiles: Connecting MAP"); 4445 mMapClientService.setConnectionPolicy(device, 4446 BluetoothProfile.CONNECTION_POLICY_ALLOWED); 4447 numProfilesConnected++; 4448 } 4449 if (mHidHostService != null && isSupported(localDeviceUuids, remoteDeviceUuids, 4450 BluetoothProfile.HID_HOST, device)) { 4451 Log.i(TAG, "connectAllEnabledProfiles: Connecting Hid Host Profile"); 4452 mHidHostService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); 4453 numProfilesConnected++; 4454 } 4455 if (mPanService != null && isSupported(localDeviceUuids, remoteDeviceUuids, 4456 BluetoothProfile.PAN, device)) { 4457 Log.i(TAG, "connectAllEnabledProfiles: Connecting Pan Profile"); 4458 mPanService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); 4459 numProfilesConnected++; 4460 } 4461 if (mPbapClientService != null && isSupported(localDeviceUuids, remoteDeviceUuids, 4462 BluetoothProfile.PBAP_CLIENT, device)) { 4463 Log.i(TAG, "connectAllEnabledProfiles: Connecting Pbap"); 4464 mPbapClientService.setConnectionPolicy(device, 4465 BluetoothProfile.CONNECTION_POLICY_ALLOWED); 4466 numProfilesConnected++; 4467 } 4468 if (mHearingAidService != null && isSupported(localDeviceUuids, remoteDeviceUuids, 4469 BluetoothProfile.HEARING_AID, device)) { 4470 Log.i(TAG, "connectAllEnabledProfiles: Connecting Hearing Aid Profile"); 4471 mHearingAidService.setConnectionPolicy(device, 4472 BluetoothProfile.CONNECTION_POLICY_ALLOWED); 4473 numProfilesConnected++; 4474 } 4475 if (mHapClientService != null && isSupported(localDeviceUuids, remoteDeviceUuids, 4476 BluetoothProfile.HAP_CLIENT, device)) { 4477 Log.i(TAG, "connectAllEnabledProfiles: Connecting Hearing Access Client Profile"); 4478 mHapClientService.setConnectionPolicy(device, 4479 BluetoothProfile.CONNECTION_POLICY_ALLOWED); 4480 numProfilesConnected++; 4481 } 4482 if (mVolumeControlService != null && isSupported(localDeviceUuids, remoteDeviceUuids, 4483 BluetoothProfile.VOLUME_CONTROL, device)) { 4484 Log.i(TAG, "connectAllEnabledProfiles: Connecting Volume Control Profile"); 4485 mVolumeControlService.setConnectionPolicy(device, 4486 BluetoothProfile.CONNECTION_POLICY_ALLOWED); 4487 numProfilesConnected++; 4488 } 4489 if (mCsipSetCoordinatorService != null 4490 && isSupported(localDeviceUuids, remoteDeviceUuids, 4491 BluetoothProfile.CSIP_SET_COORDINATOR, device)) { 4492 Log.i(TAG, "connectAllEnabledProfiles: Connecting Coordinated Set Profile"); 4493 mCsipSetCoordinatorService.setConnectionPolicy( 4494 device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); 4495 numProfilesConnected++; 4496 } 4497 if (mLeAudioService != null && isSupported(localDeviceUuids, remoteDeviceUuids, 4498 BluetoothProfile.LE_AUDIO, device)) { 4499 Log.i(TAG, "connectAllEnabledProfiles: Connecting LeAudio profile (BAP)"); 4500 mLeAudioService.setConnectionPolicy(device, 4501 BluetoothProfile.CONNECTION_POLICY_ALLOWED); 4502 numProfilesConnected++; 4503 } 4504 if (mBassClientService != null && isSupported(localDeviceUuids, remoteDeviceUuids, 4505 BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT, device)) { 4506 Log.i(TAG, "connectAllEnabledProfiles: Connecting LE Broadcast Assistant Profile"); 4507 mBassClientService.setConnectionPolicy(device, 4508 BluetoothProfile.CONNECTION_POLICY_ALLOWED); 4509 numProfilesConnected++; 4510 } 4511 4512 Log.i(TAG, "connectAllEnabledProfiles: Number of Profiles Connected: " 4513 + numProfilesConnected); 4514 4515 return BluetoothStatusCodes.SUCCESS; 4516 } 4517 4518 /** 4519 * Disconnects all enabled and supported bluetooth profiles between the local and remote device 4520 * 4521 * @param device is the remote device with which to disconnect these profiles 4522 * @return true if all profiles successfully disconnected, false if an error occurred 4523 */ 4524 @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) disconnectAllEnabledProfiles(BluetoothDevice device)4525 public int disconnectAllEnabledProfiles(BluetoothDevice device) { 4526 if (!profileServicesRunning()) { 4527 Log.e(TAG, "disconnectAllEnabledProfiles: Not all profile services bound"); 4528 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; 4529 } 4530 4531 if (mA2dpService != null && (mA2dpService.getConnectionState(device) 4532 == BluetoothProfile.STATE_CONNECTED 4533 || mA2dpService.getConnectionState(device) 4534 == BluetoothProfile.STATE_CONNECTING)) { 4535 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting A2dp"); 4536 mA2dpService.disconnect(device); 4537 } 4538 if (mA2dpSinkService != null && (mA2dpSinkService.getConnectionState(device) 4539 == BluetoothProfile.STATE_CONNECTED 4540 || mA2dpSinkService.getConnectionState(device) 4541 == BluetoothProfile.STATE_CONNECTING)) { 4542 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting A2dp Sink"); 4543 mA2dpSinkService.disconnect(device); 4544 } 4545 if (mHeadsetService != null && (mHeadsetService.getConnectionState(device) 4546 == BluetoothProfile.STATE_CONNECTED 4547 || mHeadsetService.getConnectionState(device) 4548 == BluetoothProfile.STATE_CONNECTING)) { 4549 Log.i(TAG, 4550 "disconnectAllEnabledProfiles: Disconnecting Headset Profile"); 4551 mHeadsetService.disconnect(device); 4552 } 4553 if (mHeadsetClientService != null && (mHeadsetClientService.getConnectionState(device) 4554 == BluetoothProfile.STATE_CONNECTED 4555 || mHeadsetClientService.getConnectionState(device) 4556 == BluetoothProfile.STATE_CONNECTING)) { 4557 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting HFP"); 4558 mHeadsetClientService.disconnect(device); 4559 } 4560 if (mMapClientService != null && (mMapClientService.getConnectionState(device) 4561 == BluetoothProfile.STATE_CONNECTED 4562 || mMapClientService.getConnectionState(device) 4563 == BluetoothProfile.STATE_CONNECTING)) { 4564 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting MAP Client"); 4565 mMapClientService.disconnect(device); 4566 } 4567 if (mMapService != null && (mMapService.getConnectionState(device) 4568 == BluetoothProfile.STATE_CONNECTED 4569 || mMapService.getConnectionState(device) 4570 == BluetoothProfile.STATE_CONNECTING)) { 4571 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting MAP"); 4572 mMapService.disconnect(device); 4573 } 4574 if (mHidDeviceService != null && (mHidDeviceService.getConnectionState(device) 4575 == BluetoothProfile.STATE_CONNECTED 4576 || mHidDeviceService.getConnectionState(device) 4577 == BluetoothProfile.STATE_CONNECTING)) { 4578 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Hid Device Profile"); 4579 mHidDeviceService.disconnect(device); 4580 } 4581 if (mHidHostService != null && (mHidHostService.getConnectionState(device) 4582 == BluetoothProfile.STATE_CONNECTED 4583 || mHidHostService.getConnectionState(device) 4584 == BluetoothProfile.STATE_CONNECTING)) { 4585 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Hid Host Profile"); 4586 mHidHostService.disconnect(device); 4587 } 4588 if (mPanService != null && (mPanService.getConnectionState(device) 4589 == BluetoothProfile.STATE_CONNECTED 4590 || mPanService.getConnectionState(device) 4591 == BluetoothProfile.STATE_CONNECTING)) { 4592 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Pan Profile"); 4593 mPanService.disconnect(device); 4594 } 4595 if (mPbapClientService != null && (mPbapClientService.getConnectionState(device) 4596 == BluetoothProfile.STATE_CONNECTED 4597 || mPbapClientService.getConnectionState(device) 4598 == BluetoothProfile.STATE_CONNECTING)) { 4599 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Pbap Client"); 4600 mPbapClientService.disconnect(device); 4601 } 4602 if (mPbapService != null && (mPbapService.getConnectionState(device) 4603 == BluetoothProfile.STATE_CONNECTED 4604 || mPbapService.getConnectionState(device) 4605 == BluetoothProfile.STATE_CONNECTING)) { 4606 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Pbap Server"); 4607 mPbapService.disconnect(device); 4608 } 4609 if (mHearingAidService != null && (mHearingAidService.getConnectionState(device) 4610 == BluetoothProfile.STATE_CONNECTED 4611 || mHearingAidService.getConnectionState(device) 4612 == BluetoothProfile.STATE_CONNECTING)) { 4613 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Hearing Aid Profile"); 4614 mHearingAidService.disconnect(device); 4615 } 4616 if (mHapClientService != null && (mHapClientService.getConnectionState(device) 4617 == BluetoothProfile.STATE_CONNECTED 4618 || mHapClientService.getConnectionState(device) 4619 == BluetoothProfile.STATE_CONNECTING)) { 4620 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Hearing Access Profile Client"); 4621 mHapClientService.disconnect(device); 4622 } 4623 if (mVolumeControlService != null && (mVolumeControlService.getConnectionState(device) 4624 == BluetoothProfile.STATE_CONNECTED 4625 || mVolumeControlService.getConnectionState(device) 4626 == BluetoothProfile.STATE_CONNECTING)) { 4627 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Volume Control Profile"); 4628 mVolumeControlService.disconnect(device); 4629 } 4630 if (mSapService != null && (mSapService.getConnectionState(device) 4631 == BluetoothProfile.STATE_CONNECTED 4632 || mSapService.getConnectionState(device) 4633 == BluetoothProfile.STATE_CONNECTING)) { 4634 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Sap Profile"); 4635 mSapService.disconnect(device); 4636 } 4637 if (mCsipSetCoordinatorService != null 4638 && (mCsipSetCoordinatorService.getConnectionState(device) 4639 == BluetoothProfile.STATE_CONNECTED 4640 || mCsipSetCoordinatorService.getConnectionState(device) 4641 == BluetoothProfile.STATE_CONNECTING)) { 4642 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Coordinater Set Profile"); 4643 mCsipSetCoordinatorService.disconnect(device); 4644 } 4645 if (mLeAudioService != null && (mLeAudioService.getConnectionState(device) 4646 == BluetoothProfile.STATE_CONNECTED 4647 || mLeAudioService.getConnectionState(device) 4648 == BluetoothProfile.STATE_CONNECTING)) { 4649 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting LeAudio profile (BAP)"); 4650 mLeAudioService.disconnect(device); 4651 } 4652 if (mBassClientService != null && (mBassClientService.getConnectionState(device) 4653 == BluetoothProfile.STATE_CONNECTED 4654 || mBassClientService.getConnectionState(device) 4655 == BluetoothProfile.STATE_CONNECTING)) { 4656 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting " 4657 + "LE Broadcast Assistant Profile"); 4658 mBassClientService.disconnect(device); 4659 } 4660 4661 return BluetoothStatusCodes.SUCCESS; 4662 } 4663 4664 /** 4665 * Same as API method {@link BluetoothDevice#getName()} 4666 * 4667 * @param device remote device of interest 4668 * @return remote device name 4669 */ getRemoteName(BluetoothDevice device)4670 public String getRemoteName(BluetoothDevice device) { 4671 if (mRemoteDevices == null) { 4672 return null; 4673 } 4674 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 4675 if (deviceProp == null) { 4676 return null; 4677 } 4678 return deviceProp.getName(); 4679 } 4680 4681 /** 4682 * Get UUIDs for service supported by a remote device 4683 * 4684 * @param device the remote device that we want to get UUIDs from 4685 * @return 4686 */ 4687 @VisibleForTesting getRemoteUuids(BluetoothDevice device)4688 public ParcelUuid[] getRemoteUuids(BluetoothDevice device) { 4689 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 4690 if (deviceProp == null) { 4691 return null; 4692 } 4693 return deviceProp.getUuids(); 4694 } 4695 getBluetoothConnectionCallbacks()4696 public Set<IBluetoothConnectionCallback> getBluetoothConnectionCallbacks() { 4697 return mBluetoothConnectionCallbacks; 4698 } 4699 4700 /** 4701 * Converts HCI disconnect reasons to Android disconnect reasons. 4702 * <p> 4703 * The HCI Error Codes used for ACL disconnect reasons propagated up from native code were 4704 * copied from: {@link system/bt/stack/include/hci_error_code.h}. 4705 * <p> 4706 * These error codes are specified and described in Bluetooth Core Spec v5.1, Vol 2, Part D. 4707 * 4708 * @param hciReason is the raw HCI disconnect reason from native. 4709 * @return the Android disconnect reason for apps. 4710 */ 4711 static @BluetoothAdapter.BluetoothConnectionCallback.DisconnectReason int hciToAndroidDisconnectReason(int hciReason)4712 hciToAndroidDisconnectReason(int hciReason) { 4713 switch(hciReason) { 4714 case /*HCI_SUCCESS*/ 0x00: 4715 case /*HCI_ERR_UNSPECIFIED*/ 0x1F: 4716 case /*HCI_ERR_UNDEFINED*/ 0xff: 4717 return BluetoothStatusCodes.ERROR_UNKNOWN; 4718 case /*HCI_ERR_ILLEGAL_COMMAND*/ 0x01: 4719 case /*HCI_ERR_NO_CONNECTION*/ 0x02: 4720 case /*HCI_ERR_HW_FAILURE*/ 0x03: 4721 case /*HCI_ERR_DIFF_TRANSACTION_COLLISION*/ 0x2A: 4722 case /*HCI_ERR_ROLE_SWITCH_PENDING*/ 0x32: 4723 case /*HCI_ERR_ROLE_SWITCH_FAILED*/ 0x35: 4724 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_LOCAL; 4725 case /*HCI_ERR_PAGE_TIMEOUT*/ 0x04: 4726 case /*HCI_ERR_CONNECTION_TOUT*/ 0x08: 4727 case /*HCI_ERR_HOST_TIMEOUT*/ 0x10: 4728 case /*HCI_ERR_LMP_RESPONSE_TIMEOUT*/ 0x22: 4729 case /*HCI_ERR_ADVERTISING_TIMEOUT*/ 0x3C: 4730 case /*HCI_ERR_CONN_FAILED_ESTABLISHMENT*/ 0x3E: 4731 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_TIMEOUT; 4732 case /*HCI_ERR_AUTH_FAILURE*/ 0x05: 4733 case /*HCI_ERR_KEY_MISSING*/ 0x06: 4734 case /*HCI_ERR_HOST_REJECT_SECURITY*/ 0x0E: 4735 case /*HCI_ERR_REPEATED_ATTEMPTS*/ 0x17: 4736 case /*HCI_ERR_PAIRING_NOT_ALLOWED*/ 0x18: 4737 case /*HCI_ERR_ENCRY_MODE_NOT_ACCEPTABLE*/ 0x25: 4738 case /*HCI_ERR_UNIT_KEY_USED*/ 0x26: 4739 case /*HCI_ERR_PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED*/ 0x29: 4740 case /*HCI_ERR_INSUFFCIENT_SECURITY*/ 0x2F: 4741 case /*HCI_ERR_HOST_BUSY_PAIRING*/ 0x38: 4742 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_SECURITY; 4743 case /*HCI_ERR_MEMORY_FULL*/ 0x07: 4744 case /*HCI_ERR_MAX_NUM_OF_CONNECTIONS*/ 0x09: 4745 case /*HCI_ERR_MAX_NUM_OF_SCOS*/ 0x0A: 4746 case /*HCI_ERR_COMMAND_DISALLOWED*/ 0x0C: 4747 case /*HCI_ERR_HOST_REJECT_RESOURCES*/ 0x0D: 4748 case /*HCI_ERR_LIMIT_REACHED*/ 0x43: 4749 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_RESOURCE_LIMIT_REACHED; 4750 case /*HCI_ERR_CONNECTION_EXISTS*/ 0x0B: 4751 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_CONNECTION_ALREADY_EXISTS; 4752 case /*HCI_ERR_HOST_REJECT_DEVICE*/ 0x0F: 4753 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_SYSTEM_POLICY; 4754 case /*HCI_ERR_ILLEGAL_PARAMETER_FMT*/ 0x12: 4755 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_BAD_PARAMETERS; 4756 case /*HCI_ERR_PEER_USER*/ 0x13: 4757 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_REMOTE_REQUEST; 4758 case /*HCI_ERR_REMOTE_POWER_OFF*/ 0x15: 4759 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_REMOTE_REQUEST; 4760 case /*HCI_ERR_CONN_CAUSE_LOCAL_HOST*/ 0x16: 4761 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_LOCAL_REQUEST; 4762 case /*HCI_ERR_UNSUPPORTED_REM_FEATURE*/ 0x1A: 4763 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_REMOTE; 4764 case /*HCI_ERR_UNACCEPT_CONN_INTERVAL*/ 0x3B: 4765 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_BAD_PARAMETERS; 4766 default: 4767 Log.e(TAG, "Invalid HCI disconnect reason: " + hciReason); 4768 return BluetoothStatusCodes.ERROR_UNKNOWN; 4769 } 4770 } 4771 logUserBondResponse(BluetoothDevice device, boolean accepted, int event)4772 void logUserBondResponse(BluetoothDevice device, boolean accepted, int event) { 4773 final long token = Binder.clearCallingIdentity(); 4774 try { 4775 BluetoothStatsLog.write(BluetoothStatsLog.BLUETOOTH_BOND_STATE_CHANGED, 4776 obfuscateAddress(device), 0, device.getType(), 4777 BluetoothDevice.BOND_BONDING, 4778 event, 4779 accepted ? 0 : BluetoothDevice.UNBOND_REASON_AUTH_REJECTED); 4780 } finally { 4781 Binder.restoreCallingIdentity(token); 4782 } 4783 } 4784 getDeviceAccessFromPrefs(BluetoothDevice device, String prefFile)4785 int getDeviceAccessFromPrefs(BluetoothDevice device, String prefFile) { 4786 SharedPreferences prefs = getSharedPreferences(prefFile, Context.MODE_PRIVATE); 4787 if (!prefs.contains(device.getAddress())) { 4788 return BluetoothDevice.ACCESS_UNKNOWN; 4789 } 4790 return prefs.getBoolean(device.getAddress(), false) 4791 ? BluetoothDevice.ACCESS_ALLOWED 4792 : BluetoothDevice.ACCESS_REJECTED; 4793 } 4794 setDeviceAccessFromPrefs(BluetoothDevice device, int value, String prefFile)4795 void setDeviceAccessFromPrefs(BluetoothDevice device, int value, String prefFile) { 4796 SharedPreferences pref = getSharedPreferences(prefFile, Context.MODE_PRIVATE); 4797 SharedPreferences.Editor editor = pref.edit(); 4798 if (value == BluetoothDevice.ACCESS_UNKNOWN) { 4799 editor.remove(device.getAddress()); 4800 } else { 4801 editor.putBoolean(device.getAddress(), value == BluetoothDevice.ACCESS_ALLOWED); 4802 } 4803 editor.apply(); 4804 } 4805 setPhonebookAccessPermission(BluetoothDevice device, int value)4806 public void setPhonebookAccessPermission(BluetoothDevice device, int value) { 4807 setDeviceAccessFromPrefs(device, value, PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE); 4808 } 4809 setMessageAccessPermission(BluetoothDevice device, int value)4810 public void setMessageAccessPermission(BluetoothDevice device, int value) { 4811 setDeviceAccessFromPrefs(device, value, MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE); 4812 } 4813 setSimAccessPermission(BluetoothDevice device, int value)4814 public void setSimAccessPermission(BluetoothDevice device, int value) { 4815 setDeviceAccessFromPrefs(device, value, SIM_ACCESS_PERMISSION_PREFERENCE_FILE); 4816 } 4817 isRpaOffloadSupported()4818 public boolean isRpaOffloadSupported() { 4819 return mAdapterProperties.isRpaOffloadSupported(); 4820 } 4821 getNumOfOffloadedIrkSupported()4822 public int getNumOfOffloadedIrkSupported() { 4823 return mAdapterProperties.getNumOfOffloadedIrkSupported(); 4824 } 4825 getNumOfOffloadedScanFilterSupported()4826 public int getNumOfOffloadedScanFilterSupported() { 4827 return mAdapterProperties.getNumOfOffloadedScanFilterSupported(); 4828 } 4829 getOffloadedScanResultStorage()4830 public int getOffloadedScanResultStorage() { 4831 return mAdapterProperties.getOffloadedScanResultStorage(); 4832 } 4833 isLe2MPhySupported()4834 public boolean isLe2MPhySupported() { 4835 return mAdapterProperties.isLe2MPhySupported(); 4836 } 4837 isLeCodedPhySupported()4838 public boolean isLeCodedPhySupported() { 4839 return mAdapterProperties.isLeCodedPhySupported(); 4840 } 4841 isLeExtendedAdvertisingSupported()4842 public boolean isLeExtendedAdvertisingSupported() { 4843 return mAdapterProperties.isLeExtendedAdvertisingSupported(); 4844 } 4845 isLePeriodicAdvertisingSupported()4846 public boolean isLePeriodicAdvertisingSupported() { 4847 return mAdapterProperties.isLePeriodicAdvertisingSupported(); 4848 } 4849 4850 /** 4851 * Check if the LE audio broadcast source feature is supported. 4852 * 4853 * @return true, if the LE audio broadcast source is supported 4854 */ isLeAudioBroadcastSourceSupported()4855 public boolean isLeAudioBroadcastSourceSupported() { 4856 return mAdapterProperties.isLePeriodicAdvertisingSupported() 4857 && mAdapterProperties.isLeExtendedAdvertisingSupported() 4858 && mAdapterProperties.isLeIsochronousBroadcasterSupported(); 4859 } 4860 4861 /** 4862 * Check if the LE audio broadcast assistant feature is supported. 4863 * 4864 * @return true, if the LE audio broadcast assistant is supported 4865 */ isLeAudioBroadcastAssistantSupported()4866 public boolean isLeAudioBroadcastAssistantSupported() { 4867 return mAdapterProperties.isLePeriodicAdvertisingSupported() 4868 && mAdapterProperties.isLeExtendedAdvertisingSupported() 4869 && (mAdapterProperties.isLePeriodicAdvertisingSyncTransferSenderSupported() 4870 || mAdapterProperties.isLePeriodicAdvertisingSyncTransferRecipientSupported()); 4871 } 4872 getSupportedProfilesBitMask()4873 public long getSupportedProfilesBitMask() { 4874 return Config.getSupportedProfilesBitMask(); 4875 } 4876 4877 /** 4878 * Check if the LE audio CIS central feature is supported. 4879 * 4880 * @return true, if the LE audio CIS central is supported 4881 */ isLeConnectedIsochronousStreamCentralSupported()4882 public boolean isLeConnectedIsochronousStreamCentralSupported() { 4883 return mAdapterProperties.isLeConnectedIsochronousStreamCentralSupported(); 4884 } 4885 getLeMaximumAdvertisingDataLength()4886 public int getLeMaximumAdvertisingDataLength() { 4887 return mAdapterProperties.getLeMaximumAdvertisingDataLength(); 4888 } 4889 4890 /** 4891 * Get the maximum number of connected audio devices. 4892 * 4893 * @return the maximum number of connected audio devices 4894 */ getMaxConnectedAudioDevices()4895 public int getMaxConnectedAudioDevices() { 4896 return mAdapterProperties.getMaxConnectedAudioDevices(); 4897 } 4898 4899 /** 4900 * Check whether A2DP offload is enabled. 4901 * 4902 * @return true if A2DP offload is enabled 4903 */ isA2dpOffloadEnabled()4904 public boolean isA2dpOffloadEnabled() { 4905 return mAdapterProperties.isA2dpOffloadEnabled(); 4906 } 4907 4908 @VisibleForTesting reportActivityInfo()4909 BluetoothActivityEnergyInfo reportActivityInfo() { 4910 if (mAdapterProperties.getState() != BluetoothAdapter.STATE_ON 4911 || !mAdapterProperties.isActivityAndEnergyReportingSupported()) { 4912 return null; 4913 } 4914 4915 // Pull the data. The callback will notify mEnergyInfoLock. 4916 readEnergyInfo(); 4917 4918 synchronized (mEnergyInfoLock) { 4919 try { 4920 mEnergyInfoLock.wait(CONTROLLER_ENERGY_UPDATE_TIMEOUT_MILLIS); 4921 } catch (InterruptedException e) { 4922 // Just continue, the energy data may be stale but we won't miss anything next time 4923 // we query. 4924 } 4925 4926 final BluetoothActivityEnergyInfo info = 4927 new BluetoothActivityEnergyInfo(SystemClock.elapsedRealtime(), 4928 mStackReportedState, mTxTimeTotalMs, mRxTimeTotalMs, mIdleTimeTotalMs, 4929 mEnergyUsedTotalVoltAmpSecMicro); 4930 4931 // Count the number of entries that have byte counts > 0 4932 int arrayLen = 0; 4933 for (int i = 0; i < mUidTraffic.size(); i++) { 4934 final UidTraffic traffic = mUidTraffic.valueAt(i); 4935 if (traffic.getTxBytes() != 0 || traffic.getRxBytes() != 0) { 4936 arrayLen++; 4937 } 4938 } 4939 4940 // Copy the traffic objects whose byte counts are > 0 4941 final List<UidTraffic> result = new ArrayList<>(); 4942 int putIdx = 0; 4943 for (int i = 0; i < mUidTraffic.size(); i++) { 4944 final UidTraffic traffic = mUidTraffic.valueAt(i); 4945 if (traffic.getTxBytes() != 0 || traffic.getRxBytes() != 0) { 4946 result.add(traffic.clone()); 4947 } 4948 } 4949 4950 info.setUidTraffic(result); 4951 4952 return info; 4953 } 4954 } 4955 getTotalNumOfTrackableAdvertisements()4956 public int getTotalNumOfTrackableAdvertisements() { 4957 return mAdapterProperties.getTotalNumOfTrackableAdvertisements(); 4958 } 4959 4960 /** 4961 * Notify the UID and package name of the app, and the address of associated active device 4962 * 4963 * @param source The attribution source that starts the activity 4964 * @param deviceAddress The address of the active device associated with the app 4965 */ notifyActivityAttributionInfo(AttributionSource source, String deviceAddress)4966 public void notifyActivityAttributionInfo(AttributionSource source, String deviceAddress) { 4967 mActivityAttributionService.notifyActivityAttributionInfo( 4968 source.getUid(), source.getPackageName(), deviceAddress); 4969 } 4970 convertScanModeToHal(int mode)4971 static int convertScanModeToHal(int mode) { 4972 switch (mode) { 4973 case BluetoothAdapter.SCAN_MODE_NONE: 4974 return AbstractionLayer.BT_SCAN_MODE_NONE; 4975 case BluetoothAdapter.SCAN_MODE_CONNECTABLE: 4976 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE; 4977 case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE: 4978 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE; 4979 } 4980 // errorLog("Incorrect scan mode in convertScanModeToHal"); 4981 return -1; 4982 } 4983 convertScanModeFromHal(int mode)4984 static int convertScanModeFromHal(int mode) { 4985 switch (mode) { 4986 case AbstractionLayer.BT_SCAN_MODE_NONE: 4987 return BluetoothAdapter.SCAN_MODE_NONE; 4988 case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE: 4989 return BluetoothAdapter.SCAN_MODE_CONNECTABLE; 4990 case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE: 4991 return BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE; 4992 } 4993 //errorLog("Incorrect scan mode in convertScanModeFromHal"); 4994 return -1; 4995 } 4996 4997 // This function is called from JNI. It allows native code to set a single wake 4998 // alarm. If an alarm is already pending and a new request comes in, the alarm 4999 // will be rescheduled (i.e. the previously set alarm will be cancelled). setWakeAlarm(long delayMillis, boolean shouldWake)5000 private boolean setWakeAlarm(long delayMillis, boolean shouldWake) { 5001 synchronized (this) { 5002 if (mPendingAlarm != null) { 5003 mAlarmManager.cancel(mPendingAlarm); 5004 } 5005 5006 long wakeupTime = SystemClock.elapsedRealtime() + delayMillis; 5007 int type = shouldWake ? AlarmManager.ELAPSED_REALTIME_WAKEUP 5008 : AlarmManager.ELAPSED_REALTIME; 5009 5010 Intent intent = new Intent(ACTION_ALARM_WAKEUP); 5011 mPendingAlarm = 5012 PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_ONE_SHOT 5013 | PendingIntent.FLAG_IMMUTABLE); 5014 mAlarmManager.setExact(type, wakeupTime, mPendingAlarm); 5015 return true; 5016 } 5017 } 5018 5019 // This function is called from JNI. It allows native code to acquire a single wake lock. 5020 // If the wake lock is already held, this function returns success. Although this function 5021 // only supports acquiring a single wake lock at a time right now, it will eventually be 5022 // extended to allow acquiring an arbitrary number of wake locks. The current interface 5023 // takes |lockName| as a parameter in anticipation of that implementation. acquireWakeLock(String lockName)5024 private boolean acquireWakeLock(String lockName) { 5025 synchronized (this) { 5026 if (mWakeLock == null) { 5027 mWakeLockName = lockName; 5028 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, lockName); 5029 } 5030 5031 if (!mWakeLock.isHeld()) { 5032 mWakeLock.acquire(); 5033 } 5034 } 5035 return true; 5036 } 5037 5038 // This function is called from JNI. It allows native code to release a wake lock acquired 5039 // by |acquireWakeLock|. If the wake lock is not held, this function returns failure. 5040 // Note that the release() call is also invoked by {@link #cleanup()} so a synchronization is 5041 // needed here. See the comment for |acquireWakeLock| for an explanation of the interface. releaseWakeLock(String lockName)5042 private boolean releaseWakeLock(String lockName) { 5043 synchronized (this) { 5044 if (mWakeLock == null) { 5045 errorLog("Repeated wake lock release; aborting release: " + lockName); 5046 return false; 5047 } 5048 5049 if (mWakeLock.isHeld()) { 5050 mWakeLock.release(); 5051 } 5052 } 5053 return true; 5054 } 5055 energyInfoCallback(int status, int ctrlState, long txTime, long rxTime, long idleTime, long energyUsed, UidTraffic[] data)5056 private void energyInfoCallback(int status, int ctrlState, long txTime, long rxTime, 5057 long idleTime, long energyUsed, UidTraffic[] data) throws RemoteException { 5058 if (ctrlState >= BluetoothActivityEnergyInfo.BT_STACK_STATE_INVALID 5059 && ctrlState <= BluetoothActivityEnergyInfo.BT_STACK_STATE_STATE_IDLE) { 5060 // Energy is product of mA, V and ms. If the chipset doesn't 5061 // report it, we have to compute it from time 5062 if (energyUsed == 0) { 5063 try { 5064 final long txMah = Math.multiplyExact(txTime, getTxCurrentMa()); 5065 final long rxMah = Math.multiplyExact(rxTime, getRxCurrentMa()); 5066 final long idleMah = Math.multiplyExact(idleTime, getIdleCurrentMa()); 5067 energyUsed = (long) (Math.addExact(Math.addExact(txMah, rxMah), idleMah) 5068 * getOperatingVolt()); 5069 } catch (ArithmeticException e) { 5070 Log.wtf(TAG, "overflow in bluetooth energy callback", e); 5071 // Energy is already 0 if the exception was thrown. 5072 } 5073 } 5074 5075 synchronized (mEnergyInfoLock) { 5076 mStackReportedState = ctrlState; 5077 long totalTxTimeMs; 5078 long totalRxTimeMs; 5079 long totalIdleTimeMs; 5080 long totalEnergy; 5081 try { 5082 totalTxTimeMs = Math.addExact(mTxTimeTotalMs, txTime); 5083 totalRxTimeMs = Math.addExact(mRxTimeTotalMs, rxTime); 5084 totalIdleTimeMs = Math.addExact(mIdleTimeTotalMs, idleTime); 5085 totalEnergy = Math.addExact(mEnergyUsedTotalVoltAmpSecMicro, energyUsed); 5086 } catch (ArithmeticException e) { 5087 // This could be because we accumulated a lot of time, or we got a very strange 5088 // value from the controller (more likely). Discard this data. 5089 Log.wtf(TAG, "overflow in bluetooth energy callback", e); 5090 totalTxTimeMs = mTxTimeTotalMs; 5091 totalRxTimeMs = mRxTimeTotalMs; 5092 totalIdleTimeMs = mIdleTimeTotalMs; 5093 totalEnergy = mEnergyUsedTotalVoltAmpSecMicro; 5094 } 5095 5096 mTxTimeTotalMs = totalTxTimeMs; 5097 mRxTimeTotalMs = totalRxTimeMs; 5098 mIdleTimeTotalMs = totalIdleTimeMs; 5099 mEnergyUsedTotalVoltAmpSecMicro = totalEnergy; 5100 5101 for (UidTraffic traffic : data) { 5102 UidTraffic existingTraffic = mUidTraffic.get(traffic.getUid()); 5103 if (existingTraffic == null) { 5104 mUidTraffic.put(traffic.getUid(), traffic); 5105 } else { 5106 existingTraffic.addRxBytes(traffic.getRxBytes()); 5107 existingTraffic.addTxBytes(traffic.getTxBytes()); 5108 } 5109 } 5110 mEnergyInfoLock.notifyAll(); 5111 } 5112 } 5113 5114 verboseLog("energyInfoCallback() status = " + status + "txTime = " + txTime + "rxTime = " 5115 + rxTime + "idleTime = " + idleTime + "energyUsed = " + energyUsed + "ctrlState = " 5116 + ctrlState + "traffic = " + Arrays.toString(data)); 5117 } 5118 5119 /** 5120 * Update metadata change to registered listeners 5121 */ 5122 @VisibleForTesting metadataChanged(String address, int key, byte[] value)5123 public void metadataChanged(String address, int key, byte[] value) { 5124 BluetoothDevice device = mRemoteDevices.getDevice(Utils.getBytesFromAddress(address)); 5125 5126 // pass just interesting metadata to native, to reduce spam 5127 if (key == BluetoothDevice.METADATA_LE_AUDIO) { 5128 metadataChangedNative(Utils.getBytesFromAddress(address), key, value); 5129 } 5130 5131 if (mMetadataListeners.containsKey(device)) { 5132 ArrayList<IBluetoothMetadataListener> list = mMetadataListeners.get(device); 5133 for (IBluetoothMetadataListener listener : list) { 5134 try { 5135 listener.onMetadataChanged(device, key, value); 5136 } catch (RemoteException e) { 5137 Log.w(TAG, "RemoteException when onMetadataChanged"); 5138 } 5139 } 5140 } 5141 } 5142 getIdleCurrentMa()5143 private int getIdleCurrentMa() { 5144 return BluetoothProperties.getHardwareIdleCurrentMa().orElse(0); 5145 } 5146 getTxCurrentMa()5147 private int getTxCurrentMa() { 5148 return BluetoothProperties.getHardwareTxCurrentMa().orElse(0); 5149 } 5150 getRxCurrentMa()5151 private int getRxCurrentMa() { 5152 return BluetoothProperties.getHardwareRxCurrentMa().orElse(0); 5153 } 5154 getOperatingVolt()5155 private double getOperatingVolt() { 5156 return BluetoothProperties.getHardwareOperatingVoltageMv().orElse(0) / 1000.0; 5157 } 5158 5159 @VisibleForTesting getRemoteDevices()5160 protected RemoteDevices getRemoteDevices() { 5161 return mRemoteDevices; 5162 } 5163 5164 @Override dump(FileDescriptor fd, PrintWriter writer, String[] args)5165 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 5166 if (args.length == 0) { 5167 writer.println("Skipping dump in APP SERVICES, see bluetooth_manager section."); 5168 writer.println("Use --print argument for dumpsys direct from AdapterService."); 5169 return; 5170 } 5171 5172 if ("set-test-mode".equals(args[0])) { 5173 final boolean testModeEnabled = "enabled".equalsIgnoreCase(args[1]); 5174 for (ProfileService profile : mRunningProfiles) { 5175 profile.setTestModeEnabled(testModeEnabled); 5176 } 5177 mTestModeEnabled = testModeEnabled; 5178 return; 5179 } 5180 5181 verboseLog("dumpsys arguments, check for protobuf output: " + TextUtils.join(" ", args)); 5182 if (args[0].equals("--proto-bin")) { 5183 dumpMetrics(fd); 5184 return; 5185 } 5186 5187 writer.println(); 5188 mAdapterProperties.dump(fd, writer, args); 5189 writer.println("mSnoopLogSettingAtEnable = " + mSnoopLogSettingAtEnable); 5190 writer.println("mDefaultSnoopLogSettingAtEnable = " + mDefaultSnoopLogSettingAtEnable); 5191 5192 writer.println(); 5193 writer.println("Enabled Profile Services:"); 5194 for (Class profile : Config.getSupportedProfiles()) { 5195 writer.println(" " + profile.getSimpleName()); 5196 } 5197 writer.println(); 5198 5199 mAdapterStateMachine.dump(fd, writer, args); 5200 5201 StringBuilder sb = new StringBuilder(); 5202 for (ProfileService profile : mRegisteredProfiles) { 5203 profile.dump(sb); 5204 } 5205 mSilenceDeviceManager.dump(fd, writer, args); 5206 mDatabaseManager.dump(writer); 5207 5208 writer.write(sb.toString()); 5209 writer.flush(); 5210 5211 dumpNative(fd, args); 5212 } 5213 dumpMetrics(FileDescriptor fd)5214 private void dumpMetrics(FileDescriptor fd) { 5215 BluetoothMetricsProto.BluetoothLog.Builder metricsBuilder = 5216 BluetoothMetricsProto.BluetoothLog.newBuilder(); 5217 byte[] nativeMetricsBytes = dumpMetricsNative(); 5218 debugLog("dumpMetrics: native metrics size is " + nativeMetricsBytes.length); 5219 if (nativeMetricsBytes.length > 0) { 5220 try { 5221 metricsBuilder.mergeFrom(nativeMetricsBytes); 5222 } catch (InvalidProtocolBufferException ex) { 5223 Log.w(TAG, "dumpMetrics: problem parsing metrics protobuf, " + ex.getMessage()); 5224 return; 5225 } 5226 } 5227 metricsBuilder.setNumBondedDevices(getBondedDevices().length); 5228 MetricsLogger.dumpProto(metricsBuilder); 5229 for (ProfileService profile : mRegisteredProfiles) { 5230 profile.dumpProto(metricsBuilder); 5231 } 5232 byte[] metricsBytes = Base64.encode(metricsBuilder.build().toByteArray(), Base64.DEFAULT); 5233 debugLog("dumpMetrics: combined metrics size is " + metricsBytes.length); 5234 try (FileOutputStream protoOut = new FileOutputStream(fd)) { 5235 protoOut.write(metricsBytes); 5236 } catch (IOException e) { 5237 errorLog("dumpMetrics: error writing combined protobuf to fd, " + e.getMessage()); 5238 } 5239 } 5240 debugLog(String msg)5241 private void debugLog(String msg) { 5242 if (DBG) { 5243 Log.d(TAG, msg); 5244 } 5245 } 5246 verboseLog(String msg)5247 private void verboseLog(String msg) { 5248 if (VERBOSE) { 5249 Log.v(TAG, msg); 5250 } 5251 } 5252 errorLog(String msg)5253 private void errorLog(String msg) { 5254 Log.e(TAG, msg); 5255 } 5256 5257 private final BroadcastReceiver mAlarmBroadcastReceiver = new BroadcastReceiver() { 5258 @Override 5259 public void onReceive(Context context, Intent intent) { 5260 synchronized (AdapterService.this) { 5261 mPendingAlarm = null; 5262 alarmFiredNative(); 5263 } 5264 } 5265 }; 5266 isCommonCriteriaMode()5267 private boolean isCommonCriteriaMode() { 5268 return getSystemService(DevicePolicyManager.class).isCommonCriteriaModeEnabled(null); 5269 } 5270 5271 @SuppressLint("AndroidFrameworkRequiresPermission") enforceBluetoothPrivilegedPermissionIfNeeded(OobData remoteP192Data, OobData remoteP256Data)5272 private void enforceBluetoothPrivilegedPermissionIfNeeded(OobData remoteP192Data, 5273 OobData remoteP256Data) { 5274 if (remoteP192Data != null || remoteP256Data != null) { 5275 enforceBluetoothPrivilegedPermission(this); 5276 } 5277 } 5278 5279 @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) getInitFlags()5280 private String[] getInitFlags() { 5281 final DeviceConfig.Properties properties = 5282 DeviceConfig.getProperties(DeviceConfig.NAMESPACE_BLUETOOTH); 5283 ArrayList<String> initFlags = new ArrayList<>(); 5284 for (String property: properties.getKeyset()) { 5285 if (property.startsWith("INIT_")) { 5286 initFlags.add(String.format("%s=%s", property, 5287 properties.getString(property, null))); 5288 } 5289 } 5290 return initFlags.toArray(new String[0]); 5291 } 5292 5293 private final Object mDeviceConfigLock = new Object(); 5294 5295 /** 5296 * Predicate that can be applied to names to determine if a device is 5297 * well-known to be used for physical location. 5298 */ 5299 @GuardedBy("mDeviceConfigLock") 5300 private Predicate<String> mLocationDenylistName = (v) -> false; 5301 5302 /** 5303 * Predicate that can be applied to MAC addresses to determine if a device 5304 * is well-known to be used for physical location. 5305 */ 5306 @GuardedBy("mDeviceConfigLock") 5307 private Predicate<byte[]> mLocationDenylistMac = (v) -> false; 5308 5309 /** 5310 * Predicate that can be applied to Advertising Data payloads to determine 5311 * if a device is well-known to be used for physical location. 5312 */ 5313 @GuardedBy("mDeviceConfigLock") 5314 private Predicate<byte[]> mLocationDenylistAdvertisingData = (v) -> false; 5315 5316 @GuardedBy("mDeviceConfigLock") 5317 private int mScanQuotaCount = DeviceConfigListener.DEFAULT_SCAN_QUOTA_COUNT; 5318 @GuardedBy("mDeviceConfigLock") 5319 private long mScanQuotaWindowMillis = DeviceConfigListener.DEFAULT_SCAN_QUOTA_WINDOW_MILLIS; 5320 @GuardedBy("mDeviceConfigLock") 5321 private long mScanTimeoutMillis = DeviceConfigListener.DEFAULT_SCAN_TIMEOUT_MILLIS; 5322 @GuardedBy("mDeviceConfigLock") 5323 private int mScanUpgradeDurationMillis = 5324 DeviceConfigListener.DEFAULT_SCAN_UPGRADE_DURATION_MILLIS; 5325 @GuardedBy("mDeviceConfigLock") 5326 private int mScreenOffLowPowerWindowMillis = 5327 ScanManager.SCAN_MODE_SCREEN_OFF_LOW_POWER_WINDOW_MS; 5328 @GuardedBy("mDeviceConfigLock") 5329 private int mScreenOffLowPowerIntervalMillis = 5330 ScanManager.SCAN_MODE_SCREEN_OFF_LOW_POWER_INTERVAL_MS; 5331 @GuardedBy("mDeviceConfigLock") 5332 private int mScreenOffBalancedWindowMillis = 5333 ScanManager.SCAN_MODE_SCREEN_OFF_BALANCED_WINDOW_MS; 5334 @GuardedBy("mDeviceConfigLock") 5335 private int mScreenOffBalancedIntervalMillis = 5336 ScanManager.SCAN_MODE_SCREEN_OFF_BALANCED_INTERVAL_MS; 5337 getLocationDenylistName()5338 public @NonNull Predicate<String> getLocationDenylistName() { 5339 synchronized (mDeviceConfigLock) { 5340 return mLocationDenylistName; 5341 } 5342 } 5343 getLocationDenylistMac()5344 public @NonNull Predicate<byte[]> getLocationDenylistMac() { 5345 synchronized (mDeviceConfigLock) { 5346 return mLocationDenylistMac; 5347 } 5348 } 5349 getLocationDenylistAdvertisingData()5350 public @NonNull Predicate<byte[]> getLocationDenylistAdvertisingData() { 5351 synchronized (mDeviceConfigLock) { 5352 return mLocationDenylistAdvertisingData; 5353 } 5354 } 5355 5356 /** 5357 * Returns scan quota count. 5358 */ getScanQuotaCount()5359 public int getScanQuotaCount() { 5360 synchronized (mDeviceConfigLock) { 5361 return mScanQuotaCount; 5362 } 5363 } 5364 5365 /** 5366 * Returns scan quota window in millis. 5367 */ getScanQuotaWindowMillis()5368 public long getScanQuotaWindowMillis() { 5369 synchronized (mDeviceConfigLock) { 5370 return mScanQuotaWindowMillis; 5371 } 5372 } 5373 5374 /** 5375 * Returns scan timeout in millis. 5376 */ getScanTimeoutMillis()5377 public long getScanTimeoutMillis() { 5378 synchronized (mDeviceConfigLock) { 5379 return mScanTimeoutMillis; 5380 } 5381 } 5382 5383 /** 5384 * Returns scan upgrade duration in millis. 5385 */ getScanUpgradeDurationMillis()5386 public long getScanUpgradeDurationMillis() { 5387 synchronized (mDeviceConfigLock) { 5388 return mScanUpgradeDurationMillis; 5389 } 5390 } 5391 5392 /** 5393 * Returns SCREEN_OFF_BALANCED scan window in millis. 5394 */ getScreenOffBalancedWindowMillis()5395 public int getScreenOffBalancedWindowMillis() { 5396 synchronized (mDeviceConfigLock) { 5397 return mScreenOffBalancedWindowMillis; 5398 } 5399 } 5400 5401 /** 5402 * Returns SCREEN_OFF_BALANCED scan interval in millis. 5403 */ getScreenOffBalancedIntervalMillis()5404 public int getScreenOffBalancedIntervalMillis() { 5405 synchronized (mDeviceConfigLock) { 5406 return mScreenOffBalancedIntervalMillis; 5407 } 5408 } 5409 5410 /** 5411 * Returns SCREEN_OFF low power scan window in millis. 5412 */ getScreenOffLowPowerWindowMillis()5413 public int getScreenOffLowPowerWindowMillis() { 5414 synchronized (mDeviceConfigLock) { 5415 return mScreenOffLowPowerWindowMillis; 5416 } 5417 } 5418 5419 /** 5420 * Returns SCREEN_OFF low power scan interval in millis. 5421 */ getScreenOffLowPowerIntervalMillis()5422 public int getScreenOffLowPowerIntervalMillis() { 5423 synchronized (mDeviceConfigLock) { 5424 return mScreenOffLowPowerIntervalMillis; 5425 } 5426 } 5427 5428 private final DeviceConfigListener mDeviceConfigListener = new DeviceConfigListener(); 5429 5430 private class DeviceConfigListener implements DeviceConfig.OnPropertiesChangedListener { 5431 private static final String LOCATION_DENYLIST_NAME = 5432 "location_denylist_name"; 5433 private static final String LOCATION_DENYLIST_MAC = 5434 "location_denylist_mac"; 5435 private static final String LOCATION_DENYLIST_ADVERTISING_DATA = 5436 "location_denylist_advertising_data"; 5437 private static final String SCAN_QUOTA_COUNT = 5438 "scan_quota_count"; 5439 private static final String SCAN_QUOTA_WINDOW_MILLIS = 5440 "scan_quota_window_millis"; 5441 private static final String SCAN_TIMEOUT_MILLIS = 5442 "scan_timeout_millis"; 5443 private static final String SCAN_UPGRADE_DURATION_MILLIS = 5444 "scan_upgrade_duration_millis"; 5445 private static final String SCREEN_OFF_LOW_POWER_WINDOW_MILLIS = 5446 "screen_off_low_power_window_millis"; 5447 private static final String SCREEN_OFF_LOW_POWER_INTERVAL_MILLIS = 5448 "screen_off_low_power_interval_millis"; 5449 private static final String SCREEN_OFF_BALANCED_WINDOW_MILLIS = 5450 "screen_off_balanced_window_millis"; 5451 private static final String SCREEN_OFF_BALANCED_INTERVAL_MILLIS = 5452 "screen_off_balanced_interval_millis"; 5453 5454 /** 5455 * Default denylist which matches Eddystone and iBeacon payloads. 5456 */ 5457 private static final String DEFAULT_LOCATION_DENYLIST_ADVERTISING_DATA = 5458 "⊆0016AAFE/00FFFFFF,⊆00FF4C0002/00FFFFFFFF"; 5459 5460 private static final int DEFAULT_SCAN_QUOTA_COUNT = 5; 5461 private static final long DEFAULT_SCAN_QUOTA_WINDOW_MILLIS = 30 * SECOND_IN_MILLIS; 5462 private static final long DEFAULT_SCAN_TIMEOUT_MILLIS = 30 * MINUTE_IN_MILLIS; 5463 private static final int DEFAULT_SCAN_UPGRADE_DURATION_MILLIS = (int) SECOND_IN_MILLIS * 6; 5464 start()5465 public void start() { 5466 DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_BLUETOOTH, 5467 BackgroundThread.getExecutor(), this); 5468 onPropertiesChanged(DeviceConfig.getProperties(DeviceConfig.NAMESPACE_BLUETOOTH)); 5469 } 5470 5471 @Override onPropertiesChanged(DeviceConfig.Properties properties)5472 public void onPropertiesChanged(DeviceConfig.Properties properties) { 5473 synchronized (mDeviceConfigLock) { 5474 final String name = properties.getString(LOCATION_DENYLIST_NAME, null); 5475 mLocationDenylistName = !TextUtils.isEmpty(name) 5476 ? Pattern.compile(name).asPredicate() 5477 : (v) -> false; 5478 mLocationDenylistMac = BytesMatcher 5479 .decode(properties.getString(LOCATION_DENYLIST_MAC, null)); 5480 mLocationDenylistAdvertisingData = BytesMatcher 5481 .decode(properties.getString(LOCATION_DENYLIST_ADVERTISING_DATA, 5482 DEFAULT_LOCATION_DENYLIST_ADVERTISING_DATA)); 5483 mScanQuotaCount = properties.getInt(SCAN_QUOTA_COUNT, 5484 DEFAULT_SCAN_QUOTA_COUNT); 5485 mScanQuotaWindowMillis = properties.getLong(SCAN_QUOTA_WINDOW_MILLIS, 5486 DEFAULT_SCAN_QUOTA_WINDOW_MILLIS); 5487 mScanTimeoutMillis = properties.getLong(SCAN_TIMEOUT_MILLIS, 5488 DEFAULT_SCAN_TIMEOUT_MILLIS); 5489 mScanUpgradeDurationMillis = properties.getInt(SCAN_UPGRADE_DURATION_MILLIS, 5490 DEFAULT_SCAN_UPGRADE_DURATION_MILLIS); 5491 mScreenOffLowPowerWindowMillis = properties.getInt( 5492 SCREEN_OFF_LOW_POWER_WINDOW_MILLIS, 5493 ScanManager.SCAN_MODE_SCREEN_OFF_LOW_POWER_WINDOW_MS); 5494 mScreenOffLowPowerIntervalMillis = properties.getInt( 5495 SCREEN_OFF_LOW_POWER_INTERVAL_MILLIS, 5496 ScanManager.SCAN_MODE_SCREEN_OFF_LOW_POWER_INTERVAL_MS); 5497 mScreenOffBalancedWindowMillis = properties.getInt( 5498 SCREEN_OFF_BALANCED_WINDOW_MILLIS, 5499 ScanManager.SCAN_MODE_SCREEN_OFF_BALANCED_WINDOW_MS); 5500 mScreenOffBalancedIntervalMillis = properties.getInt( 5501 SCREEN_OFF_BALANCED_INTERVAL_MILLIS, 5502 ScanManager.SCAN_MODE_SCREEN_OFF_BALANCED_INTERVAL_MS); 5503 } 5504 } 5505 } 5506 5507 /** 5508 * Obfuscate Bluetooth MAC address into a PII free ID string 5509 * 5510 * @param device Bluetooth device whose MAC address will be obfuscated 5511 * @return a byte array that is unique to this MAC address on this device, 5512 * or empty byte array when either device is null or obfuscateAddressNative fails 5513 */ obfuscateAddress(BluetoothDevice device)5514 public byte[] obfuscateAddress(BluetoothDevice device) { 5515 if (device == null) { 5516 return new byte[0]; 5517 } 5518 return obfuscateAddressNative(Utils.getByteAddress(device)); 5519 } 5520 5521 /** 5522 * Get dynamic audio buffer size supported type 5523 * 5524 * @return support <p>Possible values are 5525 * {@link BluetoothA2dp#DYNAMIC_BUFFER_SUPPORT_NONE}, 5526 * {@link BluetoothA2dp#DYNAMIC_BUFFER_SUPPORT_A2DP_OFFLOAD}, 5527 * {@link BluetoothA2dp#DYNAMIC_BUFFER_SUPPORT_A2DP_SOFTWARE_ENCODING}. 5528 */ getDynamicBufferSupport()5529 public int getDynamicBufferSupport() { 5530 return mAdapterProperties.getDynamicBufferSupport(); 5531 } 5532 5533 /** 5534 * Get dynamic audio buffer size 5535 * 5536 * @return BufferConstraints 5537 */ getBufferConstraints()5538 public BufferConstraints getBufferConstraints() { 5539 return mAdapterProperties.getBufferConstraints(); 5540 } 5541 5542 /** 5543 * Set dynamic audio buffer size 5544 * 5545 * @param codec Audio codec 5546 * @param value buffer millis 5547 * @return true if the settings is successful, false otherwise 5548 */ setBufferLengthMillis(int codec, int value)5549 public boolean setBufferLengthMillis(int codec, int value) { 5550 return mAdapterProperties.setBufferLengthMillis(codec, value); 5551 } 5552 5553 /** 5554 * Get an incremental id of Bluetooth metrics and log 5555 * 5556 * @param device Bluetooth device 5557 * @return int of id for Bluetooth metrics and logging, 0 if the device is invalid 5558 */ getMetricId(BluetoothDevice device)5559 public int getMetricId(BluetoothDevice device) { 5560 if (device == null) { 5561 return 0; 5562 } 5563 return getMetricIdNative(Utils.getByteAddress(device)); 5564 } 5565 getCompanionManager()5566 public CompanionManager getCompanionManager() { 5567 return mBtCompanionManager; 5568 } 5569 5570 /** 5571 * Call for the AdapterService receives bond state change 5572 * 5573 * @param device Bluetooth device 5574 * @param state bond state 5575 */ onBondStateChanged(BluetoothDevice device, int state)5576 public void onBondStateChanged(BluetoothDevice device, int state) { 5577 if (mBtCompanionManager != null) { 5578 mBtCompanionManager.onBondStateChanged(device, state); 5579 } 5580 } 5581 5582 /** 5583 * Get audio policy feature support status 5584 * 5585 * @param device Bluetooth device to be checked for audio policy support 5586 * @return int status of the remote support for audio policy feature 5587 */ isRequestAudioPolicyAsSinkSupported(BluetoothDevice device)5588 public int isRequestAudioPolicyAsSinkSupported(BluetoothDevice device) { 5589 if (mHeadsetClientService != null) { 5590 return mHeadsetClientService.getAudioPolicyRemoteSupported(device); 5591 } else { 5592 Log.e(TAG, "No audio transport connected"); 5593 return BluetoothStatusCodes.FEATURE_NOT_CONFIGURED; 5594 } 5595 } 5596 5597 /** 5598 * Set audio policy for remote device 5599 * 5600 * @param device Bluetooth device to be set policy for 5601 * @return int result status for requestAudioPolicyAsSink API 5602 */ requestAudioPolicyAsSink(BluetoothDevice device, BluetoothSinkAudioPolicy policies)5603 public int requestAudioPolicyAsSink(BluetoothDevice device, BluetoothSinkAudioPolicy policies) { 5604 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 5605 if (deviceProp == null) { 5606 return BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED; 5607 } 5608 5609 if (mHeadsetClientService != null) { 5610 if (isRequestAudioPolicyAsSinkSupported(device) 5611 != BluetoothStatusCodes.FEATURE_SUPPORTED) { 5612 throw new UnsupportedOperationException( 5613 "Request Audio Policy As Sink not supported"); 5614 } 5615 deviceProp.setHfAudioPolicyForRemoteAg(policies); 5616 mHeadsetClientService.setAudioPolicy(device, policies); 5617 return BluetoothStatusCodes.SUCCESS; 5618 } else { 5619 Log.e(TAG, "HeadsetClient not connected"); 5620 return BluetoothStatusCodes.ERROR_PROFILE_NOT_CONNECTED; 5621 } 5622 } 5623 5624 /** 5625 * Get audio policy for remote device 5626 * 5627 * @param device Bluetooth device to be set policy for 5628 * @return {@link BluetoothSinkAudioPolicy} policy stored for the device 5629 */ getRequestedAudioPolicyAsSink(BluetoothDevice device)5630 public BluetoothSinkAudioPolicy getRequestedAudioPolicyAsSink(BluetoothDevice device) { 5631 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 5632 if (deviceProp == null) { 5633 return null; 5634 } 5635 5636 if (mHeadsetClientService != null) { 5637 return deviceProp.getHfAudioPolicyForRemoteAg(); 5638 } else { 5639 Log.e(TAG, "HeadsetClient not connected"); 5640 return null; 5641 } 5642 } 5643 5644 /** 5645 * Allow audio low latency 5646 * 5647 * @param allowed true if audio low latency is being allowed 5648 * @param device device whose audio low latency will be allowed or disallowed 5649 * @return boolean true if audio low latency is successfully allowed or disallowed 5650 */ allowLowLatencyAudio(boolean allowed, BluetoothDevice device)5651 public boolean allowLowLatencyAudio(boolean allowed, BluetoothDevice device) { 5652 return allowLowLatencyAudioNative(allowed, Utils.getByteAddress(device)); 5653 } 5654 5655 /** 5656 * Sets the battery level of the remote device 5657 */ setBatteryLevel(BluetoothDevice device, int batteryLevel)5658 public void setBatteryLevel(BluetoothDevice device, int batteryLevel) { 5659 mRemoteDevices.updateBatteryLevel(device, batteryLevel); 5660 } 5661 classInitNative()5662 static native void classInitNative(); 5663 initNative(boolean startRestricted, boolean isCommonCriteriaMode, int configCompareResult, String[] initFlags, boolean isAtvDevice, String userDataDirectory)5664 native boolean initNative(boolean startRestricted, boolean isCommonCriteriaMode, 5665 int configCompareResult, String[] initFlags, boolean isAtvDevice, 5666 String userDataDirectory); 5667 cleanupNative()5668 native void cleanupNative(); 5669 5670 /*package*/ enableNative()5671 native boolean enableNative(); 5672 5673 /*package*/ disableNative()5674 native boolean disableNative(); 5675 5676 /*package*/ setAdapterPropertyNative(int type, byte[] val)5677 native boolean setAdapterPropertyNative(int type, byte[] val); 5678 5679 /*package*/ getAdapterPropertiesNative()5680 native boolean getAdapterPropertiesNative(); 5681 5682 /*package*/ getAdapterPropertyNative(int type)5683 native boolean getAdapterPropertyNative(int type); 5684 5685 /*package*/ setAdapterPropertyNative(int type)5686 native boolean setAdapterPropertyNative(int type); 5687 5688 /*package*/ setDevicePropertyNative(byte[] address, int type, byte[] val)5689 native boolean setDevicePropertyNative(byte[] address, int type, byte[] val); 5690 5691 /*package*/ getDevicePropertyNative(byte[] address, int type)5692 native boolean getDevicePropertyNative(byte[] address, int type); 5693 5694 /*package*/ createBondNative(byte[] address, int transport)5695 public native boolean createBondNative(byte[] address, int transport); 5696 5697 /*package*/ createBondOutOfBandNative(byte[] address, int transport, OobData p192Data, OobData p256Data)5698 native boolean createBondOutOfBandNative(byte[] address, int transport, 5699 OobData p192Data, OobData p256Data); 5700 5701 /*package*/ removeBondNative(byte[] address)5702 public native boolean removeBondNative(byte[] address); 5703 5704 /*package*/ cancelBondNative(byte[] address)5705 native boolean cancelBondNative(byte[] address); 5706 5707 /*package*/ generateLocalOobDataNative(int transport)5708 native void generateLocalOobDataNative(int transport); 5709 5710 /*package*/ sdpSearchNative(byte[] address, byte[] uuid)5711 native boolean sdpSearchNative(byte[] address, byte[] uuid); 5712 5713 /*package*/ getConnectionStateNative(byte[] address)5714 native int getConnectionStateNative(byte[] address); 5715 startDiscoveryNative()5716 private native boolean startDiscoveryNative(); 5717 cancelDiscoveryNative()5718 private native boolean cancelDiscoveryNative(); 5719 pinReplyNative(byte[] address, boolean accept, int len, byte[] pin)5720 private native boolean pinReplyNative(byte[] address, boolean accept, int len, byte[] pin); 5721 sspReplyNative(byte[] address, int type, boolean accept, int passkey)5722 private native boolean sspReplyNative(byte[] address, int type, boolean accept, int passkey); 5723 5724 /*package*/ getRemoteServicesNative(byte[] address, int transport)5725 native boolean getRemoteServicesNative(byte[] address, int transport); 5726 5727 /*package*/ getRemoteMasInstancesNative(byte[] address)5728 native boolean getRemoteMasInstancesNative(byte[] address); 5729 readEnergyInfo()5730 private native int readEnergyInfo(); 5731 5732 /*package*/ factoryResetNative()5733 native boolean factoryResetNative(); 5734 alarmFiredNative()5735 private native void alarmFiredNative(); 5736 dumpNative(FileDescriptor fd, String[] arguments)5737 private native void dumpNative(FileDescriptor fd, String[] arguments); 5738 dumpMetricsNative()5739 private native byte[] dumpMetricsNative(); 5740 obfuscateAddressNative(byte[] address)5741 private native byte[] obfuscateAddressNative(byte[] address); 5742 setBufferLengthMillisNative(int codec, int value)5743 native boolean setBufferLengthMillisNative(int codec, int value); 5744 getMetricIdNative(byte[] address)5745 private native int getMetricIdNative(byte[] address); 5746 connectSocketNative( byte[] address, int type, byte[] uuid, int port, int flag, int callingUid)5747 /*package*/ native int connectSocketNative( 5748 byte[] address, int type, byte[] uuid, int port, int flag, int callingUid); 5749 createSocketChannelNative( int type, String serviceName, byte[] uuid, int port, int flag, int callingUid)5750 /*package*/ native int createSocketChannelNative( 5751 int type, String serviceName, byte[] uuid, int port, int flag, int callingUid); 5752 requestMaximumTxDataLengthNative(byte[] address)5753 /*package*/ native void requestMaximumTxDataLengthNative(byte[] address); 5754 allowLowLatencyAudioNative(boolean allowed, byte[] address)5755 private native boolean allowLowLatencyAudioNative(boolean allowed, byte[] address); 5756 metadataChangedNative(byte[] address, int key, byte[] value)5757 private native void metadataChangedNative(byte[] address, int key, byte[] value); 5758 5759 // Returns if this is a mock object. This is currently used in testing so that we may not call 5760 // System.exit() while finalizing the object. Otherwise GC of mock objects unfortunately ends up 5761 // calling finalize() which in turn calls System.exit() and the process crashes. 5762 // 5763 // Mock this in your testing framework to return true to avoid the mentioned behavior. In 5764 // production this has no effect. isMock()5765 public boolean isMock() { 5766 return false; 5767 } 5768 } 5769