1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * Copyright (C) 2016-2017 The Linux Foundation 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package com.android.bluetooth.btservice; 19 20 import static android.Manifest.permission.BLUETOOTH_CONNECT; 21 import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; 22 import static android.Manifest.permission.BLUETOOTH_SCAN; 23 import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE; 24 import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE; 25 import static android.bluetooth.BluetoothAdapter.SCAN_MODE_NONE; 26 import static android.bluetooth.BluetoothAdapter.nameForState; 27 import static android.bluetooth.BluetoothDevice.BATTERY_LEVEL_UNKNOWN; 28 import static android.bluetooth.BluetoothDevice.BOND_NONE; 29 import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED; 30 import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; 31 import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_UNKNOWN; 32 import static android.bluetooth.BluetoothProfile.STATE_CONNECTED; 33 import static android.bluetooth.BluetoothProfile.STATE_CONNECTING; 34 import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED; 35 import static android.bluetooth.BluetoothProfile.getProfileName; 36 import static android.bluetooth.BluetoothUtils.RemoteExceptionIgnoringConsumer; 37 import static android.bluetooth.IBluetoothLeAudio.LE_AUDIO_GROUP_ID_INVALID; 38 import static android.text.format.DateUtils.MINUTE_IN_MILLIS; 39 import static android.text.format.DateUtils.SECOND_IN_MILLIS; 40 41 import static com.android.bluetooth.Utils.getBytesFromAddress; 42 import static com.android.bluetooth.Utils.isDualModeAudioEnabled; 43 import static com.android.bluetooth.Utils.isPackageNameAccurate; 44 import static com.android.modules.utils.build.SdkLevel.isAtLeastV; 45 46 import static java.util.Objects.requireNonNull; 47 48 import android.annotation.NonNull; 49 import android.annotation.Nullable; 50 import android.annotation.RequiresPermission; 51 import android.annotation.SuppressLint; 52 import android.app.AppOpsManager; 53 import android.app.PendingIntent; 54 import android.app.Service; 55 import android.app.admin.DevicePolicyManager; 56 import android.bluetooth.BluetoothA2dp; 57 import android.bluetooth.BluetoothActivityEnergyInfo; 58 import android.bluetooth.BluetoothAdapter; 59 import android.bluetooth.BluetoothAdapter.ActiveDeviceProfile; 60 import android.bluetooth.BluetoothAdapter.ActiveDeviceUse; 61 import android.bluetooth.BluetoothDevice; 62 import android.bluetooth.BluetoothDevice.BluetoothAddress; 63 import android.bluetooth.BluetoothFrameworkInitializer; 64 import android.bluetooth.BluetoothLeAudio; 65 import android.bluetooth.BluetoothMap; 66 import android.bluetooth.BluetoothProfile; 67 import android.bluetooth.BluetoothQualityReport; 68 import android.bluetooth.BluetoothSap; 69 import android.bluetooth.BluetoothServerSocket; 70 import android.bluetooth.BluetoothSinkAudioPolicy; 71 import android.bluetooth.BluetoothSocket; 72 import android.bluetooth.BluetoothStatusCodes; 73 import android.bluetooth.BluetoothUtils; 74 import android.bluetooth.BluetoothUuid; 75 import android.bluetooth.BufferConstraints; 76 import android.bluetooth.IBluetoothCallback; 77 import android.bluetooth.IBluetoothConnectionCallback; 78 import android.bluetooth.IBluetoothMetadataListener; 79 import android.bluetooth.IBluetoothOobDataCallback; 80 import android.bluetooth.IBluetoothPreferredAudioProfilesCallback; 81 import android.bluetooth.IBluetoothQualityReportReadyCallback; 82 import android.bluetooth.IncomingRfcommSocketInfo; 83 import android.bluetooth.OobData; 84 import android.bluetooth.UidTraffic; 85 import android.bluetooth.rfcomm.BluetoothRfcommProtoEnums; 86 import android.companion.CompanionDeviceManager; 87 import android.content.AttributionSource; 88 import android.content.Context; 89 import android.content.Intent; 90 import android.content.SharedPreferences; 91 import android.content.pm.PackageManager; 92 import android.hardware.devicestate.DeviceStateManager; 93 import android.os.AsyncTask; 94 import android.os.BatteryStatsManager; 95 import android.os.Binder; 96 import android.os.Build; 97 import android.os.Bundle; 98 import android.os.Handler; 99 import android.os.IBinder; 100 import android.os.Looper; 101 import android.os.Message; 102 import android.os.ParcelUuid; 103 import android.os.Parcelable; 104 import android.os.PowerManager; 105 import android.os.RemoteCallbackList; 106 import android.os.RemoteException; 107 import android.os.SystemClock; 108 import android.os.UserHandle; 109 import android.os.UserManager; 110 import android.provider.DeviceConfig; 111 import android.provider.Settings; 112 import android.sysprop.BluetoothProperties; 113 import android.text.TextUtils; 114 import android.util.Log; 115 import android.util.Pair; 116 import android.util.SparseArray; 117 118 import com.android.bluetooth.BluetoothEventLogger; 119 import com.android.bluetooth.BluetoothStatsLog; 120 import com.android.bluetooth.R; 121 import com.android.bluetooth.Utils; 122 import com.android.bluetooth.a2dp.A2dpService; 123 import com.android.bluetooth.a2dpsink.A2dpSinkService; 124 import com.android.bluetooth.avrcp.AvrcpTargetService; 125 import com.android.bluetooth.avrcpcontroller.AvrcpControllerService; 126 import com.android.bluetooth.bas.BatteryService; 127 import com.android.bluetooth.bass_client.BassClientService; 128 import com.android.bluetooth.btservice.InteropUtil.InteropFeature; 129 import com.android.bluetooth.btservice.RemoteDevices.DeviceProperties; 130 import com.android.bluetooth.btservice.bluetoothkeystore.BluetoothKeystoreNativeInterface; 131 import com.android.bluetooth.btservice.bluetoothkeystore.BluetoothKeystoreService; 132 import com.android.bluetooth.btservice.storage.DatabaseManager; 133 import com.android.bluetooth.btservice.storage.MetadataDatabase; 134 import com.android.bluetooth.csip.CsipSetCoordinatorService; 135 import com.android.bluetooth.flags.Flags; 136 import com.android.bluetooth.gatt.GattService; 137 import com.android.bluetooth.hap.HapClientService; 138 import com.android.bluetooth.hearingaid.HearingAidService; 139 import com.android.bluetooth.hfp.HeadsetService; 140 import com.android.bluetooth.hfpclient.HeadsetClientService; 141 import com.android.bluetooth.hid.HidDeviceService; 142 import com.android.bluetooth.hid.HidHostService; 143 import com.android.bluetooth.le_audio.LeAudioService; 144 import com.android.bluetooth.le_scan.ScanController; 145 import com.android.bluetooth.le_scan.ScanManager; 146 import com.android.bluetooth.map.BluetoothMapService; 147 import com.android.bluetooth.mapclient.MapClientService; 148 import com.android.bluetooth.mcp.McpService; 149 import com.android.bluetooth.opp.BluetoothOppService; 150 import com.android.bluetooth.pan.PanService; 151 import com.android.bluetooth.pbap.BluetoothPbapService; 152 import com.android.bluetooth.pbapclient.PbapClientService; 153 import com.android.bluetooth.sap.SapService; 154 import com.android.bluetooth.sdp.SdpManager; 155 import com.android.bluetooth.tbs.TbsService; 156 import com.android.bluetooth.telephony.BluetoothInCallService; 157 import com.android.bluetooth.vc.VolumeControlService; 158 import com.android.internal.annotations.GuardedBy; 159 import com.android.internal.annotations.VisibleForTesting; 160 import com.android.modules.utils.BackgroundThread; 161 import com.android.modules.utils.BytesMatcher; 162 163 import java.io.FileDescriptor; 164 import java.io.IOException; 165 import java.io.PrintWriter; 166 import java.nio.file.FileVisitResult; 167 import java.nio.file.Files; 168 import java.nio.file.Path; 169 import java.nio.file.Paths; 170 import java.nio.file.SimpleFileVisitor; 171 import java.nio.file.attribute.BasicFileAttributes; 172 import java.time.Duration; 173 import java.time.Instant; 174 import java.util.ArrayDeque; 175 import java.util.ArrayList; 176 import java.util.Arrays; 177 import java.util.HashMap; 178 import java.util.HashSet; 179 import java.util.Iterator; 180 import java.util.List; 181 import java.util.Locale; 182 import java.util.Map; 183 import java.util.Objects; 184 import java.util.Optional; 185 import java.util.Set; 186 import java.util.UUID; 187 import java.util.concurrent.ConcurrentHashMap; 188 import java.util.concurrent.ConcurrentLinkedQueue; 189 import java.util.concurrent.Executor; 190 import java.util.function.Function; 191 import java.util.function.Predicate; 192 import java.util.regex.Pattern; 193 194 public class AdapterService extends Service { 195 private static final String TAG = 196 Utils.TAG_PREFIX_BLUETOOTH + AdapterService.class.getSimpleName(); 197 198 private static final int MESSAGE_PROFILE_SERVICE_STATE_CHANGED = 1; 199 private static final int MESSAGE_PROFILE_SERVICE_REGISTERED = 2; 200 private static final int MESSAGE_PROFILE_SERVICE_UNREGISTERED = 3; 201 private static final int MESSAGE_PREFERRED_AUDIO_PROFILES_AUDIO_FRAMEWORK_TIMEOUT = 4; 202 203 private static final int CONTROLLER_ENERGY_UPDATE_TIMEOUT_MILLIS = 100; 204 205 private static final Duration PENDING_SOCKET_HANDOFF_TIMEOUT = Duration.ofMinutes(1); 206 private static final Duration GENERATE_LOCAL_OOB_DATA_TIMEOUT = Duration.ofSeconds(2); 207 private static final Duration PREFERRED_AUDIO_PROFILE_CHANGE_TIMEOUT = Duration.ofSeconds(10); 208 209 static final String PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE = "phonebook_access_permission"; 210 static final String MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE = "message_access_permission"; 211 static final String SIM_ACCESS_PERMISSION_PREFERENCE_FILE = "sim_access_permission"; 212 213 private static BluetoothProperties.snoop_log_mode_values sSnoopLogSettingAtEnable = 214 BluetoothProperties.snoop_log_mode_values.EMPTY; 215 private static String sDefaultSnoopLogSettingAtEnable = "empty"; 216 private static boolean sSnoopLogFilterHeadersSettingAtEnable = false; 217 private static boolean sSnoopLogFilterProfileA2dpSettingAtEnable = false; 218 private static boolean sSnoopLogFilterProfileRfcommSettingAtEnable = false; 219 220 private static BluetoothProperties.snoop_log_filter_profile_pbap_values 221 sSnoopLogFilterProfilePbapModeSettingAtEnable = 222 BluetoothProperties.snoop_log_filter_profile_pbap_values.EMPTY; 223 private static BluetoothProperties.snoop_log_filter_profile_map_values 224 sSnoopLogFilterProfileMapModeSettingAtEnable = 225 BluetoothProperties.snoop_log_filter_profile_map_values.EMPTY; 226 227 private static AdapterService sAdapterService; 228 229 private final Object mEnergyInfoLock = new Object(); 230 private final SparseArray<UidTraffic> mUidTraffic = new SparseArray<>(); 231 232 private final Map<Integer, ProfileService> mStartedProfiles = new HashMap<>(); 233 private final List<ProfileService> mRegisteredProfiles = new ArrayList<>(); 234 private final List<ProfileService> mRunningProfiles = new ArrayList<>(); 235 236 private final List<DiscoveringPackage> mDiscoveringPackages = new ArrayList<>(); 237 238 private final AdapterNativeInterface mNativeInterface = AdapterNativeInterface.getInstance(); 239 240 private final Map<BluetoothDevice, RemoteCallbackList<IBluetoothMetadataListener>> 241 mMetadataListeners = new HashMap<>(); 242 243 // Map<groupId, PendingAudioProfilePreferenceRequest> 244 @GuardedBy("mCsipGroupsPendingAudioProfileChanges") 245 private final Map<Integer, PendingAudioProfilePreferenceRequest> 246 mCsipGroupsPendingAudioProfileChanges = new HashMap<>(); 247 248 private final Map<BluetoothStateCallback, Executor> mLocalCallbacks = new ConcurrentHashMap<>(); 249 private final Map<UUID, RfcommListenerData> mBluetoothServerSockets = new ConcurrentHashMap<>(); 250 private final ArrayDeque<IBluetoothOobDataCallback> mOobDataCallbackQueue = new ArrayDeque<>(); 251 252 private final RemoteCallbackList<IBluetoothPreferredAudioProfilesCallback> 253 mPreferredAudioProfilesCallbacks = new RemoteCallbackList<>(); 254 private final RemoteCallbackList<IBluetoothQualityReportReadyCallback> 255 mBluetoothQualityReportReadyCallbacks = new RemoteCallbackList<>(); 256 private final RemoteCallbackList<IBluetoothCallback> mSystemServerCallbacks = 257 new RemoteCallbackList<>(); 258 private final RemoteCallbackList<IBluetoothConnectionCallback> mBluetoothConnectionCallbacks = 259 new RemoteCallbackList<>(); 260 261 private final BluetoothEventLogger mScanModeChanges = 262 new BluetoothEventLogger(10, "Scan Mode Changes"); 263 264 private final DeviceConfigListener mDeviceConfigListener = new DeviceConfigListener(); 265 266 private final BluetoothHciVendorSpecificDispatcher mBluetoothHciVendorSpecificDispatcher = 267 new BluetoothHciVendorSpecificDispatcher(); 268 269 private final Looper mLooper; 270 private final AdapterServiceHandler mHandler; 271 272 private int mStackReportedState; 273 private long mTxTimeTotalMs; 274 private long mRxTimeTotalMs; 275 private long mIdleTimeTotalMs; 276 private long mEnergyUsedTotalVoltAmpSecMicro; 277 private final HashSet<String> mLeAudioAllowDevices = new HashSet<>(); 278 279 /* List of pairs of gatt clients which controls AutoActiveMode on the device.*/ 280 @VisibleForTesting 281 final List<Pair<Integer, BluetoothDevice>> mLeGattClientsControllingAutoActiveMode = 282 new ArrayList<>(); 283 284 private BluetoothAdapter mAdapter; 285 private AdapterProperties mAdapterProperties; 286 private AdapterState mAdapterStateMachine; 287 private BondStateMachine mBondStateMachine; 288 private RemoteDevices mRemoteDevices; 289 private AdapterSuspend mAdapterSuspend; 290 291 /* TODO: Consider to remove the search API from this class, if changed to use call-back */ 292 private SdpManager mSdpManager = null; 293 294 private boolean mNativeAvailable; 295 private boolean mCleaningUp; 296 private boolean mQuietmode = false; 297 private final Map<String, CallerInfo> mBondAttemptCallerInfo = new HashMap<>(); 298 299 private BatteryStatsManager mBatteryStatsManager; 300 private PowerManager mPowerManager; 301 private PowerManager.WakeLock mWakeLock; 302 private UserManager mUserManager; 303 private CompanionDeviceManager mCompanionDeviceManager; 304 305 // Phone Policy is not used on all devices and can be empty 306 private Optional<PhonePolicy> mPhonePolicy = Optional.empty(); 307 308 private ActiveDeviceManager mActiveDeviceManager; 309 private final DatabaseManager mDatabaseManager; 310 private final SilenceDeviceManager mSilenceDeviceManager; 311 private CompanionManager mBtCompanionManager; 312 private AppOpsManager mAppOps; 313 314 private BluetoothSocketManagerBinder mBluetoothSocketManagerBinder; 315 316 private BluetoothKeystoreService mBluetoothKeystoreService; 317 private HeadsetService mHeadsetService; 318 private HeadsetClientService mHeadsetClientService; 319 private A2dpService mA2dpService; 320 private A2dpSinkService mA2dpSinkService; 321 private BluetoothMapService mMapService; 322 private MapClientService mMapClientService; 323 private HidDeviceService mHidDeviceService; 324 private HidHostService mHidHostService; 325 private PanService mPanService; 326 private BluetoothPbapService mPbapService; 327 private PbapClientService mPbapClientService; 328 private HearingAidService mHearingAidService; 329 private HapClientService mHapClientService; 330 private SapService mSapService; 331 private VolumeControlService mVolumeControlService; 332 private CsipSetCoordinatorService mCsipSetCoordinatorService; 333 private LeAudioService mLeAudioService; 334 private BassClientService mBassClientService; 335 private BatteryService mBatteryService; 336 private BluetoothQualityReportNativeInterface mBluetoothQualityReportNativeInterface; 337 private BluetoothHciVendorSpecificNativeInterface mBluetoothHciVendorSpecificNativeInterface; 338 private GattService mGattService; 339 private ScanController mScanController; 340 341 private volatile boolean mTestModeEnabled = false; 342 343 /** Handlers for incoming service calls */ 344 private AdapterServiceBinder mBinder; 345 346 private volatile int mScanMode; 347 348 // Report ID definition 349 public enum BqrQualityReportId { 350 QUALITY_REPORT_ID_MONITOR_MODE(0x01), 351 QUALITY_REPORT_ID_APPROACH_LSTO(0x02), 352 QUALITY_REPORT_ID_A2DP_AUDIO_CHOPPY(0x03), 353 QUALITY_REPORT_ID_SCO_VOICE_CHOPPY(0x04), 354 QUALITY_REPORT_ID_ROOT_INFLAMMATION(0x05), 355 QUALITY_REPORT_ID_CONNECT_FAIL(0x08), 356 QUALITY_REPORT_ID_LMP_LL_MESSAGE_TRACE(0x11), 357 QUALITY_REPORT_ID_BT_SCHEDULING_TRACE(0x12), 358 QUALITY_REPORT_ID_CONTROLLER_DBG_INFO(0x13); 359 360 private final int mValue; 361 BqrQualityReportId(int value)362 BqrQualityReportId(int value) { 363 mValue = value; 364 } 365 getValue()366 public int getValue() { 367 return mValue; 368 } 369 }; 370 371 // Keep a constructor for ActivityThread.handleCreateService AdapterService()372 AdapterService() { 373 this(Looper.getMainLooper()); 374 } 375 376 @VisibleForTesting AdapterService(Context ctx)377 public AdapterService(Context ctx) { 378 this(Looper.getMainLooper(), ctx); 379 } 380 381 @VisibleForTesting AdapterService(Looper looper, Context ctx)382 AdapterService(Looper looper, Context ctx) { 383 this(looper); 384 attachBaseContext(ctx); 385 } 386 AdapterService(Looper looper)387 private AdapterService(Looper looper) { 388 mLooper = requireNonNull(looper); 389 mHandler = new AdapterServiceHandler(mLooper); 390 mSilenceDeviceManager = new SilenceDeviceManager(this, new ServiceFactory(), mLooper); 391 mDatabaseManager = new DatabaseManager(this); 392 } 393 getAdapterService()394 public static synchronized AdapterService getAdapterService() { 395 return sAdapterService; 396 } 397 398 /** Allow test to set an AdapterService to be return by AdapterService.getAdapterService() */ 399 @VisibleForTesting setAdapterService(AdapterService instance)400 public static synchronized void setAdapterService(AdapterService instance) { 401 if (instance == null) { 402 Log.e(TAG, "setAdapterService() - instance is null"); 403 return; 404 } 405 Log.d(TAG, "setAdapterService() - set service to " + instance); 406 sAdapterService = instance; 407 } 408 409 /** Clear test Adapter service. See {@code setAdapterService} */ 410 @VisibleForTesting clearAdapterService(AdapterService instance)411 public static synchronized void clearAdapterService(AdapterService instance) { 412 if (sAdapterService == instance) { 413 Log.d(TAG, "clearAdapterService() - This adapter was cleared " + instance); 414 sAdapterService = null; 415 } else { 416 Log.d( 417 TAG, 418 "clearAdapterService() - incorrect cleared adapter." 419 + (" Instance=" + instance) 420 + (" vs sAdapterService=" + sAdapterService)); 421 } 422 } 423 424 /** 425 * Register a {@link ProfileService} with AdapterService. 426 * 427 * @param profile the service being added. 428 */ addProfile(ProfileService profile)429 public void addProfile(ProfileService profile) { 430 mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_REGISTERED, profile).sendToTarget(); 431 } 432 433 /** 434 * Unregister a ProfileService with AdapterService. 435 * 436 * @param profile the service being removed. 437 */ removeProfile(ProfileService profile)438 public void removeProfile(ProfileService profile) { 439 mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_UNREGISTERED, profile).sendToTarget(); 440 } 441 442 /** 443 * Notify AdapterService that a ProfileService has started or stopped. 444 * 445 * @param profile the service being removed. 446 * @param state {@link BluetoothAdapter#STATE_ON} or {@link BluetoothAdapter#STATE_OFF} 447 */ onProfileServiceStateChanged(ProfileService profile, int state)448 public void onProfileServiceStateChanged(ProfileService profile, int state) { 449 if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) { 450 throw new IllegalArgumentException(nameForState(state)); 451 } 452 Message m = mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_STATE_CHANGED); 453 m.obj = profile; 454 m.arg1 = state; 455 mHandler.sendMessage(m); 456 } 457 458 class AdapterServiceHandler extends Handler { AdapterServiceHandler(Looper looper)459 AdapterServiceHandler(Looper looper) { 460 super(looper); 461 } 462 463 @Override handleMessage(Message msg)464 public void handleMessage(Message msg) { 465 Log.v(TAG, "handleMessage() - Message: " + msg.what); 466 467 switch (msg.what) { 468 case MESSAGE_PROFILE_SERVICE_STATE_CHANGED: 469 Log.v(TAG, "handleMessage() - MESSAGE_PROFILE_SERVICE_STATE_CHANGED"); 470 processProfileServiceStateChanged((ProfileService) msg.obj, msg.arg1); 471 break; 472 case MESSAGE_PROFILE_SERVICE_REGISTERED: 473 Log.v(TAG, "handleMessage() - MESSAGE_PROFILE_SERVICE_REGISTERED"); 474 registerProfileService((ProfileService) msg.obj); 475 break; 476 case MESSAGE_PROFILE_SERVICE_UNREGISTERED: 477 Log.v(TAG, "handleMessage() - MESSAGE_PROFILE_SERVICE_UNREGISTERED"); 478 unregisterProfileService((ProfileService) msg.obj); 479 break; 480 case MESSAGE_PREFERRED_AUDIO_PROFILES_AUDIO_FRAMEWORK_TIMEOUT: 481 Log.e( 482 TAG, 483 "handleMessage() - " 484 + "MESSAGE_PREFERRED_PROFILE_CHANGE_AUDIO_FRAMEWORK_TIMEOUT"); 485 int groupId = (int) msg.obj; 486 487 synchronized (mCsipGroupsPendingAudioProfileChanges) { 488 removeFromPendingAudioProfileChanges(groupId); 489 PendingAudioProfilePreferenceRequest request = 490 mCsipGroupsPendingAudioProfileChanges.remove(groupId); 491 Log.e( 492 TAG, 493 "Preferred audio profiles change audio framework timeout for " 494 + ("device " + request.device)); 495 sendPreferredAudioProfilesCallbackToApps( 496 request.device, 497 request.preferences, 498 BluetoothStatusCodes.ERROR_TIMEOUT); 499 } 500 break; 501 } 502 } 503 registerProfileService(ProfileService profile)504 private void registerProfileService(ProfileService profile) { 505 if (mRegisteredProfiles.contains(profile)) { 506 Log.e(TAG, profile.getName() + " already registered."); 507 return; 508 } 509 mRegisteredProfiles.add(profile); 510 } 511 unregisterProfileService(ProfileService profile)512 private void unregisterProfileService(ProfileService profile) { 513 if (!mRegisteredProfiles.contains(profile)) { 514 Log.e(TAG, profile.getName() + " not registered (UNREGISTER)."); 515 return; 516 } 517 mRegisteredProfiles.remove(profile); 518 } 519 processProfileServiceStateChanged(ProfileService profile, int state)520 private void processProfileServiceStateChanged(ProfileService profile, int state) { 521 switch (state) { 522 case BluetoothAdapter.STATE_ON: 523 if (!mRegisteredProfiles.contains(profile)) { 524 Log.e(TAG, profile.getName() + " not registered (STATE_ON)."); 525 return; 526 } 527 if (mRunningProfiles.contains(profile)) { 528 Log.e(TAG, profile.getName() + " already running."); 529 return; 530 } 531 mRunningProfiles.add(profile); 532 // TODO(b/228875190): GATT is assumed supported. GATT starting triggers hardware 533 // initialization. Configuring a device without GATT causes start up failures. 534 if (GattService.class.getSimpleName().equals(profile.getName()) 535 && !Flags.onlyStartScanDuringBleOn()) { 536 mNativeInterface.enable(); 537 } else if (mRegisteredProfiles.size() == Config.getSupportedProfiles().length 538 && mRegisteredProfiles.size() == mRunningProfiles.size()) { 539 mAdapterProperties.onBluetoothReady(); 540 setScanMode(SCAN_MODE_CONNECTABLE, "processProfileServiceStateChanged"); 541 updateUuids(); 542 initProfileServices(); 543 mNativeInterface.getAdapterProperty( 544 AbstractionLayer.BT_PROPERTY_DYNAMIC_AUDIO_BUFFER); 545 mAdapterStateMachine.sendMessage(AdapterState.BREDR_STARTED); 546 mBtCompanionManager.loadCompanionInfo(); 547 } 548 break; 549 case BluetoothAdapter.STATE_OFF: 550 if (!mRegisteredProfiles.contains(profile)) { 551 Log.e(TAG, profile.getName() + " not registered (STATE_OFF)."); 552 return; 553 } 554 if (!mRunningProfiles.contains(profile)) { 555 Log.e(TAG, profile.getName() + " not running."); 556 return; 557 } 558 mRunningProfiles.remove(profile); 559 560 if (Flags.onlyStartScanDuringBleOn()) { 561 if (mRunningProfiles.size() == 0) { 562 mAdapterStateMachine.sendMessage(AdapterState.BREDR_STOPPED); 563 } 564 } else { 565 // TODO(b/228875190): GATT is assumed supported. GATT is expected to be the 566 // only profile available in the "BLE ON" state. If only GATT is left, send 567 // BREDR_STOPPED. If GATT is stopped, deinitialize the hardware. 568 if ((mRunningProfiles.size() == 1 569 && (GattService.class 570 .getSimpleName() 571 .equals(mRunningProfiles.get(0).getName())))) { 572 mAdapterStateMachine.sendMessage(AdapterState.BREDR_STOPPED); 573 } else if (mRunningProfiles.size() == 0) { 574 mNativeInterface.disable(); 575 } 576 } 577 break; 578 default: 579 Log.e(TAG, "Unhandled profile state: " + state); 580 } 581 } 582 } 583 584 /** 585 * Stores information about requests made to the audio framework arising from calls to {@link 586 * BluetoothAdapter#setPreferredAudioProfiles(BluetoothDevice, Bundle)}. 587 */ PendingAudioProfilePreferenceRequest( Bundle preferences, int numberOfRemainingRequestsToAudioFramework, BluetoothDevice device)588 private record PendingAudioProfilePreferenceRequest( 589 // The newly requested preferences 590 Bundle preferences, 591 // Reference counter for how many calls are pending completion in the audio framework 592 int numberOfRemainingRequestsToAudioFramework, 593 // The device with which the request was made. Used for sending the callback. 594 BluetoothDevice device) {} 595 getNonNullSystemService(@onNull Class<T> clazz)596 final @NonNull <T> T getNonNullSystemService(@NonNull Class<T> clazz) { 597 return requireNonNull(getSystemService(clazz)); 598 } 599 600 @Override onCreate()601 public void onCreate() { 602 super.onCreate(); 603 Log.d(TAG, "onCreate()"); 604 // OnCreate must perform the minimum of infallible and mandatory initialization 605 mRemoteDevices = new RemoteDevices(this, mLooper); 606 mAdapterProperties = new AdapterProperties(this, mRemoteDevices, mLooper); 607 mAdapterStateMachine = new AdapterState(this, mLooper); 608 mBinder = new AdapterServiceBinder(this); 609 mUserManager = getNonNullSystemService(UserManager.class); 610 mAppOps = getNonNullSystemService(AppOpsManager.class); 611 mPowerManager = getNonNullSystemService(PowerManager.class); 612 mBatteryStatsManager = getNonNullSystemService(BatteryStatsManager.class); 613 mCompanionDeviceManager = getNonNullSystemService(CompanionDeviceManager.class); 614 setAdapterService(this); 615 } 616 617 @SuppressLint("AndroidFrameworkRequiresPermission") init()618 private void init() { 619 Log.d(TAG, "init()"); 620 Config.init(this); 621 mDeviceConfigListener.start(); 622 623 MetricsLogger.getInstance().init(this, mRemoteDevices); 624 625 clearDiscoveringPackages(); 626 mAdapter = BluetoothAdapter.getDefaultAdapter(); 627 boolean isCommonCriteriaMode = 628 getNonNullSystemService(DevicePolicyManager.class) 629 .isCommonCriteriaModeEnabled(null); 630 mBluetoothKeystoreService = 631 new BluetoothKeystoreService( 632 BluetoothKeystoreNativeInterface.getInstance(), isCommonCriteriaMode); 633 mBluetoothKeystoreService.start(); 634 int configCompareResult = mBluetoothKeystoreService.getCompareResult(); 635 636 // Start tracking Binder latency for the bluetooth process. 637 BluetoothFrameworkInitializer.initializeBinderCallsStats(getApplicationContext()); 638 639 // Android TV doesn't show consent dialogs for just works and encryption only le pairing 640 boolean isAtvDevice = 641 getApplicationContext() 642 .getPackageManager() 643 .hasSystemFeature(PackageManager.FEATURE_LEANBACK_ONLY); 644 if (Utils.isInstrumentationTestMode()) { 645 Log.w(TAG, "This Bluetooth App is instrumented. ** Skip loading the native **"); 646 } else { 647 Log.d(TAG, "Loading JNI Library"); 648 System.loadLibrary("bluetooth_jni"); 649 } 650 mNativeInterface.init( 651 this, 652 mAdapterProperties, 653 mUserManager.isGuestUser(), 654 isCommonCriteriaMode, 655 configCompareResult, 656 isAtvDevice); 657 mNativeAvailable = true; 658 // Load the name and address 659 mNativeInterface.getAdapterProperty(AbstractionLayer.BT_PROPERTY_BDADDR); 660 mNativeInterface.getAdapterProperty(AbstractionLayer.BT_PROPERTY_BDNAME); 661 mNativeInterface.getAdapterProperty(AbstractionLayer.BT_PROPERTY_CLASS_OF_DEVICE); 662 663 mBluetoothKeystoreService.initJni(); 664 665 mBluetoothQualityReportNativeInterface = 666 requireNonNull(BluetoothQualityReportNativeInterface.getInstance()); 667 mBluetoothQualityReportNativeInterface.init(); 668 669 if (Flags.hciVendorSpecificExtension()) { 670 mBluetoothHciVendorSpecificNativeInterface = 671 requireNonNull(mBluetoothHciVendorSpecificNativeInterface.getInstance()); 672 mBluetoothHciVendorSpecificNativeInterface.init(mBluetoothHciVendorSpecificDispatcher); 673 } 674 675 mSdpManager = new SdpManager(this, mLooper); 676 677 mDatabaseManager.start(MetadataDatabase.createDatabase(this)); 678 679 boolean isAutomotiveDevice = 680 getApplicationContext() 681 .getPackageManager() 682 .hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE); 683 684 /* 685 * Phone policy is specific to phone implementations and hence if a device wants to exclude 686 * it out then it can be disabled by using the flag below. Phone policy is never used on 687 * Android Automotive OS builds, in favor of a policy currently located in 688 * CarBluetoothService. 689 */ 690 if (!isAutomotiveDevice && getResources().getBoolean(R.bool.enable_phone_policy)) { 691 Log.i(TAG, "Phone policy enabled"); 692 mPhonePolicy = Optional.of(new PhonePolicy(this, mLooper, new ServiceFactory())); 693 } else { 694 Log.i(TAG, "Phone policy disabled"); 695 } 696 697 mActiveDeviceManager = new ActiveDeviceManager(this, new ServiceFactory()); 698 mActiveDeviceManager.start(); 699 700 mBtCompanionManager = new CompanionManager(this, new ServiceFactory()); 701 702 mBluetoothSocketManagerBinder = new BluetoothSocketManagerBinder(this); 703 704 if (Flags.adapterSuspendMgmt() && isAtLeastV()) { 705 mAdapterSuspend = 706 new AdapterSuspend( 707 mNativeInterface, mLooper, getSystemService(DeviceStateManager.class)); 708 } 709 710 invalidateBluetoothCaches(); 711 712 // First call to getSharedPreferences will result in a file read into 713 // memory cache. Call it here asynchronously to avoid potential ANR 714 // in the future 715 new AsyncTask<Void, Void, Void>() { 716 @Override 717 protected Void doInBackground(Void... params) { 718 getSharedPreferences( 719 PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE, Context.MODE_PRIVATE); 720 getSharedPreferences( 721 MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE, Context.MODE_PRIVATE); 722 getSharedPreferences(SIM_ACCESS_PERMISSION_PREFERENCE_FILE, Context.MODE_PRIVATE); 723 return null; 724 } 725 }.execute(); 726 727 try { 728 int systemUiUid = 729 getApplicationContext() 730 .createContextAsUser(UserHandle.SYSTEM, /* flags= */ 0) 731 .getPackageManager() 732 .getPackageUid( 733 "com.android.systemui", PackageManager.MATCH_SYSTEM_ONLY); 734 735 Utils.setSystemUiUid(systemUiUid); 736 } catch (PackageManager.NameNotFoundException e) { 737 // Some platforms, such as wearables do not have a system ui. 738 Log.w(TAG, "Unable to resolve SystemUI's UID.", e); 739 } 740 } 741 742 @Override onBind(Intent intent)743 public IBinder onBind(Intent intent) { 744 Log.d(TAG, "onBind()"); 745 return mBinder; 746 } 747 748 @Override onUnbind(Intent intent)749 public boolean onUnbind(Intent intent) { 750 Log.d(TAG, "onUnbind()"); 751 return super.onUnbind(intent); 752 } 753 754 @Override onDestroy()755 public void onDestroy() { 756 Log.d(TAG, "onDestroy()"); 757 } 758 getActiveDeviceManager()759 public ActiveDeviceManager getActiveDeviceManager() { 760 return mActiveDeviceManager; 761 } 762 getRemoteDevices()763 public RemoteDevices getRemoteDevices() { 764 return mRemoteDevices; 765 } 766 getSilenceDeviceManager()767 public SilenceDeviceManager getSilenceDeviceManager() { 768 return mSilenceDeviceManager; 769 } 770 getNative()771 AdapterNativeInterface getNative() { 772 return mNativeInterface; 773 } 774 getHandler()775 AdapterServiceHandler getHandler() { 776 return mHandler; 777 } 778 getDatabaseManager()779 DatabaseManager getDatabaseManager() { 780 return mDatabaseManager; 781 } 782 getAdapterProperties()783 AdapterProperties getAdapterProperties() { 784 return mAdapterProperties; 785 } 786 getMetadataListeners()787 Map<BluetoothDevice, RemoteCallbackList<IBluetoothMetadataListener>> getMetadataListeners() { 788 return mMetadataListeners; 789 } 790 getBondAttemptCallerInfo()791 Map<String, CallerInfo> getBondAttemptCallerInfo() { 792 return mBondAttemptCallerInfo; 793 } 794 getPhonePolicy()795 Optional<PhonePolicy> getPhonePolicy() { 796 return mPhonePolicy; 797 } 798 getBondStateMachine()799 BondStateMachine getBondStateMachine() { 800 return mBondStateMachine; 801 } 802 getCompanionDeviceManager()803 CompanionDeviceManager getCompanionDeviceManager() { 804 return mCompanionDeviceManager; 805 } 806 getBluetoothSocketManagerBinder()807 BluetoothSocketManagerBinder getBluetoothSocketManagerBinder() { 808 return mBluetoothSocketManagerBinder; 809 } 810 getBluetoothConnectionCallbacks()811 RemoteCallbackList<IBluetoothConnectionCallback> getBluetoothConnectionCallbacks() { 812 return mBluetoothConnectionCallbacks; 813 } 814 815 RemoteCallbackList<IBluetoothPreferredAudioProfilesCallback> getPreferredAudioProfilesCallbacks()816 getPreferredAudioProfilesCallbacks() { 817 return mPreferredAudioProfilesCallbacks; 818 } 819 820 RemoteCallbackList<IBluetoothQualityReportReadyCallback> getBluetoothQualityReportReadyCallbacks()821 getBluetoothQualityReportReadyCallbacks() { 822 return mBluetoothQualityReportReadyCallbacks; 823 } 824 getBluetoothHciVendorSpecificDispatcher()825 BluetoothHciVendorSpecificDispatcher getBluetoothHciVendorSpecificDispatcher() { 826 return mBluetoothHciVendorSpecificDispatcher; 827 } 828 getBluetoothHciVendorSpecificNativeInterface()829 BluetoothHciVendorSpecificNativeInterface getBluetoothHciVendorSpecificNativeInterface() { 830 return mBluetoothHciVendorSpecificNativeInterface; 831 } 832 833 /** 834 * Log L2CAP CoC Server Connection Metrics 835 * 836 * @param port port of socket 837 * @param isSecured if secured API is called 838 * @param result transaction result of the connection 839 * @param socketCreationLatencyMillis latency of the connection 840 * @param timeoutMillis timeout set by the app 841 */ logL2capcocServerConnection( BluetoothDevice device, int port, boolean isSecured, int result, long socketCreationTimeMillis, long socketCreationLatencyMillis, long socketConnectionTimeMillis, long timeoutMillis, int appUid)842 public void logL2capcocServerConnection( 843 BluetoothDevice device, 844 int port, 845 boolean isSecured, 846 int result, 847 long socketCreationTimeMillis, 848 long socketCreationLatencyMillis, 849 long socketConnectionTimeMillis, 850 long timeoutMillis, 851 int appUid) { 852 853 int metricId = 0; 854 if (device != null) { 855 metricId = getMetricId(device); 856 } 857 long currentTime = System.currentTimeMillis(); 858 long endToEndLatencyMillis = currentTime - socketCreationTimeMillis; 859 long socketAcceptanceLatencyMillis = currentTime - socketConnectionTimeMillis; 860 Log.i( 861 TAG, 862 "Statslog L2capcoc server connection." 863 + (" metricId " + metricId) 864 + (" port " + port) 865 + (" isSecured " + isSecured) 866 + (" result " + result) 867 + (" endToEndLatencyMillis " + endToEndLatencyMillis) 868 + (" socketCreationLatencyMillis " + socketCreationLatencyMillis) 869 + (" socketAcceptanceLatencyMillis " + socketAcceptanceLatencyMillis) 870 + (" timeout set by app " + timeoutMillis) 871 + (" appUid " + appUid)); 872 BluetoothStatsLog.write( 873 BluetoothStatsLog.BLUETOOTH_L2CAP_COC_SERVER_CONNECTION, 874 metricId, 875 port, 876 isSecured, 877 result, 878 endToEndLatencyMillis, 879 timeoutMillis, 880 appUid, 881 socketCreationLatencyMillis, 882 socketAcceptanceLatencyMillis); 883 } 884 885 /** 886 * Log L2CAP CoC Client Connection Metrics 887 * 888 * @param device Bluetooth device 889 * @param port port of socket 890 * @param isSecured if secured API is called 891 * @param result transaction result of the connection 892 * @param socketCreationLatencyNanos latency of the connection 893 */ logL2capcocClientConnection( BluetoothDevice device, int port, boolean isSecured, int result, long socketCreationTimeNanos, long socketCreationLatencyNanos, long socketConnectionTimeNanos, int appUid)894 public void logL2capcocClientConnection( 895 BluetoothDevice device, 896 int port, 897 boolean isSecured, 898 int result, 899 long socketCreationTimeNanos, 900 long socketCreationLatencyNanos, 901 long socketConnectionTimeNanos, 902 int appUid) { 903 904 int metricId = getMetricId(device); 905 long currentTime = System.nanoTime(); 906 long endToEndLatencyMillis = (currentTime - socketCreationTimeNanos) / 1000000; 907 long socketCreationLatencyMillis = socketCreationLatencyNanos / 1000000; 908 long socketConnectionLatencyMillis = (currentTime - socketConnectionTimeNanos) / 1000000; 909 Log.i( 910 TAG, 911 "Statslog L2capcoc client connection." 912 + (" metricId " + metricId) 913 + (" port " + port) 914 + (" isSecured " + isSecured) 915 + (" result " + result) 916 + (" endToEndLatencyMillis " + endToEndLatencyMillis) 917 + (" socketCreationLatencyMillis " + socketCreationLatencyMillis) 918 + (" socketConnectionLatencyMillis " + socketConnectionLatencyMillis) 919 + (" appUid " + appUid)); 920 BluetoothStatsLog.write( 921 BluetoothStatsLog.BLUETOOTH_L2CAP_COC_CLIENT_CONNECTION, 922 metricId, 923 port, 924 isSecured, 925 result, 926 endToEndLatencyMillis, 927 appUid, 928 socketCreationLatencyMillis, 929 socketConnectionLatencyMillis); 930 } 931 932 /** 933 * Log RFCOMM Connection Metrics 934 * 935 * @param device Bluetooth device 936 * @param isSecured if secured API is called 937 * @param resultCode transaction result of the connection 938 * @param isSerialPort true if service class UUID is 0x1101 939 */ logRfcommConnectionAttempt( BluetoothDevice device, boolean isSecured, int resultCode, long socketCreationTimeNanos, boolean isSerialPort, int appUid)940 public void logRfcommConnectionAttempt( 941 BluetoothDevice device, 942 boolean isSecured, 943 int resultCode, 944 long socketCreationTimeNanos, 945 boolean isSerialPort, 946 int appUid) { 947 int metricId = getMetricId(device); 948 long currentTime = System.nanoTime(); 949 long endToEndLatencyNanos = currentTime - socketCreationTimeNanos; 950 byte[] remoteDeviceInfoBytes = MetricsLogger.getInstance().getRemoteDeviceInfoProto(device); 951 BluetoothStatsLog.write( 952 BluetoothStatsLog.BLUETOOTH_RFCOMM_CONNECTION_ATTEMPTED, 953 metricId, 954 endToEndLatencyNanos, 955 isSecured 956 ? BluetoothRfcommProtoEnums.SOCKET_SECURITY_SECURE 957 : BluetoothRfcommProtoEnums.SOCKET_SECURITY_INSECURE, 958 resultCode, 959 isSerialPort, 960 appUid, 961 remoteDeviceInfoBytes); 962 } 963 sdpSearch(BluetoothDevice device, ParcelUuid uuid)964 public boolean sdpSearch(BluetoothDevice device, ParcelUuid uuid) { 965 if (mSdpManager == null) { 966 return false; 967 } 968 mSdpManager.sdpSearch(device, uuid); 969 return true; 970 } 971 972 @RequiresPermission(BLUETOOTH_CONNECT) bringUpBle()973 void bringUpBle() { 974 Log.d(TAG, "bleOnProcessStart()"); 975 976 if (getResources() 977 .getBoolean(R.bool.config_bluetooth_reload_supported_profiles_when_enabled)) { 978 Config.init(getApplicationContext()); 979 } 980 981 // Reset |mRemoteDevices| whenever BLE is turned off then on 982 // This is to replace the fact that |mRemoteDevices| was 983 // reinitialized in previous code. 984 // 985 // TODO(apanicke): The reason is unclear but 986 // I believe it is to clear the variable every time BLE was 987 // turned off then on. The same effect can be achieved by 988 // calling cleanup but this may not be necessary at all 989 // We should figure out why this is needed later 990 mRemoteDevices.reset(); 991 mAdapterProperties.init(); 992 993 Log.d(TAG, "bleOnProcessStart() - Make Bond State Machine"); 994 mBondStateMachine = BondStateMachine.make(this, mAdapterProperties, mRemoteDevices); 995 996 mNativeInterface.getCallbacks().init(mBondStateMachine, mRemoteDevices); 997 998 mBatteryStatsManager.reportBleScanReset(); 999 BluetoothStatsLog.write_non_chained( 1000 BluetoothStatsLog.BLE_SCAN_STATE_CHANGED, 1001 -1, 1002 null, 1003 BluetoothStatsLog.BLE_SCAN_STATE_CHANGED__STATE__RESET, 1004 false, 1005 false, 1006 false); 1007 1008 // TODO(b/228875190): GATT is assumed supported. As a result, we don't respect the 1009 // configuration sysprop. Configuring a device without GATT, although rare, will cause stack 1010 // start up errors yielding init loops. 1011 if (!GattService.isEnabled()) { 1012 Log.w( 1013 TAG, 1014 "GATT is configured off but the stack assumes it to be enabled. Start anyway."); 1015 } 1016 if (Flags.onlyStartScanDuringBleOn()) { 1017 startScanController(); 1018 } else { 1019 startGattProfileService(); 1020 } 1021 } 1022 bringDownBle()1023 void bringDownBle() { 1024 if (Flags.onlyStartScanDuringBleOn()) { 1025 stopScanController(); 1026 } else { 1027 stopGattProfileService(); 1028 } 1029 } 1030 stateChangeCallback(int status)1031 void stateChangeCallback(int status) { 1032 if (status == AbstractionLayer.BT_STATE_OFF) { 1033 Log.d(TAG, "stateChangeCallback: disableNative() completed"); 1034 mAdapterStateMachine.sendMessage(AdapterState.BLE_STOPPED); 1035 } else if (status == AbstractionLayer.BT_STATE_ON) { 1036 mAdapterStateMachine.sendMessage(AdapterState.BLE_STARTED); 1037 } else { 1038 Log.e(TAG, "Incorrect status " + status + " in stateChangeCallback"); 1039 } 1040 } 1041 startProfileServices()1042 void startProfileServices() { 1043 Log.d(TAG, "startCoreServices()"); 1044 int[] supportedProfileServices = Config.getSupportedProfiles(); 1045 if (Flags.onlyStartScanDuringBleOn()) { 1046 // Scanning is always supported, started separately, and is not a profile service. 1047 // This will check other profile services. 1048 if (supportedProfileServices.length == 0) { 1049 mAdapterProperties.onBluetoothReady(); 1050 setScanMode(SCAN_MODE_CONNECTABLE, "startProfileServices"); 1051 updateUuids(); 1052 mAdapterStateMachine.sendMessage(AdapterState.BREDR_STARTED); 1053 } else { 1054 setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_ON); 1055 } 1056 } else { 1057 // TODO(b/228875190): GATT is assumed supported. If we support no other profiles then 1058 // just move on to BREDR_STARTED. Note that configuring GATT to NOT supported will cause 1059 // adapter initialization failures 1060 if (supportedProfileServices.length == 1 1061 && supportedProfileServices[0] == BluetoothProfile.GATT) { 1062 mAdapterProperties.onBluetoothReady(); 1063 setScanMode(SCAN_MODE_CONNECTABLE, "startProfileServices"); 1064 updateUuids(); 1065 mAdapterStateMachine.sendMessage(AdapterState.BREDR_STARTED); 1066 } else { 1067 setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_ON); 1068 } 1069 } 1070 } 1071 stopProfileServices()1072 void stopProfileServices() { 1073 // Make sure to stop classic background tasks now 1074 mNativeInterface.cancelDiscovery(); 1075 setScanMode(SCAN_MODE_NONE, "StopProfileServices"); 1076 1077 int[] supportedProfileServices = Config.getSupportedProfiles(); 1078 if (Flags.onlyStartScanDuringBleOn()) { 1079 // Scanning is always supported, started separately, and is not a profile service. 1080 // This will check other profile services. 1081 if (supportedProfileServices.length == 0) { 1082 mAdapterStateMachine.sendMessage(AdapterState.BREDR_STOPPED); 1083 } else { 1084 setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_OFF); 1085 } 1086 } else { 1087 // TODO(b/228875190): GATT is assumed supported. If we support no profiles then just 1088 // move on to BREDR_STOPPED 1089 if (supportedProfileServices.length == 1 1090 && (mRunningProfiles.size() == 1 1091 && GattService.class 1092 .getSimpleName() 1093 .equals(mRunningProfiles.get(0).getName()))) { 1094 Log.d( 1095 TAG, 1096 "stopProfileServices() - No profiles services to stop or already stopped."); 1097 mAdapterStateMachine.sendMessage(AdapterState.BREDR_STOPPED); 1098 } else { 1099 setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_OFF); 1100 } 1101 } 1102 } 1103 startGattProfileService()1104 private void startGattProfileService() { 1105 Log.i(TAG, "startGattProfileService() called"); 1106 mGattService = new GattService(this); 1107 1108 mStartedProfiles.put(BluetoothProfile.GATT, mGattService); 1109 addProfile(mGattService); 1110 mGattService.setAvailable(true); 1111 onProfileServiceStateChanged(mGattService, BluetoothAdapter.STATE_ON); 1112 } 1113 startScanController()1114 private void startScanController() { 1115 Log.i(TAG, "startScanController() called"); 1116 mScanController = new ScanController(this); 1117 mNativeInterface.enable(); 1118 } 1119 stopGattProfileService()1120 private void stopGattProfileService() { 1121 Log.i(TAG, "stopGattProfileService() called"); 1122 setScanMode(SCAN_MODE_NONE, "stopGattProfileService"); 1123 1124 if (mRunningProfiles.size() == 0) { 1125 Log.d(TAG, "stopGattProfileService() - No profiles services to stop."); 1126 mAdapterStateMachine.sendMessage(AdapterState.BLE_STOPPED); 1127 } 1128 1129 mStartedProfiles.remove(BluetoothProfile.GATT); 1130 if (mGattService != null) { 1131 mGattService.setAvailable(false); 1132 onProfileServiceStateChanged(mGattService, BluetoothAdapter.STATE_OFF); 1133 removeProfile(mGattService); 1134 mGattService.cleanup(); 1135 mGattService.getBinder().cleanup(); 1136 mGattService = null; 1137 } 1138 } 1139 stopScanController()1140 private void stopScanController() { 1141 Log.i(TAG, "stopScanController() called"); 1142 setScanMode(SCAN_MODE_NONE, "stopScanController"); 1143 1144 if (mScanController == null) { 1145 mAdapterStateMachine.sendMessage(AdapterState.BLE_STOPPED); 1146 } else { 1147 mScanController.cleanup(); 1148 mScanController = null; 1149 mNativeInterface.disable(); 1150 } 1151 } 1152 updateLeAudioProfileServiceState()1153 void updateLeAudioProfileServiceState() { 1154 Set<Integer> nonSupportedProfiles = new HashSet<>(); 1155 1156 if (!isLeConnectedIsochronousStreamCentralSupported()) { 1157 for (int profileId : Config.getLeAudioUnicastProfiles()) { 1158 nonSupportedProfiles.add(profileId); 1159 } 1160 } 1161 1162 if (!isLeAudioBroadcastAssistantSupported()) { 1163 nonSupportedProfiles.add(BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT); 1164 } 1165 1166 if (!isLeAudioBroadcastSourceSupported()) { 1167 Config.setProfileEnabled(BluetoothProfile.LE_AUDIO_BROADCAST, false); 1168 } 1169 1170 // Disable the non-supported profiles service 1171 for (int profileId : nonSupportedProfiles) { 1172 Config.setProfileEnabled(profileId, false); 1173 if (mStartedProfiles.containsKey(profileId)) { 1174 setProfileServiceState(profileId, BluetoothAdapter.STATE_OFF); 1175 } 1176 } 1177 } 1178 broadcastToSystemServerCallbacks( String logAction, RemoteExceptionIgnoringConsumer<IBluetoothCallback> action)1179 private void broadcastToSystemServerCallbacks( 1180 String logAction, RemoteExceptionIgnoringConsumer<IBluetoothCallback> action) { 1181 final int itemCount = mSystemServerCallbacks.beginBroadcast(); 1182 Log.d(TAG, "Broadcasting [" + logAction + "] to " + itemCount + " receivers."); 1183 for (int i = 0; i < itemCount; i++) { 1184 action.accept(mSystemServerCallbacks.getBroadcastItem(i)); 1185 } 1186 mSystemServerCallbacks.finishBroadcast(); 1187 } 1188 updateAdapterName(String name)1189 void updateAdapterName(String name) { 1190 broadcastToSystemServerCallbacks( 1191 "updateAdapterName(" + name + ")", (c) -> c.onAdapterNameChange(name)); 1192 } 1193 updateAdapterAddress(String address)1194 void updateAdapterAddress(String address) { 1195 broadcastToSystemServerCallbacks( 1196 "updateAdapterAddress(" + BluetoothUtils.toAnonymizedAddress(address) + ")", 1197 (c) -> c.onAdapterAddressChange(address)); 1198 } 1199 updateAdapterState(int from, int to)1200 void updateAdapterState(int from, int to) { 1201 mAdapterProperties.setState(to); 1202 1203 broadcastToSystemServerCallbacks( 1204 "updateAdapterState(" + nameForState(from) + ", " + nameForState(to) + ")", 1205 (c) -> c.onBluetoothStateChange(from, to)); 1206 1207 for (Map.Entry<BluetoothStateCallback, Executor> e : mLocalCallbacks.entrySet()) { 1208 e.getValue().execute(() -> e.getKey().onBluetoothStateChange(from, to)); 1209 } 1210 1211 // Turn the Adapter all the way off if we are disabling and the snoop log setting changed. 1212 if (to == BluetoothAdapter.STATE_BLE_TURNING_ON) { 1213 sSnoopLogSettingAtEnable = 1214 BluetoothProperties.snoop_log_mode() 1215 .orElse(BluetoothProperties.snoop_log_mode_values.EMPTY); 1216 sDefaultSnoopLogSettingAtEnable = 1217 Settings.Global.getString( 1218 getContentResolver(), Settings.Global.BLUETOOTH_BTSNOOP_DEFAULT_MODE); 1219 1220 sSnoopLogFilterHeadersSettingAtEnable = 1221 BluetoothProperties.snoop_log_filter_snoop_headers_enabled().orElse(false); 1222 sSnoopLogFilterProfileA2dpSettingAtEnable = 1223 BluetoothProperties.snoop_log_filter_profile_a2dp_enabled().orElse(false); 1224 sSnoopLogFilterProfileRfcommSettingAtEnable = 1225 BluetoothProperties.snoop_log_filter_profile_rfcomm_enabled().orElse(false); 1226 sSnoopLogFilterProfilePbapModeSettingAtEnable = 1227 BluetoothProperties.snoop_log_filter_profile_pbap() 1228 .orElse(BluetoothProperties.snoop_log_filter_profile_pbap_values.EMPTY); 1229 sSnoopLogFilterProfileMapModeSettingAtEnable = 1230 BluetoothProperties.snoop_log_filter_profile_map() 1231 .orElse(BluetoothProperties.snoop_log_filter_profile_map_values.EMPTY); 1232 1233 if (Utils.isInstrumentationTestMode()) { 1234 return; 1235 } 1236 BluetoothProperties.snoop_default_mode( 1237 BluetoothProperties.snoop_default_mode_values.DISABLED); 1238 for (BluetoothProperties.snoop_default_mode_values value : 1239 BluetoothProperties.snoop_default_mode_values.values()) { 1240 if (value.getPropValue().equals(sDefaultSnoopLogSettingAtEnable)) { 1241 BluetoothProperties.snoop_default_mode(value); 1242 } 1243 } 1244 } else if (to == BluetoothAdapter.STATE_BLE_ON && from != BluetoothAdapter.STATE_OFF) { 1245 var snoopLogSetting = 1246 BluetoothProperties.snoop_log_mode() 1247 .orElse(BluetoothProperties.snoop_log_mode_values.EMPTY); 1248 var snoopDefaultModeSetting = 1249 Settings.Global.getString( 1250 getContentResolver(), Settings.Global.BLUETOOTH_BTSNOOP_DEFAULT_MODE); 1251 1252 var snoopLogFilterHeadersSettingAtEnable = 1253 BluetoothProperties.snoop_log_filter_snoop_headers_enabled().orElse(false); 1254 var snoopLogFilterProfileA2dpSettingAtEnable = 1255 BluetoothProperties.snoop_log_filter_profile_a2dp_enabled().orElse(false); 1256 var snoopLogFilterProfileRfcommSettingAtEnable = 1257 BluetoothProperties.snoop_log_filter_profile_rfcomm_enabled().orElse(false); 1258 1259 var snoopLogFilterProfilePbapModeSetting = 1260 BluetoothProperties.snoop_log_filter_profile_pbap() 1261 .orElse(BluetoothProperties.snoop_log_filter_profile_pbap_values.EMPTY); 1262 var snoopLogFilterProfileMapModeSetting = 1263 BluetoothProperties.snoop_log_filter_profile_map() 1264 .orElse(BluetoothProperties.snoop_log_filter_profile_map_values.EMPTY); 1265 1266 if (!(sSnoopLogSettingAtEnable == snoopLogSetting) 1267 || !(Objects.equals(sDefaultSnoopLogSettingAtEnable, snoopDefaultModeSetting)) 1268 || !(sSnoopLogFilterHeadersSettingAtEnable 1269 == snoopLogFilterHeadersSettingAtEnable) 1270 || !(sSnoopLogFilterProfileA2dpSettingAtEnable 1271 == snoopLogFilterProfileA2dpSettingAtEnable) 1272 || !(sSnoopLogFilterProfileRfcommSettingAtEnable 1273 == snoopLogFilterProfileRfcommSettingAtEnable) 1274 || !(sSnoopLogFilterProfilePbapModeSettingAtEnable 1275 == snoopLogFilterProfilePbapModeSetting) 1276 || !(sSnoopLogFilterProfileMapModeSettingAtEnable 1277 == snoopLogFilterProfileMapModeSetting)) { 1278 mAdapterStateMachine.sendMessage(AdapterState.BLE_TURN_OFF); 1279 } 1280 } 1281 } 1282 linkQualityReportCallback( long timestamp, int reportId, int rssi, int snr, int retransmissionCount, int packetsNotReceiveCount, int negativeAcknowledgementCount)1283 void linkQualityReportCallback( 1284 long timestamp, 1285 int reportId, 1286 int rssi, 1287 int snr, 1288 int retransmissionCount, 1289 int packetsNotReceiveCount, 1290 int negativeAcknowledgementCount) { 1291 BluetoothInCallService bluetoothInCallService = BluetoothInCallService.getInstance(); 1292 1293 if (reportId == BqrQualityReportId.QUALITY_REPORT_ID_SCO_VOICE_CHOPPY.getValue()) { 1294 if (bluetoothInCallService == null) { 1295 Log.w( 1296 TAG, 1297 "No BluetoothInCallService while trying to send BQR." 1298 + (" timestamp: " + timestamp) 1299 + (" reportId: " + reportId) 1300 + (" rssi: " + rssi) 1301 + (" snr: " + snr) 1302 + (" retransmissionCount: " + retransmissionCount) 1303 + (" packetsNotReceiveCount: " + packetsNotReceiveCount) 1304 + (" negativeAcknowledgementCount: " 1305 + negativeAcknowledgementCount)); 1306 return; 1307 } 1308 bluetoothInCallService.sendBluetoothCallQualityReport( 1309 timestamp, 1310 rssi, 1311 snr, 1312 retransmissionCount, 1313 packetsNotReceiveCount, 1314 negativeAcknowledgementCount); 1315 } 1316 } 1317 1318 /** 1319 * Callback from Bluetooth Quality Report Native Interface to inform the listeners about 1320 * Bluetooth Quality. 1321 * 1322 * @param device is the BluetoothDevice which connection quality is being reported 1323 * @param bluetoothQualityReport a Parcel that contains information about Bluetooth Quality 1324 * @return whether the Bluetooth stack acknowledged the change successfully 1325 */ bluetoothQualityReportReadyCallback( BluetoothDevice device, BluetoothQualityReport bluetoothQualityReport)1326 public int bluetoothQualityReportReadyCallback( 1327 BluetoothDevice device, BluetoothQualityReport bluetoothQualityReport) { 1328 synchronized (mBluetoothQualityReportReadyCallbacks) { 1329 int n = mBluetoothQualityReportReadyCallbacks.beginBroadcast(); 1330 Log.d( 1331 TAG, 1332 "bluetoothQualityReportReadyCallback() - " 1333 + "Broadcasting Bluetooth Quality Report to " 1334 + n 1335 + " receivers."); 1336 for (int i = 0; i < n; i++) { 1337 try { 1338 mBluetoothQualityReportReadyCallbacks 1339 .getBroadcastItem(i) 1340 .onBluetoothQualityReportReady( 1341 device, bluetoothQualityReport, BluetoothStatusCodes.SUCCESS); 1342 } catch (RemoteException e) { 1343 Log.d( 1344 TAG, 1345 "bluetoothQualityReportReadyCallback() - Callback #" 1346 + i 1347 + " failed (" 1348 + e 1349 + ")"); 1350 } 1351 } 1352 mBluetoothQualityReportReadyCallbacks.finishBroadcast(); 1353 } 1354 1355 return BluetoothStatusCodes.SUCCESS; 1356 } 1357 switchBufferSizeCallback(boolean isLowLatencyBufferSize)1358 void switchBufferSizeCallback(boolean isLowLatencyBufferSize) { 1359 List<BluetoothDevice> activeDevices = getActiveDevices(BluetoothProfile.A2DP); 1360 if (activeDevices.size() != 1) { 1361 Log.e( 1362 TAG, 1363 "Cannot switch buffer size. The number of A2DP active devices is " 1364 + activeDevices.size()); 1365 return; 1366 } 1367 1368 // Send intent to fastpair 1369 Intent switchBufferSizeIntent = new Intent(BluetoothDevice.ACTION_SWITCH_BUFFER_SIZE); 1370 switchBufferSizeIntent.setClassName( 1371 getString(com.android.bluetooth.R.string.peripheral_link_package), 1372 getString(com.android.bluetooth.R.string.peripheral_link_package) 1373 + getString(com.android.bluetooth.R.string.peripheral_link_service)); 1374 switchBufferSizeIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, activeDevices.get(0)); 1375 switchBufferSizeIntent.putExtra( 1376 BluetoothDevice.EXTRA_LOW_LATENCY_BUFFER_SIZE, isLowLatencyBufferSize); 1377 sendBroadcastMultiplePermissions( 1378 switchBufferSizeIntent, 1379 new String[] {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}, 1380 null); 1381 } 1382 switchCodecCallback(boolean isLowLatencyBufferSize)1383 void switchCodecCallback(boolean isLowLatencyBufferSize) { 1384 List<BluetoothDevice> activeDevices = getActiveDevices(BluetoothProfile.A2DP); 1385 if (activeDevices.size() != 1) { 1386 Log.e( 1387 TAG, 1388 "Cannot switch buffer size. The number of A2DP active devices is " 1389 + activeDevices.size()); 1390 return; 1391 } 1392 mA2dpService.switchCodecByBufferSize(activeDevices.get(0), isLowLatencyBufferSize); 1393 } 1394 1395 @RequiresPermission(BLUETOOTH_CONNECT) cleanup()1396 void cleanup() { 1397 Log.d(TAG, "cleanup()"); 1398 if (mCleaningUp) { 1399 Log.e(TAG, "cleanup() - Service already starting to cleanup, ignoring request..."); 1400 return; 1401 } 1402 1403 MetricsLogger.getInstance().close(); 1404 1405 clearAdapterService(this); 1406 1407 mCleaningUp = true; 1408 invalidateBluetoothCaches(); 1409 1410 stopRfcommServerSockets(); 1411 1412 // This wake lock release may also be called concurrently by 1413 // {@link #releaseWakeLock(String lockName)}, so a synchronization is needed here. 1414 synchronized (this) { 1415 if (mWakeLock != null) { 1416 if (mWakeLock.isHeld()) { 1417 mWakeLock.release(); 1418 } 1419 mWakeLock = null; 1420 } 1421 } 1422 1423 mDatabaseManager.cleanup(); 1424 1425 if (mAdapterStateMachine != null) { 1426 mAdapterStateMachine.doQuit(); 1427 } 1428 1429 if (mBondStateMachine != null) { 1430 mBondStateMachine.doQuit(); 1431 } 1432 1433 if (mRemoteDevices != null) { 1434 mRemoteDevices.reset(); 1435 } 1436 1437 if (mSdpManager != null) { 1438 mSdpManager.cleanup(); 1439 mSdpManager = null; 1440 } 1441 1442 if (mNativeAvailable) { 1443 Log.d(TAG, "cleanup() - Cleaning up adapter native"); 1444 mNativeInterface.cleanup(); 1445 mNativeAvailable = false; 1446 } 1447 1448 if (mAdapterProperties != null) { 1449 mAdapterProperties.cleanup(); 1450 } 1451 1452 if (mNativeInterface.getCallbacks() != null) { 1453 mNativeInterface.getCallbacks().cleanup(); 1454 } 1455 1456 if (mBluetoothKeystoreService != null) { 1457 Log.d(TAG, "cleanup(): mBluetoothKeystoreService.cleanup()"); 1458 mBluetoothKeystoreService.cleanup(); 1459 } 1460 1461 mPhonePolicy.ifPresent(policy -> policy.cleanup()); 1462 1463 mSilenceDeviceManager.cleanup(); 1464 1465 if (mActiveDeviceManager != null) { 1466 mActiveDeviceManager.cleanup(); 1467 } 1468 1469 if (mBluetoothSocketManagerBinder != null) { 1470 mBluetoothSocketManagerBinder.cleanUp(); 1471 mBluetoothSocketManagerBinder = null; 1472 } 1473 1474 if (mAdapterSuspend != null) { 1475 if (Flags.adapterSuspendMgmt() && isAtLeastV()) { 1476 mAdapterSuspend.cleanup(); 1477 } 1478 mAdapterSuspend = null; 1479 } 1480 1481 mPreferredAudioProfilesCallbacks.kill(); 1482 1483 mBluetoothQualityReportReadyCallbacks.kill(); 1484 1485 mBluetoothConnectionCallbacks.kill(); 1486 1487 mSystemServerCallbacks.kill(); 1488 1489 mMetadataListeners.values().forEach(v -> v.kill()); 1490 } 1491 invalidateBluetoothCaches()1492 private static void invalidateBluetoothCaches() { 1493 BluetoothAdapter.invalidateGetProfileConnectionStateCache(); 1494 BluetoothAdapter.invalidateIsOffloadedFilteringSupportedCache(); 1495 BluetoothDevice.invalidateBluetoothGetBondStateCache(); 1496 BluetoothAdapter.invalidateGetAdapterConnectionStateCache(); 1497 BluetoothMap.invalidateBluetoothGetConnectionStateCache(); 1498 BluetoothSap.invalidateBluetoothGetConnectionStateCache(); 1499 } 1500 1501 private static final Map<Integer, Function<AdapterService, ProfileService>> 1502 PROFILE_CONSTRUCTORS = 1503 Map.ofEntries( 1504 Map.entry(BluetoothProfile.A2DP, A2dpService::new), 1505 Map.entry(BluetoothProfile.A2DP_SINK, A2dpSinkService::new), 1506 Map.entry(BluetoothProfile.AVRCP, AvrcpTargetService::new), 1507 Map.entry( 1508 BluetoothProfile.AVRCP_CONTROLLER, AvrcpControllerService::new), 1509 Map.entry( 1510 BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT, 1511 BassClientService::new), 1512 Map.entry(BluetoothProfile.BATTERY, BatteryService::new), 1513 Map.entry( 1514 BluetoothProfile.CSIP_SET_COORDINATOR, 1515 CsipSetCoordinatorService::new), 1516 Map.entry(BluetoothProfile.HAP_CLIENT, HapClientService::new), 1517 Map.entry(BluetoothProfile.HEADSET, HeadsetService::new), 1518 Map.entry(BluetoothProfile.HEADSET_CLIENT, HeadsetClientService::new), 1519 Map.entry(BluetoothProfile.HEARING_AID, HearingAidService::new), 1520 Map.entry(BluetoothProfile.HID_DEVICE, HidDeviceService::new), 1521 Map.entry(BluetoothProfile.HID_HOST, HidHostService::new), 1522 Map.entry(BluetoothProfile.GATT, GattService::new), 1523 Map.entry(BluetoothProfile.LE_AUDIO, LeAudioService::new), 1524 Map.entry(BluetoothProfile.LE_CALL_CONTROL, TbsService::new), 1525 Map.entry(BluetoothProfile.MAP, BluetoothMapService::new), 1526 Map.entry(BluetoothProfile.MAP_CLIENT, MapClientService::new), 1527 Map.entry(BluetoothProfile.MCP_SERVER, McpService::new), 1528 Map.entry(BluetoothProfile.OPP, BluetoothOppService::new), 1529 Map.entry(BluetoothProfile.PAN, PanService::new), 1530 Map.entry(BluetoothProfile.PBAP, BluetoothPbapService::new), 1531 Map.entry(BluetoothProfile.PBAP_CLIENT, PbapClientService::new), 1532 Map.entry(BluetoothProfile.SAP, SapService::new), 1533 Map.entry(BluetoothProfile.VOLUME_CONTROL, VolumeControlService::new)); 1534 1535 @VisibleForTesting setProfileServiceState(int profileId, int state)1536 void setProfileServiceState(int profileId, int state) { 1537 Instant start = Instant.now(); 1538 String logHdr = "setProfileServiceState(" + getProfileName(profileId) + ", " + state + "):"; 1539 1540 if (state == BluetoothAdapter.STATE_ON) { 1541 if (mStartedProfiles.containsKey(profileId)) { 1542 Log.wtf(TAG, logHdr + " profile is already started"); 1543 return; 1544 } 1545 Log.i(TAG, logHdr + " starting profile"); 1546 ProfileService profileService = PROFILE_CONSTRUCTORS.get(profileId).apply(this); 1547 mStartedProfiles.put(profileId, profileService); 1548 addProfile(profileService); 1549 profileService.setAvailable(true); 1550 // With `Flags.onlyStartScanDuringBleOn()` GattService initialization is pushed back to 1551 // `ON` state instead of `BLE_ON`. Here we ensure mGattService is set prior 1552 // to other Profiles using it. 1553 if (profileId == BluetoothProfile.GATT && Flags.onlyStartScanDuringBleOn()) { 1554 mGattService = GattService.getGattService(); 1555 } 1556 onProfileServiceStateChanged(profileService, BluetoothAdapter.STATE_ON); 1557 } else if (state == BluetoothAdapter.STATE_OFF) { 1558 ProfileService profileService = mStartedProfiles.remove(profileId); 1559 if (profileService == null) { 1560 Log.wtf(TAG, logHdr + " profile is already stopped"); 1561 return; 1562 } 1563 Log.i(TAG, logHdr + " stopping profile"); 1564 profileService.setAvailable(false); 1565 onProfileServiceStateChanged(profileService, BluetoothAdapter.STATE_OFF); 1566 removeProfile(profileService); 1567 profileService.cleanup(); 1568 if (profileService.getBinder() != null) { 1569 profileService.getBinder().cleanup(); 1570 } 1571 } 1572 Instant end = Instant.now(); 1573 Log.i(TAG, logHdr + " completed in " + Duration.between(start, end).toMillis() + "ms"); 1574 } 1575 setAllProfileServiceStates(int[] profileIds, int state)1576 private void setAllProfileServiceStates(int[] profileIds, int state) { 1577 for (int profileId : profileIds) { 1578 if (!Flags.onlyStartScanDuringBleOn()) { 1579 // TODO(b/228875190): GATT is assumed supported and treated differently as part of 1580 // the "BLE ON" state, despite GATT not being BLE specific. 1581 if (profileId == BluetoothProfile.GATT) { 1582 continue; 1583 } 1584 } 1585 setProfileServiceState(profileId, state); 1586 } 1587 } 1588 1589 /** 1590 * Checks whether the remote device is a dual mode audio sink device (supports both classic and 1591 * LE Audio sink roles. 1592 * 1593 * @param device the remote device 1594 * @return {@code true} if it's a dual mode audio device, {@code false} otherwise 1595 */ isDualModeAudioSinkDevice(BluetoothDevice device)1596 public boolean isDualModeAudioSinkDevice(BluetoothDevice device) { 1597 if (mLeAudioService == null 1598 || mLeAudioService.getGroupId(device) == LE_AUDIO_GROUP_ID_INVALID) { 1599 return false; 1600 } 1601 1602 // Check if any device in the CSIP group is a dual mode audio sink device 1603 for (BluetoothDevice groupDevice : 1604 mLeAudioService.getGroupDevices(mLeAudioService.getGroupId(device))) { 1605 if (isProfileSupported(groupDevice, BluetoothProfile.LE_AUDIO) 1606 && (isProfileSupported(groupDevice, BluetoothProfile.HEADSET) 1607 || isProfileSupported(groupDevice, BluetoothProfile.A2DP))) { 1608 return true; 1609 } 1610 } 1611 return false; 1612 } 1613 1614 /** 1615 * Checks whether the local and remote device support a connection for duplex audio (input and 1616 * output) over HFP or LE Audio. 1617 * 1618 * @param groupDevices the devices in the CSIP group 1619 * @return {@code true} if duplex is supported on the remote device, {@code false} otherwise 1620 */ isDuplexAudioSupported(List<BluetoothDevice> groupDevices)1621 private boolean isDuplexAudioSupported(List<BluetoothDevice> groupDevices) { 1622 for (BluetoothDevice device : groupDevices) { 1623 if (isProfileSupported(device, BluetoothProfile.HEADSET) 1624 || (isProfileSupported(device, BluetoothProfile.LE_AUDIO) 1625 && mLeAudioService != null 1626 && mLeAudioService.isLeAudioDuplexSupported(device))) { 1627 return true; 1628 } 1629 } 1630 return false; 1631 } 1632 1633 /** 1634 * Checks whether the local and remote device support a connection for output only audio over 1635 * A2DP or LE Audio. 1636 * 1637 * @param groupDevices the devices in the CSIP group 1638 * @return {@code true} if output only is supported, {@code false} otherwise 1639 */ isOutputOnlyAudioSupported(List<BluetoothDevice> groupDevices)1640 private boolean isOutputOnlyAudioSupported(List<BluetoothDevice> groupDevices) { 1641 for (BluetoothDevice device : groupDevices) { 1642 if (isProfileSupported(device, BluetoothProfile.A2DP) 1643 || (isProfileSupported(device, BluetoothProfile.LE_AUDIO) 1644 && mLeAudioService != null 1645 && mLeAudioService.isLeAudioOutputSupported(device))) { 1646 return true; 1647 } 1648 } 1649 return false; 1650 } 1651 1652 /** 1653 * Verifies whether the profile is supported by the local bluetooth adapter by checking a 1654 * bitmask of its supported profiles 1655 * 1656 * @param device is the remote device we wish to connect to 1657 * @param profile is the profile we are checking for support 1658 * @return true if the profile is supported by both the local and remote device, false otherwise 1659 */ 1660 @VisibleForTesting isProfileSupported(BluetoothDevice device, int profile)1661 boolean isProfileSupported(BluetoothDevice device, int profile) { 1662 final ParcelUuid[] remoteDeviceUuids = getRemoteUuids(device); 1663 final ParcelUuid[] localDeviceUuids = mAdapterProperties.getUuids(); 1664 if (remoteDeviceUuids == null || remoteDeviceUuids.length == 0) { 1665 Log.e( 1666 TAG, 1667 "isProfileSupported(" 1668 + ("device=" + device) 1669 + (", profile=" + BluetoothProfile.getProfileName(profile) + "):") 1670 + " remote device Uuids Empty"); 1671 } 1672 1673 Log.v( 1674 TAG, 1675 "isProfileSupported(" 1676 + ("device=" + device) 1677 + (", profile=" + BluetoothProfile.getProfileName(profile) + "):") 1678 + (" local_uuids=" + Arrays.toString(localDeviceUuids)) 1679 + (", remote_uuids=" + Arrays.toString(remoteDeviceUuids))); 1680 1681 if (profile == BluetoothProfile.HEADSET) { 1682 return (Utils.arrayContains(localDeviceUuids, BluetoothUuid.HSP_AG) 1683 && Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HSP)) 1684 || (Utils.arrayContains(localDeviceUuids, BluetoothUuid.HFP_AG) 1685 && Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HFP)); 1686 } 1687 if (profile == BluetoothProfile.HEADSET_CLIENT) { 1688 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HFP_AG) 1689 && Utils.arrayContains(localDeviceUuids, BluetoothUuid.HFP); 1690 } 1691 if (profile == BluetoothProfile.A2DP) { 1692 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.ADV_AUDIO_DIST) 1693 || Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.A2DP_SINK); 1694 } 1695 if (profile == BluetoothProfile.A2DP_SINK) { 1696 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.ADV_AUDIO_DIST) 1697 || Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.A2DP_SOURCE); 1698 } 1699 if (profile == BluetoothProfile.OPP) { 1700 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.OBEX_OBJECT_PUSH); 1701 } 1702 if (profile == BluetoothProfile.HID_HOST) { 1703 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HID) 1704 || Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HOGP) 1705 || Utils.arrayContains( 1706 remoteDeviceUuids, HidHostService.ANDROID_HEADTRACKER_UUID); 1707 } 1708 if (profile == BluetoothProfile.HID_DEVICE) { 1709 return mHidDeviceService.getConnectionState(device) == STATE_DISCONNECTED; 1710 } 1711 if (profile == BluetoothProfile.PAN) { 1712 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.NAP); 1713 } 1714 if (profile == BluetoothProfile.MAP) { 1715 return mMapService.getConnectionState(device) == STATE_CONNECTED; 1716 } 1717 if (profile == BluetoothProfile.PBAP) { 1718 return mPbapService.getConnectionState(device) == STATE_CONNECTED; 1719 } 1720 if (profile == BluetoothProfile.MAP_CLIENT) { 1721 return Utils.arrayContains(localDeviceUuids, BluetoothUuid.MNS) 1722 && Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.MAS); 1723 } 1724 if (profile == BluetoothProfile.PBAP_CLIENT) { 1725 return Utils.arrayContains(localDeviceUuids, BluetoothUuid.PBAP_PCE) 1726 && Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.PBAP_PSE); 1727 } 1728 if (profile == BluetoothProfile.HEARING_AID) { 1729 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HEARING_AID); 1730 } 1731 if (profile == BluetoothProfile.SAP) { 1732 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.SAP); 1733 } 1734 if (profile == BluetoothProfile.VOLUME_CONTROL) { 1735 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.VOLUME_CONTROL); 1736 } 1737 if (profile == BluetoothProfile.CSIP_SET_COORDINATOR) { 1738 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.COORDINATED_SET); 1739 } 1740 if (profile == BluetoothProfile.LE_AUDIO) { 1741 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.LE_AUDIO); 1742 } 1743 if (profile == BluetoothProfile.HAP_CLIENT) { 1744 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HAS); 1745 } 1746 if (profile == BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT) { 1747 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.BASS); 1748 } 1749 if (profile == BluetoothProfile.BATTERY) { 1750 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.BATTERY); 1751 } 1752 1753 Log.e(TAG, "isSupported: Unexpected profile passed in to function: " + profile); 1754 return false; 1755 } 1756 1757 /** 1758 * Checks if the connection policy of all profiles are unknown for the given device 1759 * 1760 * @param device is the device for which we are checking if the connection policy of all 1761 * profiles are unknown 1762 * @return false if one of profile is enabled or disabled, true otherwise 1763 */ isAllProfilesUnknown(BluetoothDevice device)1764 boolean isAllProfilesUnknown(BluetoothDevice device) { 1765 if (mHeadsetService != null 1766 && mHeadsetService.getConnectionPolicy(device) != CONNECTION_POLICY_UNKNOWN) { 1767 return false; 1768 } 1769 if (mHeadsetClientService != null 1770 && mHeadsetClientService.getConnectionPolicy(device) != CONNECTION_POLICY_UNKNOWN) { 1771 return false; 1772 } 1773 if (mA2dpService != null 1774 && mA2dpService.getConnectionPolicy(device) != CONNECTION_POLICY_UNKNOWN) { 1775 return false; 1776 } 1777 if (mA2dpSinkService != null 1778 && mA2dpSinkService.getConnectionPolicy(device) != CONNECTION_POLICY_UNKNOWN) { 1779 return false; 1780 } 1781 if (mMapClientService != null 1782 && mMapClientService.getConnectionPolicy(device) != CONNECTION_POLICY_UNKNOWN) { 1783 return false; 1784 } 1785 if (mHidHostService != null 1786 && mHidHostService.getConnectionPolicy(device) != CONNECTION_POLICY_UNKNOWN) { 1787 return false; 1788 } 1789 if (mPanService != null 1790 && mPanService.getConnectionPolicy(device) != CONNECTION_POLICY_UNKNOWN) { 1791 return false; 1792 } 1793 if (mPbapClientService != null 1794 && mPbapClientService.getConnectionPolicy(device) != CONNECTION_POLICY_UNKNOWN) { 1795 return false; 1796 } 1797 if (mHearingAidService != null 1798 && mHearingAidService.getConnectionPolicy(device) != CONNECTION_POLICY_UNKNOWN) { 1799 return false; 1800 } 1801 if (mHapClientService != null 1802 && mHapClientService.getConnectionPolicy(device) != CONNECTION_POLICY_UNKNOWN) { 1803 return false; 1804 } 1805 if (mVolumeControlService != null 1806 && mVolumeControlService.getConnectionPolicy(device) != CONNECTION_POLICY_UNKNOWN) { 1807 return false; 1808 } 1809 if (mCsipSetCoordinatorService != null 1810 && mCsipSetCoordinatorService.getConnectionPolicy(device) 1811 != CONNECTION_POLICY_UNKNOWN) { 1812 return false; 1813 } 1814 if (mLeAudioService != null 1815 && mLeAudioService.getConnectionPolicy(device) != CONNECTION_POLICY_UNKNOWN) { 1816 return false; 1817 } 1818 if (mBassClientService != null 1819 && mBassClientService.getConnectionPolicy(device) != CONNECTION_POLICY_UNKNOWN) { 1820 return false; 1821 } 1822 return true; 1823 } 1824 1825 /** 1826 * Connects only available profiles (those with {@link 1827 * BluetoothProfile#CONNECTION_POLICY_ALLOWED}) 1828 * 1829 * @param device is the device with which we are connecting the profiles 1830 * @return {@link BluetoothStatusCodes#SUCCESS} 1831 */ connectEnabledProfiles(BluetoothDevice device)1832 private int connectEnabledProfiles(BluetoothDevice device) { 1833 if (mCsipSetCoordinatorService != null 1834 && isProfileSupported(device, BluetoothProfile.CSIP_SET_COORDINATOR) 1835 && mCsipSetCoordinatorService.getConnectionPolicy(device) 1836 > CONNECTION_POLICY_FORBIDDEN) { 1837 Log.i(TAG, "connectEnabledProfiles: Connecting Coordinated Set Profile"); 1838 mCsipSetCoordinatorService.connect(device); 1839 } 1840 // Order matters, some devices do not accept A2DP connection before HFP connection 1841 if (mHeadsetService != null 1842 && isProfileSupported(device, BluetoothProfile.HEADSET) 1843 && mHeadsetService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN) { 1844 Log.i(TAG, "connectEnabledProfiles: Connecting Headset Profile"); 1845 mHeadsetService.connect(device); 1846 } 1847 if (mHeadsetClientService != null 1848 && isProfileSupported(device, BluetoothProfile.HEADSET_CLIENT) 1849 && mHeadsetClientService.getConnectionPolicy(device) 1850 > CONNECTION_POLICY_FORBIDDEN) { 1851 Log.i(TAG, "connectEnabledProfiles: Connecting HFP"); 1852 mHeadsetClientService.connect(device); 1853 } 1854 if (mA2dpService != null 1855 && isProfileSupported(device, BluetoothProfile.A2DP) 1856 && mA2dpService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN) { 1857 Log.i(TAG, "connectEnabledProfiles: Connecting A2dp"); 1858 mA2dpService.connect(device); 1859 } 1860 if (mA2dpSinkService != null 1861 && isProfileSupported(device, BluetoothProfile.A2DP_SINK) 1862 && mA2dpSinkService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN) { 1863 Log.i(TAG, "connectEnabledProfiles: Connecting A2dp Sink"); 1864 mA2dpSinkService.connect(device); 1865 } 1866 if (mMapClientService != null 1867 && isProfileSupported(device, BluetoothProfile.MAP_CLIENT) 1868 && mMapClientService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN) { 1869 Log.i(TAG, "connectEnabledProfiles: Connecting MAP"); 1870 mMapClientService.connect(device); 1871 } 1872 if (mHidHostService != null 1873 && isProfileSupported(device, BluetoothProfile.HID_HOST) 1874 && mHidHostService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN) { 1875 Log.i(TAG, "connectEnabledProfiles: Connecting Hid Host Profile"); 1876 mHidHostService.connect(device); 1877 } 1878 if (mPanService != null 1879 && isProfileSupported(device, BluetoothProfile.PAN) 1880 && mPanService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN) { 1881 Log.i(TAG, "connectEnabledProfiles: Connecting Pan Profile"); 1882 mPanService.connect(device); 1883 } 1884 if (mPbapClientService != null 1885 && isProfileSupported(device, BluetoothProfile.PBAP_CLIENT) 1886 && mPbapClientService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN) { 1887 Log.i(TAG, "connectEnabledProfiles: Connecting Pbap"); 1888 mPbapClientService.connect(device); 1889 } 1890 if (mHearingAidService != null 1891 && isProfileSupported(device, BluetoothProfile.HEARING_AID) 1892 && mHearingAidService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN) { 1893 Log.i(TAG, "connectEnabledProfiles: Connecting Hearing Aid Profile"); 1894 mHearingAidService.connect(device); 1895 } 1896 if (mHapClientService != null 1897 && isProfileSupported(device, BluetoothProfile.HAP_CLIENT) 1898 && mHapClientService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN) { 1899 Log.i(TAG, "connectEnabledProfiles: Connecting HAS Profile"); 1900 mHapClientService.connect(device); 1901 } 1902 if (mVolumeControlService != null 1903 && isProfileSupported(device, BluetoothProfile.VOLUME_CONTROL) 1904 && mVolumeControlService.getConnectionPolicy(device) 1905 > CONNECTION_POLICY_FORBIDDEN) { 1906 Log.i(TAG, "connectEnabledProfiles: Connecting Volume Control Profile"); 1907 mVolumeControlService.connect(device); 1908 } 1909 if (mLeAudioService != null 1910 && isProfileSupported(device, BluetoothProfile.LE_AUDIO) 1911 && mLeAudioService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN) { 1912 Log.i(TAG, "connectEnabledProfiles: Connecting LeAudio profile (BAP)"); 1913 mLeAudioService.connect(device); 1914 } 1915 if (mBassClientService != null 1916 && isProfileSupported(device, BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT) 1917 && mBassClientService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN) { 1918 Log.i(TAG, "connectEnabledProfiles: Connecting LE Broadcast Assistant Profile"); 1919 mBassClientService.connect(device); 1920 } 1921 if (mBatteryService != null 1922 && isProfileSupported(device, BluetoothProfile.BATTERY) 1923 && mBatteryService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN) { 1924 Log.i(TAG, "connectEnabledProfiles: Connecting Battery Service"); 1925 mBatteryService.connect(device); 1926 } 1927 return BluetoothStatusCodes.SUCCESS; 1928 } 1929 1930 /** 1931 * Verifies that all bluetooth profile services are running 1932 * 1933 * @return true if all bluetooth profile services running, false otherwise 1934 */ profileServicesRunning()1935 private boolean profileServicesRunning() { 1936 if (mRegisteredProfiles.size() == Config.getSupportedProfiles().length 1937 && mRegisteredProfiles.size() == mRunningProfiles.size()) { 1938 return true; 1939 } 1940 1941 Log.e(TAG, "profileServicesRunning: One or more supported services not running"); 1942 return false; 1943 } 1944 1945 /** Initializes all the profile services fields */ initProfileServices()1946 private void initProfileServices() { 1947 Log.i(TAG, "initProfileServices: Initializing all bluetooth profile services"); 1948 mHeadsetService = HeadsetService.getHeadsetService(); 1949 mHeadsetClientService = HeadsetClientService.getHeadsetClientService(); 1950 mA2dpService = A2dpService.getA2dpService(); 1951 mA2dpSinkService = A2dpSinkService.getA2dpSinkService(); 1952 mMapService = BluetoothMapService.getBluetoothMapService(); 1953 mMapClientService = MapClientService.getMapClientService(); 1954 mHidDeviceService = HidDeviceService.getHidDeviceService(); 1955 mHidHostService = HidHostService.getHidHostService(); 1956 mPanService = PanService.getPanService(); 1957 mPbapService = BluetoothPbapService.getBluetoothPbapService(); 1958 mPbapClientService = PbapClientService.getPbapClientService(); 1959 mHearingAidService = HearingAidService.getHearingAidService(); 1960 mHapClientService = HapClientService.getHapClientService(); 1961 mSapService = SapService.getSapService(); 1962 mVolumeControlService = VolumeControlService.getVolumeControlService(); 1963 mCsipSetCoordinatorService = CsipSetCoordinatorService.getCsipSetCoordinatorService(); 1964 mLeAudioService = LeAudioService.getLeAudioService(); 1965 mBassClientService = BassClientService.getBassClientService(); 1966 mBatteryService = BatteryService.getBatteryService(); 1967 } 1968 1969 @BluetoothAdapter.RfcommListenerResult 1970 @RequiresPermission(BLUETOOTH_CONNECT) startRfcommListener( String name, ParcelUuid uuid, PendingIntent pendingIntent, AttributionSource source)1971 int startRfcommListener( 1972 String name, ParcelUuid uuid, PendingIntent pendingIntent, AttributionSource source) { 1973 if (mBluetoothServerSockets.containsKey(uuid.getUuid())) { 1974 Log.d(TAG, "Cannot start RFCOMM listener: UUID " + uuid.getUuid() + "already in use."); 1975 return BluetoothStatusCodes.RFCOMM_LISTENER_START_FAILED_UUID_IN_USE; 1976 } 1977 1978 try { 1979 startRfcommListenerInternal(name, uuid.getUuid(), pendingIntent, source); 1980 } catch (IOException e) { 1981 return BluetoothStatusCodes.RFCOMM_LISTENER_FAILED_TO_CREATE_SERVER_SOCKET; 1982 } 1983 1984 return BluetoothStatusCodes.SUCCESS; 1985 } 1986 1987 @BluetoothAdapter.RfcommListenerResult stopRfcommListener(ParcelUuid uuid, AttributionSource source)1988 int stopRfcommListener(ParcelUuid uuid, AttributionSource source) { 1989 RfcommListenerData listenerData = mBluetoothServerSockets.get(uuid.getUuid()); 1990 1991 if (listenerData == null) { 1992 Log.d(TAG, "Cannot stop RFCOMM listener: UUID " + uuid.getUuid() + "is not registered"); 1993 return BluetoothStatusCodes.RFCOMM_LISTENER_OPERATION_FAILED_NO_MATCHING_SERVICE_RECORD; 1994 } 1995 1996 if (source.getUid() != listenerData.source.getUid()) { 1997 return BluetoothStatusCodes.RFCOMM_LISTENER_OPERATION_FAILED_DIFFERENT_APP; 1998 } 1999 2000 // Remove the entry so that it does not try and restart the server socket. 2001 mBluetoothServerSockets.remove(uuid.getUuid()); 2002 2003 return listenerData.closeServerAndPendingSockets(mHandler); 2004 } 2005 retrievePendingSocketForServiceRecord( ParcelUuid uuid, AttributionSource source)2006 IncomingRfcommSocketInfo retrievePendingSocketForServiceRecord( 2007 ParcelUuid uuid, AttributionSource source) { 2008 IncomingRfcommSocketInfo socketInfo = new IncomingRfcommSocketInfo(); 2009 2010 RfcommListenerData listenerData = mBluetoothServerSockets.get(uuid.getUuid()); 2011 2012 if (listenerData == null) { 2013 socketInfo.status = 2014 BluetoothStatusCodes 2015 .RFCOMM_LISTENER_OPERATION_FAILED_NO_MATCHING_SERVICE_RECORD; 2016 return socketInfo; 2017 } 2018 2019 if (source.getUid() != listenerData.source.getUid()) { 2020 socketInfo.status = BluetoothStatusCodes.RFCOMM_LISTENER_OPERATION_FAILED_DIFFERENT_APP; 2021 return socketInfo; 2022 } 2023 2024 BluetoothSocket socket = listenerData.pendingSockets.poll(); 2025 2026 if (socket == null) { 2027 socketInfo.status = BluetoothStatusCodes.RFCOMM_LISTENER_NO_SOCKET_AVAILABLE; 2028 return socketInfo; 2029 } 2030 2031 mHandler.removeCallbacksAndMessages(socket); 2032 2033 socketInfo.bluetoothDevice = socket.getRemoteDevice(); 2034 socketInfo.pfd = socket.getParcelFileDescriptor(); 2035 socketInfo.status = BluetoothStatusCodes.SUCCESS; 2036 2037 return socketInfo; 2038 } 2039 2040 @RequiresPermission(BLUETOOTH_CONNECT) handleIncomingRfcommConnections(UUID uuid)2041 private void handleIncomingRfcommConnections(UUID uuid) { 2042 RfcommListenerData listenerData = mBluetoothServerSockets.get(uuid); 2043 while (true) { 2044 BluetoothSocket socket; 2045 try { 2046 socket = listenerData.serverSocket.accept(); 2047 } catch (IOException e) { 2048 if (mBluetoothServerSockets.containsKey(uuid)) { 2049 // The uuid still being in the map indicates that the accept failure is 2050 // unexpected. Try and restart the listener. 2051 Log.e(TAG, "Failed to accept socket on " + listenerData.serverSocket, e); 2052 restartRfcommListener(listenerData, uuid); 2053 } 2054 return; 2055 } 2056 2057 listenerData.pendingSockets.add(socket); 2058 try { 2059 listenerData.pendingIntent.send(); 2060 } catch (PendingIntent.CanceledException e) { 2061 Log.e(TAG, "PendingIntent for RFCOMM socket notifications cancelled.", e); 2062 // The pending intent was cancelled, close the server as there is no longer any way 2063 // to notify the app that registered the listener. 2064 listenerData.closeServerAndPendingSockets(mHandler); 2065 mBluetoothServerSockets.remove(uuid); 2066 return; 2067 } 2068 mHandler.postDelayed( 2069 () -> pendingSocketTimeoutRunnable(listenerData, socket), 2070 socket, 2071 PENDING_SOCKET_HANDOFF_TIMEOUT.toMillis()); 2072 } 2073 } 2074 2075 // Tries to restart the rfcomm listener for the given UUID 2076 @RequiresPermission(BLUETOOTH_CONNECT) restartRfcommListener(RfcommListenerData listenerData, UUID uuid)2077 private void restartRfcommListener(RfcommListenerData listenerData, UUID uuid) { 2078 listenerData.closeServerAndPendingSockets(mHandler); 2079 try { 2080 startRfcommListenerInternal( 2081 listenerData.name, uuid, listenerData.pendingIntent, listenerData.source); 2082 } catch (IOException e) { 2083 Log.e(TAG, "Failed to recreate rfcomm server socket", e); 2084 2085 mBluetoothServerSockets.remove(uuid); 2086 } 2087 } 2088 pendingSocketTimeoutRunnable( RfcommListenerData listenerData, BluetoothSocket socket)2089 private static void pendingSocketTimeoutRunnable( 2090 RfcommListenerData listenerData, BluetoothSocket socket) { 2091 boolean socketFound = listenerData.pendingSockets.remove(socket); 2092 if (socketFound) { 2093 try { 2094 socket.close(); 2095 } catch (IOException e) { 2096 Log.e(TAG, "Failed to close bt socket", e); 2097 // We don't care if closing the socket failed, just continue on. 2098 } 2099 } 2100 } 2101 2102 @RequiresPermission(BLUETOOTH_CONNECT) startRfcommListenerInternal( String name, UUID uuid, PendingIntent intent, AttributionSource source)2103 private void startRfcommListenerInternal( 2104 String name, UUID uuid, PendingIntent intent, AttributionSource source) 2105 throws IOException { 2106 BluetoothServerSocket bluetoothServerSocket = 2107 mAdapter.listenUsingRfcommWithServiceRecord(name, uuid); 2108 2109 RfcommListenerData listenerData = 2110 new RfcommListenerData( 2111 bluetoothServerSocket, name, intent, source, new ConcurrentLinkedQueue<>()); 2112 2113 mBluetoothServerSockets.put(uuid, listenerData); 2114 2115 new Thread(() -> handleIncomingRfcommConnections(uuid)).start(); 2116 } 2117 stopRfcommServerSockets()2118 private void stopRfcommServerSockets() { 2119 Iterator<Map.Entry<UUID, RfcommListenerData>> socketsIterator = 2120 mBluetoothServerSockets.entrySet().iterator(); 2121 while (socketsIterator.hasNext()) { 2122 socketsIterator.next().getValue().closeServerAndPendingSockets(mHandler); 2123 socketsIterator.remove(); 2124 } 2125 } 2126 RfcommListenerData( BluetoothServerSocket serverSocket, String name, PendingIntent pendingIntent, AttributionSource source, ConcurrentLinkedQueue<BluetoothSocket> pendingSockets)2127 private record RfcommListenerData( 2128 BluetoothServerSocket serverSocket, 2129 // Service record name 2130 String name, 2131 // Contains the Service info to which the incoming socket connections are handed off to 2132 PendingIntent pendingIntent, 2133 // AttributionSource for the requester of the RFCOMM listener 2134 AttributionSource source, 2135 // Contains the connected sockets which are pending transfer to the app which requested 2136 // the listener. 2137 ConcurrentLinkedQueue<BluetoothSocket> pendingSockets) { 2138 2139 int closeServerAndPendingSockets(Handler handler) { 2140 int result = BluetoothStatusCodes.SUCCESS; 2141 try { 2142 serverSocket.close(); 2143 } catch (IOException e) { 2144 Log.e(TAG, "Failed to call close on rfcomm server socket", e); 2145 result = BluetoothStatusCodes.RFCOMM_LISTENER_FAILED_TO_CLOSE_SERVER_SOCKET; 2146 } 2147 pendingSockets.forEach( 2148 pendingSocket -> { 2149 handler.removeCallbacksAndMessages(pendingSocket); 2150 try { 2151 pendingSocket.close(); 2152 } catch (IOException e) { 2153 Log.e(TAG, "Failed to close socket", e); 2154 } 2155 }); 2156 pendingSockets.clear(); 2157 return result; 2158 } 2159 } 2160 isAvailable()2161 boolean isAvailable() { 2162 return !mCleaningUp; 2163 } 2164 2165 /** 2166 * Set metadata value for the given device and key 2167 * 2168 * @return true if metadata is set successfully 2169 */ setMetadata(BluetoothDevice device, int key, byte[] value)2170 public boolean setMetadata(BluetoothDevice device, int key, byte[] value) { 2171 if (value == null || value.length > BluetoothDevice.METADATA_MAX_LENGTH) { 2172 return false; 2173 } 2174 return mDatabaseManager.setCustomMeta(device, key, value); 2175 } 2176 2177 /** 2178 * Get metadata of given device and key 2179 * 2180 * @return value of given device and key combination 2181 */ getMetadata(BluetoothDevice device, int key)2182 public byte[] getMetadata(BluetoothDevice device, int key) { 2183 return mDatabaseManager.getCustomMeta(device, key); 2184 } 2185 2186 /** Update Adapter Properties when BT profiles connection state changes. */ updateProfileConnectionAdapterProperties( BluetoothDevice device, int profile, int state, int prevState)2187 public void updateProfileConnectionAdapterProperties( 2188 BluetoothDevice device, int profile, int state, int prevState) { 2189 mHandler.post( 2190 () -> 2191 mAdapterProperties.updateOnProfileConnectionChanged( 2192 device, profile, state, prevState)); 2193 } 2194 2195 /** 2196 * Gets the preferred audio profiles for the device. See {@link 2197 * BluetoothAdapter#getPreferredAudioProfiles(BluetoothDevice)} for more details. 2198 * 2199 * @param device is the remote device whose preferences we want to fetch 2200 * @return a Bundle containing the preferred audio profiles for the device 2201 */ getPreferredAudioProfiles(BluetoothDevice device)2202 public Bundle getPreferredAudioProfiles(BluetoothDevice device) { 2203 if (!isDualModeAudioEnabled() 2204 || mLeAudioService == null 2205 || !isDualModeAudioSinkDevice(device)) { 2206 return Bundle.EMPTY; 2207 } 2208 // Checks if the device is part of an LE Audio group 2209 List<BluetoothDevice> groupDevices = mLeAudioService.getGroupDevices(device); 2210 if (groupDevices.isEmpty()) { 2211 return Bundle.EMPTY; 2212 } 2213 2214 // If there are no preferences stored, return the defaults 2215 Bundle storedBundle = Bundle.EMPTY; 2216 for (BluetoothDevice groupDevice : groupDevices) { 2217 Bundle groupDevicePreferences = mDatabaseManager.getPreferredAudioProfiles(groupDevice); 2218 if (!groupDevicePreferences.isEmpty()) { 2219 storedBundle = groupDevicePreferences; 2220 break; 2221 } 2222 } 2223 2224 if (storedBundle.isEmpty()) { 2225 Bundle defaultPreferencesBundle = new Bundle(); 2226 boolean useDefaultPreferences = false; 2227 if (isOutputOnlyAudioSupported(groupDevices)) { 2228 // Gets the default output only audio profile or defaults to LE_AUDIO if not present 2229 int outputOnlyDefault = 2230 BluetoothProperties.getDefaultOutputOnlyAudioProfile() 2231 .orElse(BluetoothProfile.LE_AUDIO); 2232 if (outputOnlyDefault != BluetoothProfile.A2DP 2233 && outputOnlyDefault != BluetoothProfile.LE_AUDIO) { 2234 outputOnlyDefault = BluetoothProfile.LE_AUDIO; 2235 } 2236 defaultPreferencesBundle.putInt( 2237 BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY, outputOnlyDefault); 2238 useDefaultPreferences = true; 2239 } 2240 if (isDuplexAudioSupported(groupDevices)) { 2241 // Gets the default duplex audio profile or defaults to LE_AUDIO if not present 2242 int duplexDefault = 2243 BluetoothProperties.getDefaultDuplexAudioProfile() 2244 .orElse(BluetoothProfile.LE_AUDIO); 2245 if (duplexDefault != BluetoothProfile.HEADSET 2246 && duplexDefault != BluetoothProfile.LE_AUDIO) { 2247 duplexDefault = BluetoothProfile.LE_AUDIO; 2248 } 2249 defaultPreferencesBundle.putInt(BluetoothAdapter.AUDIO_MODE_DUPLEX, duplexDefault); 2250 useDefaultPreferences = true; 2251 } 2252 2253 if (useDefaultPreferences) { 2254 return defaultPreferencesBundle; 2255 } 2256 } 2257 return storedBundle; 2258 } 2259 2260 /** 2261 * Sets the preferred audio profiles for the device. See {@link 2262 * BluetoothAdapter#setPreferredAudioProfiles(BluetoothDevice, Bundle)} for more details. 2263 * 2264 * @param device is the remote device whose preferences we want to fetch 2265 * @param modeToProfileBundle is the preferences we want to set for the device 2266 * @return whether the preferences were successfully requested 2267 */ setPreferredAudioProfiles(BluetoothDevice device, Bundle modeToProfileBundle)2268 int setPreferredAudioProfiles(BluetoothDevice device, Bundle modeToProfileBundle) { 2269 Log.i(TAG, "setPreferredAudioProfiles for device=" + device); 2270 if (!isDualModeAudioEnabled()) { 2271 Log.e(TAG, "setPreferredAudioProfiles called while sysprop is disabled"); 2272 return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED; 2273 } 2274 if (mLeAudioService == null) { 2275 Log.e(TAG, "setPreferredAudioProfiles: LEA service is not up"); 2276 return BluetoothStatusCodes.ERROR_PROFILE_NOT_CONNECTED; 2277 } 2278 if (!isDualModeAudioSinkDevice(device)) { 2279 Log.e(TAG, "setPreferredAudioProfiles: Not a dual mode audio device"); 2280 return BluetoothStatusCodes.ERROR_NOT_DUAL_MODE_AUDIO_DEVICE; 2281 } 2282 // Checks if the device is part of an LE Audio group 2283 int groupId = mLeAudioService.getGroupId(device); 2284 List<BluetoothDevice> groupDevices = mLeAudioService.getGroupDevices(groupId); 2285 if (groupDevices.isEmpty()) { 2286 return BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED; 2287 } 2288 2289 // Copies relevant keys & values from modeToProfile bundle 2290 Bundle strippedPreferences = new Bundle(); 2291 if (modeToProfileBundle.containsKey(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY) 2292 && isOutputOnlyAudioSupported(groupDevices)) { 2293 int outputOnlyProfile = 2294 modeToProfileBundle.getInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY); 2295 if (outputOnlyProfile != BluetoothProfile.A2DP 2296 && outputOnlyProfile != BluetoothProfile.LE_AUDIO) { 2297 throw new IllegalArgumentException( 2298 "AUDIO_MODE_OUTPUT_ONLY has invalid value: " + outputOnlyProfile); 2299 } 2300 strippedPreferences.putInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY, outputOnlyProfile); 2301 } 2302 if (modeToProfileBundle.containsKey(BluetoothAdapter.AUDIO_MODE_DUPLEX) 2303 && isDuplexAudioSupported(groupDevices)) { 2304 int duplexProfile = modeToProfileBundle.getInt(BluetoothAdapter.AUDIO_MODE_DUPLEX); 2305 if (duplexProfile != BluetoothProfile.HEADSET 2306 && duplexProfile != BluetoothProfile.LE_AUDIO) { 2307 throw new IllegalArgumentException( 2308 "AUDIO_MODE_DUPLEX has invalid value: " + duplexProfile); 2309 } 2310 strippedPreferences.putInt(BluetoothAdapter.AUDIO_MODE_DUPLEX, duplexProfile); 2311 } 2312 2313 synchronized (mCsipGroupsPendingAudioProfileChanges) { 2314 if (mCsipGroupsPendingAudioProfileChanges.containsKey(groupId)) { 2315 return BluetoothStatusCodes.ERROR_ANOTHER_ACTIVE_REQUEST; 2316 } 2317 2318 Bundle previousPreferences = getPreferredAudioProfiles(device); 2319 2320 int dbResult = 2321 mDatabaseManager.setPreferredAudioProfiles(groupDevices, strippedPreferences); 2322 if (dbResult != BluetoothStatusCodes.SUCCESS) { 2323 return dbResult; 2324 } 2325 2326 int outputOnlyPreference = 2327 strippedPreferences.getInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY); 2328 if (outputOnlyPreference == 0) { 2329 outputOnlyPreference = 2330 previousPreferences.getInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY); 2331 } 2332 int duplexPreference = strippedPreferences.getInt(BluetoothAdapter.AUDIO_MODE_DUPLEX); 2333 if (duplexPreference == 0) { 2334 duplexPreference = previousPreferences.getInt(BluetoothAdapter.AUDIO_MODE_DUPLEX); 2335 } 2336 2337 mLeAudioService.sendAudioProfilePreferencesToNative( 2338 groupId, 2339 outputOnlyPreference == BluetoothProfile.LE_AUDIO, 2340 duplexPreference == BluetoothProfile.LE_AUDIO); 2341 2342 /* Populates the HashMap to hold requests on the groupId. We will update 2343 numRequestsToAudioFramework after we make requests to the audio framework */ 2344 PendingAudioProfilePreferenceRequest holdRequest = 2345 new PendingAudioProfilePreferenceRequest(strippedPreferences, 0, device); 2346 mCsipGroupsPendingAudioProfileChanges.put(groupId, holdRequest); 2347 2348 // Notifies audio framework via the handler thread to avoid this blocking calls 2349 mHandler.post( 2350 () -> 2351 sendPreferredAudioProfileChangeToAudioFramework( 2352 device, strippedPreferences, previousPreferences)); 2353 return BluetoothStatusCodes.SUCCESS; 2354 } 2355 } 2356 2357 /** 2358 * Sends the updated preferred audio profiles to the audio framework. 2359 * 2360 * @param device is the device with updated audio preferences 2361 * @param strippedPreferences is a {@link Bundle} containing the preferences 2362 */ sendPreferredAudioProfileChangeToAudioFramework( BluetoothDevice device, Bundle strippedPreferences, Bundle previousPreferences)2363 private void sendPreferredAudioProfileChangeToAudioFramework( 2364 BluetoothDevice device, Bundle strippedPreferences, Bundle previousPreferences) { 2365 int newOutput = strippedPreferences.getInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY); 2366 int newDuplex = strippedPreferences.getInt(BluetoothAdapter.AUDIO_MODE_DUPLEX); 2367 int previousOutput = previousPreferences.getInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY); 2368 int previousDuplex = previousPreferences.getInt(BluetoothAdapter.AUDIO_MODE_DUPLEX); 2369 2370 Log.i( 2371 TAG, 2372 "sendPreferredAudioProfileChangeToAudioFramework: changing output from " 2373 + BluetoothProfile.getProfileName(previousOutput) 2374 + " to " 2375 + BluetoothProfile.getProfileName(newOutput) 2376 + " and duplex from " 2377 + BluetoothProfile.getProfileName(previousDuplex) 2378 + " to " 2379 + BluetoothProfile.getProfileName(newDuplex)); 2380 2381 // If no change from existing preferences, do not inform audio framework 2382 if (previousOutput == newOutput && previousDuplex == newDuplex) { 2383 Log.i(TAG, "No change to preferred audio profiles, no requests to Audio FW"); 2384 sendPreferredAudioProfilesCallbackToApps( 2385 device, strippedPreferences, BluetoothStatusCodes.SUCCESS); 2386 return; 2387 } 2388 2389 int numRequestsToAudioFw = 0; 2390 2391 // Checks if the device is part of an LE Audio group 2392 int groupId = mLeAudioService.getGroupId(device); 2393 List<BluetoothDevice> groupDevices = mLeAudioService.getGroupDevices(groupId); 2394 if (groupDevices.isEmpty()) { 2395 Log.i( 2396 TAG, 2397 "sendPreferredAudioProfileChangeToAudioFramework: Empty LEA group for " 2398 + "device - " 2399 + device); 2400 sendPreferredAudioProfilesCallbackToApps( 2401 device, strippedPreferences, BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED); 2402 return; 2403 } 2404 2405 synchronized (mCsipGroupsPendingAudioProfileChanges) { 2406 if (previousOutput != newOutput) { 2407 if (newOutput == BluetoothProfile.A2DP 2408 && mA2dpService.getActiveDevice() != null 2409 && groupDevices.contains(mA2dpService.getActiveDevice())) { 2410 Log.i(TAG, "Sent change for AUDIO_MODE_OUTPUT_ONLY to A2DP to Audio FW"); 2411 numRequestsToAudioFw += 2412 mA2dpService.sendPreferredAudioProfileChangeToAudioFramework(); 2413 } else if (newOutput == BluetoothProfile.LE_AUDIO 2414 && mLeAudioService.getActiveGroupId() == groupId) { 2415 Log.i(TAG, "Sent change for AUDIO_MODE_OUTPUT_ONLY to LE_AUDIO to Audio FW"); 2416 numRequestsToAudioFw += 2417 mLeAudioService.sendPreferredAudioProfileChangeToAudioFramework(); 2418 } 2419 } 2420 2421 if (previousDuplex != newDuplex) { 2422 if (newDuplex == BluetoothProfile.HEADSET 2423 && mHeadsetService.getActiveDevice() != null 2424 && groupDevices.contains(mHeadsetService.getActiveDevice())) { 2425 Log.i(TAG, "Sent change for AUDIO_MODE_DUPLEX to HFP to Audio FW"); 2426 // TODO(b/275426145): Add similar HFP method in BluetoothProfileConnectionInfo 2427 numRequestsToAudioFw += 2428 mA2dpService.sendPreferredAudioProfileChangeToAudioFramework(); 2429 } else if (newDuplex == BluetoothProfile.LE_AUDIO 2430 && mLeAudioService.getActiveGroupId() == groupId) { 2431 Log.i(TAG, "Sent change for AUDIO_MODE_DUPLEX to LE_AUDIO to Audio FW"); 2432 numRequestsToAudioFw += 2433 mLeAudioService.sendPreferredAudioProfileChangeToAudioFramework(); 2434 } 2435 } 2436 2437 Log.i( 2438 TAG, 2439 "sendPreferredAudioProfileChangeToAudioFramework: sent " 2440 + numRequestsToAudioFw 2441 + " request(s) to the Audio Framework for device: " 2442 + device); 2443 2444 if (numRequestsToAudioFw > 0) { 2445 mCsipGroupsPendingAudioProfileChanges.put( 2446 groupId, 2447 new PendingAudioProfilePreferenceRequest( 2448 strippedPreferences, numRequestsToAudioFw, device)); 2449 2450 Message m = 2451 mHandler.obtainMessage( 2452 MESSAGE_PREFERRED_AUDIO_PROFILES_AUDIO_FRAMEWORK_TIMEOUT); 2453 m.obj = groupId; 2454 mHandler.sendMessageDelayed(m, PREFERRED_AUDIO_PROFILE_CHANGE_TIMEOUT.toMillis()); 2455 return; 2456 } 2457 } 2458 sendPreferredAudioProfilesCallbackToApps( 2459 device, strippedPreferences, BluetoothStatusCodes.SUCCESS); 2460 } 2461 removeFromPendingAudioProfileChanges(int groupId)2462 private void removeFromPendingAudioProfileChanges(int groupId) { 2463 synchronized (mCsipGroupsPendingAudioProfileChanges) { 2464 Log.i( 2465 TAG, 2466 "removeFromPendingAudioProfileChanges: Timeout on change for groupId=" 2467 + groupId); 2468 if (!mCsipGroupsPendingAudioProfileChanges.containsKey(groupId)) { 2469 Log.e( 2470 TAG, 2471 "removeFromPendingAudioProfileChanges( " 2472 + groupId 2473 + ", " 2474 + groupId 2475 + ") is not pending"); 2476 return; 2477 } 2478 } 2479 } 2480 2481 /** 2482 * Notification from the audio framework that an active device change has taken effect. See 2483 * {@link BluetoothAdapter#notifyActiveDeviceChangeApplied(BluetoothDevice)} for more details. 2484 * 2485 * @param device the remote device whose preferred audio profiles have been changed 2486 * @return whether the Bluetooth stack acknowledged the change successfully 2487 */ notifyActiveDeviceChangeApplied(BluetoothDevice device)2488 int notifyActiveDeviceChangeApplied(BluetoothDevice device) { 2489 if (mLeAudioService == null) { 2490 Log.e(TAG, "LE Audio profile not enabled"); 2491 return BluetoothStatusCodes.ERROR_PROFILE_NOT_CONNECTED; 2492 } 2493 2494 int groupId = mLeAudioService.getGroupId(device); 2495 if (groupId == LE_AUDIO_GROUP_ID_INVALID) { 2496 return BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED; 2497 } 2498 2499 synchronized (mCsipGroupsPendingAudioProfileChanges) { 2500 if (!mCsipGroupsPendingAudioProfileChanges.containsKey(groupId)) { 2501 Log.e( 2502 TAG, 2503 "notifyActiveDeviceChangeApplied, but no pending request for " 2504 + "groupId: " 2505 + groupId); 2506 return BluetoothStatusCodes.ERROR_UNKNOWN; 2507 } 2508 2509 PendingAudioProfilePreferenceRequest pendingRequest = 2510 mCsipGroupsPendingAudioProfileChanges.get(groupId); 2511 2512 // If this is the final audio framework request, send callback to apps 2513 if (pendingRequest.numberOfRemainingRequestsToAudioFramework == 1) { 2514 Log.i( 2515 TAG, 2516 "notifyActiveDeviceChangeApplied: Complete for device " 2517 + pendingRequest.device); 2518 sendPreferredAudioProfilesCallbackToApps( 2519 pendingRequest.device, 2520 pendingRequest.preferences, 2521 BluetoothStatusCodes.SUCCESS); 2522 // Removes the timeout from the handler 2523 mHandler.removeMessages( 2524 MESSAGE_PREFERRED_AUDIO_PROFILES_AUDIO_FRAMEWORK_TIMEOUT, groupId); 2525 } else if (pendingRequest.numberOfRemainingRequestsToAudioFramework > 1) { 2526 PendingAudioProfilePreferenceRequest updatedPendingRequest = 2527 new PendingAudioProfilePreferenceRequest( 2528 pendingRequest.preferences, 2529 pendingRequest.numberOfRemainingRequestsToAudioFramework - 1, 2530 pendingRequest.device); 2531 Log.i( 2532 TAG, 2533 "notifyActiveDeviceChangeApplied: Updating device " 2534 + updatedPendingRequest.device 2535 + " with new remaining requests count=" 2536 + updatedPendingRequest.numberOfRemainingRequestsToAudioFramework); 2537 mCsipGroupsPendingAudioProfileChanges.put(groupId, updatedPendingRequest); 2538 } else { 2539 Log.i( 2540 TAG, 2541 "notifyActiveDeviceChangeApplied: " 2542 + pendingRequest.device 2543 + " has no remaining requests to audio framework, but is still" 2544 + " present in mCsipGroupsPendingAudioProfileChanges"); 2545 } 2546 } 2547 2548 return BluetoothStatusCodes.SUCCESS; 2549 } 2550 sendPreferredAudioProfilesCallbackToApps( BluetoothDevice device, Bundle preferredAudioProfiles, int status)2551 private void sendPreferredAudioProfilesCallbackToApps( 2552 BluetoothDevice device, Bundle preferredAudioProfiles, int status) { 2553 int n = mPreferredAudioProfilesCallbacks.beginBroadcast(); 2554 Log.d( 2555 TAG, 2556 "sendPreferredAudioProfilesCallbackToApps() - Broadcasting audio profile " 2557 + ("change callback to device: " + device) 2558 + (" and status=" + status) 2559 + (" to " + n + " receivers.")); 2560 for (int i = 0; i < n; i++) { 2561 try { 2562 mPreferredAudioProfilesCallbacks 2563 .getBroadcastItem(i) 2564 .onPreferredAudioProfilesChanged(device, preferredAudioProfiles, status); 2565 } catch (RemoteException e) { 2566 Log.d( 2567 TAG, 2568 "sendPreferredAudioProfilesCallbackToApps() - Callback #" 2569 + i 2570 + " failed (" 2571 + e 2572 + ")"); 2573 } 2574 } 2575 mPreferredAudioProfilesCallbacks.finishBroadcast(); 2576 } 2577 2578 // ----API Methods-------- 2579 isEnabled()2580 public boolean isEnabled() { 2581 return getState() == BluetoothAdapter.STATE_ON; 2582 } 2583 getState()2584 public int getState() { 2585 if (mAdapterProperties != null) { 2586 return mAdapterProperties.getState(); 2587 } 2588 return BluetoothAdapter.STATE_OFF; 2589 } 2590 offToBleOn(boolean quietMode)2591 public synchronized void offToBleOn(boolean quietMode) { 2592 // Enforce the user restriction for disallowing Bluetooth if it was set. 2593 if (mUserManager.hasUserRestrictionForUser( 2594 UserManager.DISALLOW_BLUETOOTH, UserHandle.SYSTEM)) { 2595 Log.d(TAG, "offToBleOn() called when Bluetooth was disallowed"); 2596 return; 2597 } 2598 // The call to init must be done on the main thread 2599 mHandler.post(() -> init()); 2600 2601 Log.i(TAG, "offToBleOn() - Enable called with quiet mode status = " + quietMode); 2602 mQuietmode = quietMode; 2603 mAdapterStateMachine.sendMessage(AdapterState.BLE_TURN_ON); 2604 } 2605 onToBleOn()2606 void onToBleOn() { 2607 Log.d(TAG, "onToBleOn() called with mRunningProfiles.size() = " + mRunningProfiles.size()); 2608 mAdapterStateMachine.sendMessage(AdapterState.USER_TURN_OFF); 2609 } 2610 disconnectAllAcls()2611 void disconnectAllAcls() { 2612 Log.d(TAG, "disconnectAllAcls()"); 2613 mNativeInterface.disconnectAllAcls(); 2614 } 2615 getName()2616 public String getName() { 2617 return mAdapterProperties.getName(); 2618 } 2619 getNameLengthForAdvertise()2620 public int getNameLengthForAdvertise() { 2621 return mAdapterProperties.getName().length(); 2622 } 2623 getDiscoveringPackages()2624 List<DiscoveringPackage> getDiscoveringPackages() { 2625 return mDiscoveringPackages; 2626 } 2627 clearDiscoveringPackages()2628 void clearDiscoveringPackages() { 2629 synchronized (mDiscoveringPackages) { 2630 mDiscoveringPackages.clear(); 2631 } 2632 } 2633 startDiscovery(AttributionSource source)2634 boolean startDiscovery(AttributionSource source) { 2635 UserHandle callingUser = Binder.getCallingUserHandle(); 2636 Log.d(TAG, "startDiscovery"); 2637 String callingPackage = source.getPackageName(); 2638 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); 2639 boolean isQApp = Utils.checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.Q); 2640 boolean hasDisavowedLocation = 2641 Utils.hasDisavowedLocationForScan(this, source, mTestModeEnabled); 2642 String permission = null; 2643 if (Utils.checkCallerHasNetworkSettingsPermission(this)) { 2644 permission = android.Manifest.permission.NETWORK_SETTINGS; 2645 } else if (Utils.checkCallerHasNetworkSetupWizardPermission(this)) { 2646 permission = android.Manifest.permission.NETWORK_SETUP_WIZARD; 2647 } else if (!hasDisavowedLocation) { 2648 if (isQApp) { 2649 if (!Utils.checkCallerHasFineLocation(this, source, callingUser)) { 2650 return false; 2651 } 2652 permission = android.Manifest.permission.ACCESS_FINE_LOCATION; 2653 } else { 2654 if (!Utils.checkCallerHasCoarseLocation(this, source, callingUser)) { 2655 return false; 2656 } 2657 permission = android.Manifest.permission.ACCESS_COARSE_LOCATION; 2658 } 2659 } 2660 2661 synchronized (mDiscoveringPackages) { 2662 mDiscoveringPackages.add( 2663 new DiscoveringPackage(callingPackage, permission, hasDisavowedLocation)); 2664 } 2665 return mNativeInterface.startDiscovery(); 2666 } 2667 2668 /** 2669 * Same as API method {@link BluetoothAdapter#getBondedDevices()} 2670 * 2671 * @return array of bonded {@link BluetoothDevice} or null on error 2672 */ getBondedDevices()2673 public BluetoothDevice[] getBondedDevices() { 2674 return mAdapterProperties.getBondedDevices(); 2675 } 2676 2677 /** 2678 * Get the database manager to access Bluetooth storage 2679 * 2680 * @return {@link DatabaseManager} or null on error 2681 */ getDatabase()2682 public DatabaseManager getDatabase() { 2683 return mDatabaseManager; 2684 } 2685 getByteIdentityAddress(BluetoothDevice device)2686 public byte[] getByteIdentityAddress(BluetoothDevice device) { 2687 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 2688 if (deviceProp != null && deviceProp.getIdentityAddress() != null) { 2689 return Utils.getBytesFromAddress(deviceProp.getIdentityAddress()); 2690 } 2691 2692 // Return null if identity address unknown 2693 return null; 2694 } 2695 getDeviceFromByte(byte[] address)2696 public BluetoothDevice getDeviceFromByte(byte[] address) { 2697 BluetoothDevice device = mRemoteDevices.getDevice(address); 2698 if (device == null) { 2699 device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address); 2700 } 2701 return device; 2702 } 2703 getIdentityAddress(String address)2704 public String getIdentityAddress(String address) { 2705 BluetoothDevice device = 2706 BluetoothAdapter.getDefaultAdapter() 2707 .getRemoteDevice(address.toUpperCase(Locale.ROOT)); 2708 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 2709 if (deviceProp != null && deviceProp.getIdentityAddress() != null) { 2710 return deviceProp.getIdentityAddress(); 2711 } 2712 // Return null if identity address unknown 2713 return null; 2714 } 2715 2716 /** 2717 * Returns the identity address and identity address type. 2718 * 2719 * @param address of remote device 2720 * @return a {@link BluetoothDevice.BluetoothAddress} containing identity address and identity 2721 * address type 2722 */ 2723 @NonNull getIdentityAddressWithType(@onNull String address)2724 public BluetoothAddress getIdentityAddressWithType(@NonNull String address) { 2725 BluetoothDevice device = 2726 BluetoothAdapter.getDefaultAdapter() 2727 .getRemoteDevice(address.toUpperCase(Locale.ROOT)); 2728 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 2729 2730 String identityAddress = null; 2731 int identityAddressType = BluetoothDevice.ADDRESS_TYPE_UNKNOWN; 2732 2733 if (deviceProp != null) { 2734 if (deviceProp.getIdentityAddress() != null) { 2735 identityAddress = deviceProp.getIdentityAddress(); 2736 } 2737 identityAddressType = deviceProp.getIdentityAddressType(); 2738 } else { 2739 identityAddress = null; 2740 } 2741 2742 return new BluetoothAddress(identityAddress, identityAddressType); 2743 } 2744 addAssociatedPackage(BluetoothDevice device, String packageName)2745 public boolean addAssociatedPackage(BluetoothDevice device, String packageName) { 2746 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 2747 if (deviceProp == null) { 2748 return false; 2749 } 2750 deviceProp.addPackage(packageName); 2751 return true; 2752 } 2753 CallerInfo(String callerPackageName, UserHandle user)2754 private record CallerInfo(String callerPackageName, UserHandle user) {} 2755 createBond( BluetoothDevice device, int transport, OobData remoteP192Data, OobData remoteP256Data, String callingPackage)2756 boolean createBond( 2757 BluetoothDevice device, 2758 int transport, 2759 OobData remoteP192Data, 2760 OobData remoteP256Data, 2761 String callingPackage) { 2762 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 2763 if (deviceProp != null && deviceProp.getBondState() != BluetoothDevice.BOND_NONE) { 2764 // true for BONDING, false for BONDED 2765 return deviceProp.getBondState() == BluetoothDevice.BOND_BONDING; 2766 } 2767 2768 if (!isEnabled()) { 2769 Log.e(TAG, "Impossible to call createBond when Bluetooth is not enabled"); 2770 return false; 2771 } 2772 2773 if (!isPackageNameAccurate(this, callingPackage, Binder.getCallingUid())) { 2774 return false; 2775 } 2776 2777 CallerInfo createBondCaller = new CallerInfo(callingPackage, Binder.getCallingUserHandle()); 2778 mBondAttemptCallerInfo.put(device.getAddress(), createBondCaller); 2779 2780 mRemoteDevices.setBondingInitiatedLocally(Utils.getByteAddress(device)); 2781 2782 // Pairing is unreliable while scanning, so cancel discovery 2783 // Note, remove this when native stack improves 2784 mNativeInterface.cancelDiscovery(); 2785 2786 Message msg = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND); 2787 msg.obj = device; 2788 msg.arg1 = transport; 2789 2790 Bundle remoteOobDatasBundle = new Bundle(); 2791 boolean setData = false; 2792 if (remoteP192Data != null) { 2793 remoteOobDatasBundle.putParcelable(BondStateMachine.OOBDATAP192, remoteP192Data); 2794 setData = true; 2795 } 2796 if (remoteP256Data != null) { 2797 remoteOobDatasBundle.putParcelable(BondStateMachine.OOBDATAP256, remoteP256Data); 2798 setData = true; 2799 } 2800 if (setData) { 2801 msg.setData(remoteOobDatasBundle); 2802 } else { 2803 MetricsLogger.getInstance() 2804 .logBluetoothEvent( 2805 device, 2806 BluetoothStatsLog 2807 .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__BONDING, 2808 BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__START, 2809 Binder.getCallingUid()); 2810 } 2811 mBondStateMachine.sendMessage(msg); 2812 return true; 2813 } 2814 2815 /** 2816 * Fetches the local OOB data to give out to remote. 2817 * 2818 * @param transport - specify data transport. 2819 * @param callback - callback used to receive the requested {@link OobData}; null will be 2820 * ignored silently. 2821 */ generateLocalOobData( int transport, IBluetoothOobDataCallback callback)2822 public synchronized void generateLocalOobData( 2823 int transport, IBluetoothOobDataCallback callback) { 2824 if (callback == null) { 2825 Log.e(TAG, "'callback' argument must not be null!"); 2826 return; 2827 } 2828 if (mOobDataCallbackQueue.peek() != null) { 2829 try { 2830 callback.onError(BluetoothStatusCodes.ERROR_ANOTHER_ACTIVE_OOB_REQUEST); 2831 } catch (RemoteException e) { 2832 Log.e(TAG, "Failed to make callback", e); 2833 } 2834 return; 2835 } 2836 mOobDataCallbackQueue.offer(callback); 2837 mHandler.postDelayed( 2838 () -> removeFromOobDataCallbackQueue(callback), 2839 GENERATE_LOCAL_OOB_DATA_TIMEOUT.toMillis()); 2840 mNativeInterface.generateLocalOobData(transport); 2841 } 2842 removeFromOobDataCallbackQueue(IBluetoothOobDataCallback callback)2843 private synchronized void removeFromOobDataCallbackQueue(IBluetoothOobDataCallback callback) { 2844 if (callback == null) { 2845 return; 2846 } 2847 2848 if (mOobDataCallbackQueue.peek() == callback) { 2849 try { 2850 mOobDataCallbackQueue.poll().onError(BluetoothStatusCodes.ERROR_UNKNOWN); 2851 } catch (RemoteException e) { 2852 Log.e(TAG, "Failed to make OobDataCallback to remove callback from queue", e); 2853 } 2854 } 2855 } 2856 notifyOobDataCallback(int transport, OobData oobData)2857 /* package */ synchronized void notifyOobDataCallback(int transport, OobData oobData) { 2858 if (mOobDataCallbackQueue.peek() == null) { 2859 Log.e(TAG, "Failed to make callback, no callback exists"); 2860 return; 2861 } 2862 if (oobData == null) { 2863 try { 2864 mOobDataCallbackQueue.poll().onError(BluetoothStatusCodes.ERROR_UNKNOWN); 2865 } catch (RemoteException e) { 2866 Log.e(TAG, "Failed to make callback", e); 2867 } 2868 } else { 2869 try { 2870 mOobDataCallbackQueue.poll().onOobData(transport, oobData); 2871 } catch (RemoteException e) { 2872 Log.e(TAG, "Failed to make callback", e); 2873 } 2874 } 2875 } 2876 isQuietModeEnabled()2877 public boolean isQuietModeEnabled() { 2878 Log.d(TAG, "isQuietModeEnabled() - Enabled = " + mQuietmode); 2879 return mQuietmode; 2880 } 2881 updateUuids()2882 public void updateUuids() { 2883 Log.d(TAG, "updateUuids() - Updating UUIDs for bonded devices"); 2884 BluetoothDevice[] bondedDevices = getBondedDevices(); 2885 if (bondedDevices == null) { 2886 return; 2887 } 2888 2889 for (BluetoothDevice device : bondedDevices) { 2890 mRemoteDevices.updateUuids(device); 2891 } 2892 } 2893 2894 /** 2895 * Update device UUID changed to {@link BondStateMachine} 2896 * 2897 * @param device remote device of interest 2898 */ deviceUuidUpdated(BluetoothDevice device)2899 public void deviceUuidUpdated(BluetoothDevice device) { 2900 // Notify BondStateMachine for SDP complete / UUID changed. 2901 Message msg = mBondStateMachine.obtainMessage(BondStateMachine.UUID_UPDATE); 2902 msg.obj = device; 2903 mBondStateMachine.sendMessage(msg); 2904 } 2905 2906 /** 2907 * Get the bond state of a particular {@link BluetoothDevice} 2908 * 2909 * @param device remote device of interest 2910 * @return bond state 2911 * <p>Possible values are {@link BluetoothDevice#BOND_NONE}, {@link 2912 * BluetoothDevice#BOND_BONDING}, {@link BluetoothDevice#BOND_BONDED}. 2913 */ getBondState(BluetoothDevice device)2914 public int getBondState(BluetoothDevice device) { 2915 return mRemoteDevices.getBondState(device); 2916 } 2917 isConnected(BluetoothDevice device)2918 public boolean isConnected(BluetoothDevice device) { 2919 return getConnectionState(device) != BluetoothDevice.CONNECTION_STATE_DISCONNECTED; 2920 } 2921 addGattClientToControlAutoActiveMode(int clientIf, BluetoothDevice device)2922 private void addGattClientToControlAutoActiveMode(int clientIf, BluetoothDevice device) { 2923 if (!Flags.allowGattConnectFromTheAppsWithoutMakingLeaudioDeviceActive()) { 2924 Log.i( 2925 TAG, 2926 "flag: allowGattConnectFromTheAppsWithoutMakingLeaudioDeviceActive is not" 2927 + " enabled"); 2928 return; 2929 } 2930 2931 /* When GATT client is connecting to LeAudio device, stack should not assume that 2932 * LeAudio device should be automatically connected to Audio Framework. 2933 * e.g. given LeAudio device might be busy with audio streaming from another device. 2934 * LeAudio shall be automatically connected to Audio Framework when 2935 * 1. Remote device expects that - Targeted Announcements are used 2936 * 2. User is connecting device from Settings application. 2937 * 2938 * Above conditions are tracked by LeAudioService. In here, there is need to notify 2939 * LeAudioService that connection is made for GATT purposes, so LeAudioService can 2940 * disable AutoActiveMode and make sure to not make device Active just after connection 2941 * is created. 2942 * 2943 * Note: AutoActiveMode is by default set to true and it means that LeAudio device is ready 2944 * to streaming just after connection is created. That implies that device will be connected 2945 * to Audio Framework (is made Active) when connection is created. 2946 */ 2947 2948 int groupId = mLeAudioService.getGroupId(device); 2949 if (groupId == BluetoothLeAudio.GROUP_ID_INVALID) { 2950 /* If this is not a LeAudio device, there is nothing to do here. */ 2951 return; 2952 } 2953 2954 if (mLeAudioService.getConnectionPolicy(device) != CONNECTION_POLICY_ALLOWED) { 2955 Log.d( 2956 TAG, 2957 "addGattClientToControlAutoActiveMode: " 2958 + device 2959 + " LeAudio connection policy is not allowed"); 2960 return; 2961 } 2962 2963 Log.i( 2964 TAG, 2965 "addGattClientToControlAutoActiveMode: clientIf: " 2966 + clientIf 2967 + ", " 2968 + device 2969 + ", groupId: " 2970 + groupId); 2971 2972 synchronized (mLeGattClientsControllingAutoActiveMode) { 2973 Pair newPair = new Pair<>(clientIf, device); 2974 if (mLeGattClientsControllingAutoActiveMode.contains(newPair)) { 2975 return; 2976 } 2977 2978 for (Pair<Integer, BluetoothDevice> pair : mLeGattClientsControllingAutoActiveMode) { 2979 if (pair.second.equals(device) 2980 || groupId == mLeAudioService.getGroupId(pair.second)) { 2981 Log.i(TAG, "addGattClientToControlAutoActiveMode: adding new client"); 2982 mLeGattClientsControllingAutoActiveMode.add(newPair); 2983 return; 2984 } 2985 } 2986 2987 if (mLeAudioService.setAutoActiveModeState(mLeAudioService.getGroupId(device), false)) { 2988 Log.i( 2989 TAG, 2990 "addGattClientToControlAutoActiveMode: adding new client and notifying" 2991 + " leAudioService"); 2992 mLeGattClientsControllingAutoActiveMode.add(newPair); 2993 } 2994 } 2995 } 2996 2997 /** 2998 * When this is called, AdapterService is aware of user doing GATT connection over LE. Adapter 2999 * service will use this information to manage internal GATT services if needed. For now, 3000 * AdapterService is using this information to control Auto Active Mode for LeAudio devices. 3001 * 3002 * @param clientIf clientIf ClientIf which was doing GATT connection attempt 3003 * @param device device Remote device to connect 3004 */ notifyDirectLeGattClientConnect(int clientIf, BluetoothDevice device)3005 public void notifyDirectLeGattClientConnect(int clientIf, BluetoothDevice device) { 3006 if (mLeAudioService != null) { 3007 addGattClientToControlAutoActiveMode(clientIf, device); 3008 } 3009 } 3010 removeGattClientFromControlAutoActiveMode(int clientIf, BluetoothDevice device)3011 private void removeGattClientFromControlAutoActiveMode(int clientIf, BluetoothDevice device) { 3012 if (mLeGattClientsControllingAutoActiveMode.isEmpty()) { 3013 return; 3014 } 3015 3016 int groupId = mLeAudioService.getGroupId(device); 3017 if (groupId == BluetoothLeAudio.GROUP_ID_INVALID) { 3018 /* If this is not a LeAudio device, there is nothing to do here. */ 3019 return; 3020 } 3021 3022 /* Remember if auto active mode is still disabled. 3023 * If it is disabled, it means, that either User or remote device did not make an 3024 * action to make LeAudio device Active. 3025 * That means, AdapterService should disconnect ACL when all the clients are disconnected 3026 * from the group to which the device belongs. 3027 */ 3028 boolean isAutoActiveModeDisabled = !mLeAudioService.isAutoActiveModeEnabled(groupId); 3029 3030 synchronized (mLeGattClientsControllingAutoActiveMode) { 3031 Log.d( 3032 TAG, 3033 "removeGattClientFromControlAutoActiveMode: removing clientIf:" 3034 + clientIf 3035 + ", " 3036 + device 3037 + ", groupId: " 3038 + groupId); 3039 3040 mLeGattClientsControllingAutoActiveMode.remove(new Pair<>(clientIf, device)); 3041 3042 if (!mLeGattClientsControllingAutoActiveMode.isEmpty()) { 3043 for (Pair<Integer, BluetoothDevice> pair : 3044 mLeGattClientsControllingAutoActiveMode) { 3045 if (pair.second.equals(device) 3046 || groupId == mLeAudioService.getGroupId(pair.second)) { 3047 Log.d( 3048 TAG, 3049 "removeGattClientFromControlAutoActiveMode:" 3050 + device 3051 + " or groupId: " 3052 + groupId 3053 + " is still in use by clientif: " 3054 + pair.first); 3055 return; 3056 } 3057 } 3058 } 3059 3060 /* Back auto active mode to default. */ 3061 mLeAudioService.setAutoActiveModeState(groupId, true); 3062 } 3063 3064 int leConnectedState = 3065 BluetoothDevice.CONNECTION_STATE_ENCRYPTED_LE 3066 | BluetoothDevice.CONNECTION_STATE_CONNECTED; 3067 3068 /* If auto active mode was disabled for the given group and is still connected 3069 * make sure to disconnected all the devices from the group 3070 */ 3071 if (isAutoActiveModeDisabled && ((getConnectionState(device) & leConnectedState) != 0)) { 3072 for (BluetoothDevice dev : mLeAudioService.getGroupDevices(groupId)) { 3073 /* Need to disconnect all the devices from the group as those might be connected 3074 * as well especially those which might keep the connection 3075 */ 3076 if ((getConnectionState(dev) & leConnectedState) != 0) { 3077 mNativeInterface.disconnectAcl(dev, BluetoothDevice.TRANSPORT_LE); 3078 } 3079 } 3080 } 3081 } 3082 3083 /** 3084 * Notify AdapterService about failed GATT connection attempt. 3085 * 3086 * @param clientIf ClientIf which was doing GATT connection attempt 3087 * @param device Remote device to which connection attempt failed 3088 */ notifyGattClientConnectFailed(int clientIf, BluetoothDevice device)3089 public void notifyGattClientConnectFailed(int clientIf, BluetoothDevice device) { 3090 if (mLeAudioService != null) { 3091 removeGattClientFromControlAutoActiveMode(clientIf, device); 3092 } 3093 } 3094 3095 /** 3096 * Notify AdapterService about GATT connection being disconnecting or disconnected. 3097 * 3098 * @param clientIf ClientIf which is disconnecting or is already disconnected 3099 * @param device Remote device which is disconnecting or is disconnected 3100 */ notifyGattClientDisconnect(int clientIf, BluetoothDevice device)3101 public void notifyGattClientDisconnect(int clientIf, BluetoothDevice device) { 3102 if (mLeAudioService != null) { 3103 removeGattClientFromControlAutoActiveMode(clientIf, device); 3104 } 3105 } 3106 getConnectionState(BluetoothDevice device)3107 public int getConnectionState(BluetoothDevice device) { 3108 final String address = device.getAddress(); 3109 int connectionState = mNativeInterface.getConnectionState(getBytesFromAddress(address)); 3110 final String identityAddress = getIdentityAddress(address); 3111 if (identityAddress != null) { 3112 connectionState |= 3113 mNativeInterface.getConnectionState(getBytesFromAddress(identityAddress)); 3114 } 3115 return connectionState; 3116 } 3117 getConnectionHandle(BluetoothDevice device, int transport)3118 int getConnectionHandle(BluetoothDevice device, int transport) { 3119 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 3120 if (deviceProp == null) { 3121 return BluetoothDevice.ERROR; 3122 } 3123 return deviceProp.getConnectionHandle(transport); 3124 } 3125 3126 /** 3127 * Get ASHA Capability 3128 * 3129 * @param device discovered bluetooth device 3130 * @return ASHA capability 3131 */ getAshaCapability(BluetoothDevice device)3132 public int getAshaCapability(BluetoothDevice device) { 3133 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 3134 if (deviceProp == null) { 3135 return BluetoothDevice.ERROR; 3136 } 3137 return deviceProp.getAshaCapability(); 3138 } 3139 3140 /** 3141 * Get ASHA truncated HiSyncId 3142 * 3143 * @param device discovered bluetooth device 3144 * @return ASHA truncated HiSyncId 3145 */ getAshaTruncatedHiSyncId(BluetoothDevice device)3146 public int getAshaTruncatedHiSyncId(BluetoothDevice device) { 3147 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 3148 if (deviceProp == null) { 3149 return BluetoothDevice.ERROR; 3150 } 3151 return deviceProp.getAshaTruncatedHiSyncId(); 3152 } 3153 3154 /** 3155 * Checks whether the device was recently associated with the companion app that called {@link 3156 * BluetoothDevice#createBond}. This allows these devices to skip the pairing dialog if their 3157 * pairing variant is {@link BluetoothDevice#PAIRING_VARIANT_CONSENT}. 3158 * 3159 * @param device the bluetooth device that is being bonded 3160 * @return true if it was recently associated and we can bypass the dialog, false otherwise 3161 */ canBondWithoutDialog(BluetoothDevice device)3162 public boolean canBondWithoutDialog(BluetoothDevice device) { 3163 if (mBondAttemptCallerInfo.containsKey(device.getAddress())) { 3164 CallerInfo bondCallerInfo = mBondAttemptCallerInfo.get(device.getAddress()); 3165 3166 return mCompanionDeviceManager.canPairWithoutPrompt( 3167 bondCallerInfo.callerPackageName, device.getAddress(), bondCallerInfo.user); 3168 } 3169 return false; 3170 } 3171 3172 /** 3173 * Returns the package name of the most recent caller that called {@link 3174 * BluetoothDevice#createBond} on the given device. 3175 */ 3176 @Nullable getPackageNameOfBondingApplication(BluetoothDevice device)3177 public String getPackageNameOfBondingApplication(BluetoothDevice device) { 3178 CallerInfo info = mBondAttemptCallerInfo.get(device.getAddress()); 3179 if (info == null) { 3180 return null; 3181 } 3182 return info.callerPackageName; 3183 } 3184 3185 /** 3186 * Sets device as the active devices for the profiles passed into the function. 3187 * 3188 * @param device is the remote bluetooth device 3189 * @param profiles is a constant that references for which profiles we'll be setting the remote 3190 * device as our active device. One of the following: {@link 3191 * BluetoothAdapter#ACTIVE_DEVICE_AUDIO}, {@link BluetoothAdapter#ACTIVE_DEVICE_PHONE_CALL} 3192 * {@link BluetoothAdapter#ACTIVE_DEVICE_ALL} 3193 * @return false if profiles value is not one of the constants we accept, true otherwise 3194 */ setActiveDevice(BluetoothDevice device, @ActiveDeviceUse int profiles)3195 public boolean setActiveDevice(BluetoothDevice device, @ActiveDeviceUse int profiles) { 3196 if (getState() != BluetoothAdapter.STATE_ON) { 3197 Log.e(TAG, "setActiveDevice: Bluetooth is not enabled"); 3198 return false; 3199 } 3200 boolean setHeadset = false; 3201 boolean setA2dp = false; 3202 3203 // Determine for which profiles we want to set device as our active device 3204 switch (profiles) { 3205 case BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL -> setHeadset = true; 3206 case BluetoothAdapter.ACTIVE_DEVICE_AUDIO -> setA2dp = true; 3207 case BluetoothAdapter.ACTIVE_DEVICE_ALL -> { 3208 setHeadset = true; 3209 setA2dp = true; 3210 } 3211 default -> { 3212 return false; 3213 } 3214 } 3215 3216 boolean hfpSupported = 3217 mHeadsetService != null 3218 && (device == null 3219 || mHeadsetService.getConnectionPolicy(device) 3220 == CONNECTION_POLICY_ALLOWED); 3221 boolean a2dpSupported = 3222 mA2dpService != null 3223 && (device == null 3224 || mA2dpService.getConnectionPolicy(device) 3225 == CONNECTION_POLICY_ALLOWED); 3226 boolean leAudioSupported = 3227 mLeAudioService != null 3228 && (device == null 3229 || mLeAudioService.getConnectionPolicy(device) 3230 == CONNECTION_POLICY_ALLOWED); 3231 3232 if (leAudioSupported) { 3233 Log.i(TAG, "setActiveDevice: Setting active Le Audio device " + device); 3234 if (device == null) { 3235 /* If called by BluetoothAdapter it means Audio should not be stopped. 3236 * For this reason let's say that fallback device exists 3237 */ 3238 mLeAudioService.removeActiveDevice(true /* hasFallbackDevice */); 3239 } else { 3240 if (mA2dpService != null && mA2dpService.getActiveDevice() != null) { 3241 // TODO: b/312396770 3242 mA2dpService.removeActiveDevice(false); 3243 } 3244 mLeAudioService.setActiveDevice(device); 3245 } 3246 } 3247 3248 // Order matters, some devices do not accept A2DP connection before HFP connection 3249 if (setHeadset && hfpSupported) { 3250 Log.i(TAG, "setActiveDevice: Setting active Headset " + device); 3251 mHeadsetService.setActiveDevice(device); 3252 } 3253 3254 if (setA2dp && a2dpSupported) { 3255 Log.i(TAG, "setActiveDevice: Setting active A2dp device " + device); 3256 if (device == null) { 3257 mA2dpService.removeActiveDevice(false); 3258 } else { 3259 /* Workaround for the controller issue which is not able to handle correctly 3260 * A2DP offloader vendor specific command while ISO Data path is set. 3261 * Proper solutions should be delivered in b/312396770 3262 */ 3263 if (mLeAudioService != null) { 3264 List<BluetoothDevice> activeLeAudioDevices = mLeAudioService.getActiveDevices(); 3265 if (activeLeAudioDevices.get(0) != null) { 3266 mLeAudioService.removeActiveDevice(true); 3267 } 3268 } 3269 mA2dpService.setActiveDevice(device); 3270 } 3271 } 3272 3273 if (mHearingAidService != null 3274 && (device == null 3275 || mHearingAidService.getConnectionPolicy(device) 3276 == CONNECTION_POLICY_ALLOWED)) { 3277 Log.i(TAG, "setActiveDevice: Setting active Hearing Aid " + device); 3278 if (device == null) { 3279 mHearingAidService.removeActiveDevice(false); 3280 } else { 3281 mHearingAidService.setActiveDevice(device); 3282 } 3283 } 3284 3285 return true; 3286 } 3287 3288 /** 3289 * Checks if all supported classic audio profiles are active on this LE Audio device. 3290 * 3291 * @param leAudioDevice the remote device 3292 * @return {@code true} if all supported classic audio profiles are active on this device, 3293 * {@code false} otherwise 3294 */ isAllSupportedClassicAudioProfilesActive(BluetoothDevice leAudioDevice)3295 public boolean isAllSupportedClassicAudioProfilesActive(BluetoothDevice leAudioDevice) { 3296 if (mLeAudioService == null) { 3297 return false; 3298 } 3299 boolean hfpSupported = isProfileSupported(leAudioDevice, BluetoothProfile.HEADSET); 3300 boolean a2dpSupported = isProfileSupported(leAudioDevice, BluetoothProfile.A2DP); 3301 3302 List<BluetoothDevice> groupDevices = mLeAudioService.getGroupDevices(leAudioDevice); 3303 if (hfpSupported && mHeadsetService != null) { 3304 BluetoothDevice activeHfpDevice = mHeadsetService.getActiveDevice(); 3305 if (activeHfpDevice == null || !groupDevices.contains(activeHfpDevice)) { 3306 return false; 3307 } 3308 } 3309 if (a2dpSupported && mA2dpService != null) { 3310 BluetoothDevice activeA2dpDevice = mA2dpService.getActiveDevice(); 3311 if (activeA2dpDevice == null || !groupDevices.contains(activeA2dpDevice)) { 3312 return false; 3313 } 3314 } 3315 return true; 3316 } 3317 3318 /** 3319 * Get the active devices for the BluetoothProfile specified 3320 * 3321 * @param profile is the profile from which we want the active devices. Possible values are: 3322 * {@link BluetoothProfile#HEADSET}, {@link BluetoothProfile#A2DP}, {@link 3323 * BluetoothProfile#HEARING_AID} {@link BluetoothProfile#LE_AUDIO} 3324 * @return A list of active bluetooth devices 3325 */ getActiveDevices(@ctiveDeviceProfile int profile)3326 public List<BluetoothDevice> getActiveDevices(@ActiveDeviceProfile int profile) { 3327 List<BluetoothDevice> activeDevices = new ArrayList<>(); 3328 3329 switch (profile) { 3330 case BluetoothProfile.HEADSET: 3331 if (mHeadsetService == null) { 3332 Log.e(TAG, "getActiveDevices: HeadsetService is null"); 3333 } else { 3334 BluetoothDevice device = mHeadsetService.getActiveDevice(); 3335 if (device != null) { 3336 activeDevices.add(device); 3337 } 3338 Log.i(TAG, "getActiveDevices: Headset device: " + device); 3339 } 3340 break; 3341 case BluetoothProfile.A2DP: 3342 if (mA2dpService == null) { 3343 Log.e(TAG, "getActiveDevices: A2dpService is null"); 3344 } else { 3345 BluetoothDevice device = mA2dpService.getActiveDevice(); 3346 if (device != null) { 3347 activeDevices.add(device); 3348 } 3349 Log.i(TAG, "getActiveDevices: A2dp device: " + device); 3350 } 3351 break; 3352 case BluetoothProfile.HEARING_AID: 3353 if (mHearingAidService == null) { 3354 Log.e(TAG, "getActiveDevices: HearingAidService is null"); 3355 } else { 3356 activeDevices = mHearingAidService.getActiveDevices(); 3357 Log.i( 3358 TAG, 3359 "getActiveDevices: Hearing Aid devices:" 3360 + (" Left[" + activeDevices.get(0) + "] -") 3361 + (" Right[" + activeDevices.get(1) + "]")); 3362 } 3363 break; 3364 case BluetoothProfile.LE_AUDIO: 3365 if (mLeAudioService == null) { 3366 Log.e(TAG, "getActiveDevices: LeAudioService is null"); 3367 } else { 3368 activeDevices = mLeAudioService.getActiveDevices(); 3369 Log.i( 3370 TAG, 3371 "getActiveDevices: LeAudio devices:" 3372 + (" Lead[" + activeDevices.get(0) + "] -") 3373 + (" member_1[" + activeDevices.get(1) + "]")); 3374 } 3375 break; 3376 default: 3377 Log.e(TAG, "getActiveDevices: profile value is not valid"); 3378 } 3379 return activeDevices; 3380 } 3381 3382 /** 3383 * Attempts connection to all enabled and supported bluetooth profiles between the local and 3384 * remote device 3385 * 3386 * @param device is the remote device with which to connect these profiles 3387 * @return {@link BluetoothStatusCodes#SUCCESS} if all profiles connections are attempted, false 3388 * if an error occurred 3389 */ connectAllEnabledProfiles(BluetoothDevice device)3390 public int connectAllEnabledProfiles(BluetoothDevice device) { 3391 if (!profileServicesRunning()) { 3392 Log.e(TAG, "connectAllEnabledProfiles: Not all profile services running"); 3393 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; 3394 } 3395 3396 // Checks if any profiles are enabled or disabled and if so, only connect enabled profiles 3397 if (!isAllProfilesUnknown(device)) { 3398 return connectEnabledProfiles(device); 3399 } 3400 3401 connectAllSupportedProfiles(device); 3402 3403 return BluetoothStatusCodes.SUCCESS; 3404 } 3405 3406 /** All profile toggles are disabled, so connects all supported profiles */ connectAllSupportedProfiles(BluetoothDevice device)3407 void connectAllSupportedProfiles(BluetoothDevice device) { 3408 int numProfilesConnected = 0; 3409 3410 // Order matters, some devices do not accept A2DP connection before HFP connection 3411 if (mHeadsetService != null && isProfileSupported(device, BluetoothProfile.HEADSET)) { 3412 Log.i(TAG, "connectAllSupportedProfiles: Connecting Headset Profile"); 3413 mHeadsetService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED); 3414 numProfilesConnected++; 3415 } 3416 if (mHeadsetClientService != null 3417 && isProfileSupported(device, BluetoothProfile.HEADSET_CLIENT)) { 3418 Log.i(TAG, "connectAllSupportedProfiles: Connecting HFP"); 3419 mHeadsetClientService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED); 3420 numProfilesConnected++; 3421 } 3422 if (mA2dpService != null && isProfileSupported(device, BluetoothProfile.A2DP)) { 3423 Log.i(TAG, "connectAllSupportedProfiles: Connecting A2dp"); 3424 // Set connection policy also connects the profile with CONNECTION_POLICY_ALLOWED 3425 mA2dpService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED); 3426 numProfilesConnected++; 3427 } 3428 if (mA2dpSinkService != null && isProfileSupported(device, BluetoothProfile.A2DP_SINK)) { 3429 Log.i(TAG, "connectAllSupportedProfiles: Connecting A2dp Sink"); 3430 mA2dpSinkService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED); 3431 numProfilesConnected++; 3432 } 3433 if (mMapClientService != null && isProfileSupported(device, BluetoothProfile.MAP_CLIENT)) { 3434 Log.i(TAG, "connectAllSupportedProfiles: Connecting MAP"); 3435 mMapClientService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED); 3436 numProfilesConnected++; 3437 } 3438 if (mHidHostService != null && isProfileSupported(device, BluetoothProfile.HID_HOST)) { 3439 Log.i(TAG, "connectAllSupportedProfiles: Connecting Hid Host Profile"); 3440 mHidHostService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED); 3441 numProfilesConnected++; 3442 } 3443 if (mPanService != null && isProfileSupported(device, BluetoothProfile.PAN)) { 3444 Log.i(TAG, "connectAllSupportedProfiles: Connecting Pan Profile"); 3445 mPanService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED); 3446 numProfilesConnected++; 3447 } 3448 if (mPbapClientService != null 3449 && isProfileSupported(device, BluetoothProfile.PBAP_CLIENT)) { 3450 Log.i(TAG, "connectAllSupportedProfiles: Connecting Pbap"); 3451 mPbapClientService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED); 3452 numProfilesConnected++; 3453 } 3454 if (mHearingAidService != null 3455 && isProfileSupported(device, BluetoothProfile.HEARING_AID)) { 3456 if (mHapClientService != null 3457 && isProfileSupported(device, BluetoothProfile.HAP_CLIENT)) { 3458 Log.i( 3459 TAG, 3460 "connectAllSupportedProfiles: Hearing Access Client Profile is enabled at" 3461 + " the same time with Hearing Aid Profile, ignore Hearing Aid" 3462 + " Profile"); 3463 } else { 3464 Log.i(TAG, "connectAllSupportedProfiles: Connecting Hearing Aid Profile"); 3465 mHearingAidService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED); 3466 numProfilesConnected++; 3467 } 3468 } 3469 if (mHapClientService != null && isProfileSupported(device, BluetoothProfile.HAP_CLIENT)) { 3470 Log.i(TAG, "connectAllSupportedProfiles: Connecting Hearing Access Client Profile"); 3471 mHapClientService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED); 3472 numProfilesConnected++; 3473 } 3474 if (mVolumeControlService != null 3475 && isProfileSupported(device, BluetoothProfile.VOLUME_CONTROL)) { 3476 Log.i(TAG, "connectAllSupportedProfiles: Connecting Volume Control Profile"); 3477 mVolumeControlService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED); 3478 numProfilesConnected++; 3479 } 3480 if (mCsipSetCoordinatorService != null 3481 && isProfileSupported(device, BluetoothProfile.CSIP_SET_COORDINATOR)) { 3482 Log.i(TAG, "connectAllSupportedProfiles: Connecting Coordinated Set Profile"); 3483 mCsipSetCoordinatorService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED); 3484 numProfilesConnected++; 3485 } 3486 if (mLeAudioService != null && isProfileSupported(device, BluetoothProfile.LE_AUDIO)) { 3487 Log.i(TAG, "connectAllSupportedProfiles: Connecting LeAudio profile (BAP)"); 3488 mLeAudioService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED); 3489 numProfilesConnected++; 3490 } 3491 if (mBassClientService != null 3492 && isProfileSupported(device, BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT)) { 3493 Log.i(TAG, "connectAllSupportedProfiles: Connecting LE Broadcast Assistant Profile"); 3494 mBassClientService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED); 3495 numProfilesConnected++; 3496 } 3497 if (mBatteryService != null && isProfileSupported(device, BluetoothProfile.BATTERY)) { 3498 Log.i(TAG, "connectAllSupportedProfiles: Connecting Battery Service"); 3499 mBatteryService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED); 3500 numProfilesConnected++; 3501 } 3502 3503 Log.i( 3504 TAG, 3505 "connectAllSupportedProfiles: Number of Profiles Connected: " 3506 + numProfilesConnected); 3507 } 3508 3509 /** 3510 * Disconnects all enabled and supported bluetooth profiles between the local and remote device 3511 * 3512 * @param device is the remote device with which to disconnect these profiles 3513 * @return true if all profiles successfully disconnected, false if an error occurred 3514 */ disconnectAllEnabledProfiles(BluetoothDevice device)3515 public int disconnectAllEnabledProfiles(BluetoothDevice device) { 3516 if (!profileServicesRunning()) { 3517 Log.e(TAG, "disconnectAllEnabledProfiles: Not all profile services bound"); 3518 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; 3519 } 3520 3521 if (mHeadsetService != null 3522 && (mHeadsetService.getConnectionState(device) == STATE_CONNECTED 3523 || mHeadsetService.getConnectionState(device) == STATE_CONNECTING)) { 3524 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Headset Profile"); 3525 mHeadsetService.disconnect(device); 3526 } 3527 if (mHeadsetClientService != null 3528 && (mHeadsetClientService.getConnectionState(device) == STATE_CONNECTED 3529 || mHeadsetClientService.getConnectionState(device) == STATE_CONNECTING)) { 3530 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting HFP"); 3531 mHeadsetClientService.disconnect(device); 3532 } 3533 if (mA2dpService != null 3534 && (mA2dpService.getConnectionState(device) == STATE_CONNECTED 3535 || mA2dpService.getConnectionState(device) == STATE_CONNECTING)) { 3536 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting A2dp"); 3537 mA2dpService.disconnect(device); 3538 } 3539 if (mA2dpSinkService != null 3540 && (mA2dpSinkService.getConnectionState(device) == STATE_CONNECTED 3541 || mA2dpSinkService.getConnectionState(device) == STATE_CONNECTING)) { 3542 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting A2dp Sink"); 3543 mA2dpSinkService.disconnect(device); 3544 } 3545 if (mMapClientService != null 3546 && (mMapClientService.getConnectionState(device) == STATE_CONNECTED 3547 || mMapClientService.getConnectionState(device) == STATE_CONNECTING)) { 3548 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting MAP Client"); 3549 mMapClientService.disconnect(device); 3550 } 3551 if (mMapService != null 3552 && (mMapService.getConnectionState(device) == STATE_CONNECTED 3553 || mMapService.getConnectionState(device) == STATE_CONNECTING)) { 3554 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting MAP"); 3555 mMapService.disconnect(device); 3556 } 3557 if (mHidDeviceService != null 3558 && (mHidDeviceService.getConnectionState(device) == STATE_CONNECTED 3559 || mHidDeviceService.getConnectionState(device) == STATE_CONNECTING)) { 3560 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Hid Device Profile"); 3561 mHidDeviceService.disconnect(device); 3562 } 3563 if (mHidHostService != null 3564 && (mHidHostService.getConnectionState(device) == STATE_CONNECTED 3565 || mHidHostService.getConnectionState(device) == STATE_CONNECTING)) { 3566 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Hid Host Profile"); 3567 mHidHostService.disconnect(device); 3568 } 3569 if (mPanService != null 3570 && (mPanService.getConnectionState(device) == STATE_CONNECTED 3571 || mPanService.getConnectionState(device) == STATE_CONNECTING)) { 3572 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Pan Profile"); 3573 mPanService.disconnect(device); 3574 } 3575 if (mPbapClientService != null 3576 && (mPbapClientService.getConnectionState(device) == STATE_CONNECTED 3577 || mPbapClientService.getConnectionState(device) == STATE_CONNECTING)) { 3578 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Pbap Client"); 3579 mPbapClientService.disconnect(device); 3580 } 3581 if (mPbapService != null 3582 && (mPbapService.getConnectionState(device) == STATE_CONNECTED 3583 || mPbapService.getConnectionState(device) == STATE_CONNECTING)) { 3584 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Pbap Server"); 3585 mPbapService.disconnect(device); 3586 } 3587 if (mHearingAidService != null 3588 && (mHearingAidService.getConnectionState(device) == STATE_CONNECTED 3589 || mHearingAidService.getConnectionState(device) == STATE_CONNECTING)) { 3590 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Hearing Aid Profile"); 3591 mHearingAidService.disconnect(device); 3592 } 3593 if (mHapClientService != null 3594 && (mHapClientService.getConnectionState(device) == STATE_CONNECTED 3595 || mHapClientService.getConnectionState(device) == STATE_CONNECTING)) { 3596 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Hearing Access Profile Client"); 3597 mHapClientService.disconnect(device); 3598 } 3599 if (mVolumeControlService != null 3600 && (mVolumeControlService.getConnectionState(device) == STATE_CONNECTED 3601 || mVolumeControlService.getConnectionState(device) == STATE_CONNECTING)) { 3602 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Volume Control Profile"); 3603 mVolumeControlService.disconnect(device); 3604 } 3605 if (mSapService != null 3606 && (mSapService.getConnectionState(device) == STATE_CONNECTED 3607 || mSapService.getConnectionState(device) == STATE_CONNECTING)) { 3608 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Sap Profile"); 3609 mSapService.disconnect(device); 3610 } 3611 if (mCsipSetCoordinatorService != null 3612 && (mCsipSetCoordinatorService.getConnectionState(device) == STATE_CONNECTED 3613 || mCsipSetCoordinatorService.getConnectionState(device) 3614 == STATE_CONNECTING)) { 3615 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Coordinator Set Profile"); 3616 mCsipSetCoordinatorService.disconnect(device); 3617 } 3618 if (mLeAudioService != null 3619 && (mLeAudioService.getConnectionState(device) == STATE_CONNECTED 3620 || mLeAudioService.getConnectionState(device) == STATE_CONNECTING)) { 3621 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting LeAudio profile (BAP)"); 3622 mLeAudioService.disconnect(device); 3623 } 3624 if (mBassClientService != null 3625 && (mBassClientService.getConnectionState(device) == STATE_CONNECTED 3626 || mBassClientService.getConnectionState(device) == STATE_CONNECTING)) { 3627 Log.i( 3628 TAG, 3629 "disconnectAllEnabledProfiles: Disconnecting " 3630 + "LE Broadcast Assistant Profile"); 3631 mBassClientService.disconnect(device); 3632 } 3633 if (mBatteryService != null 3634 && (mBatteryService.getConnectionState(device) == STATE_CONNECTED 3635 || mBatteryService.getConnectionState(device) == STATE_CONNECTING)) { 3636 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting " + "Battery Service"); 3637 mBatteryService.disconnect(device); 3638 } 3639 3640 return BluetoothStatusCodes.SUCCESS; 3641 } 3642 3643 /** 3644 * Same as API method {@link BluetoothDevice#getName()} 3645 * 3646 * @param device remote device of interest 3647 * @return remote device name 3648 */ getRemoteName(BluetoothDevice device)3649 public String getRemoteName(BluetoothDevice device) { 3650 return mRemoteDevices.getName(device); 3651 } 3652 getRemoteClass(BluetoothDevice device)3653 public int getRemoteClass(BluetoothDevice device) { 3654 return mRemoteDevices.getBluetoothClass(device); 3655 } 3656 3657 /** 3658 * Get UUIDs for service supported by a remote device 3659 * 3660 * @param device the remote device that we want to get UUIDs from 3661 * @return the uuids of the remote device 3662 */ getRemoteUuids(BluetoothDevice device)3663 public ParcelUuid[] getRemoteUuids(BluetoothDevice device) { 3664 return mRemoteDevices.getUuids(device); 3665 } 3666 aclStateChangeBroadcastCallback( RemoteExceptionIgnoringConsumer<IBluetoothConnectionCallback> cb)3667 void aclStateChangeBroadcastCallback( 3668 RemoteExceptionIgnoringConsumer<IBluetoothConnectionCallback> cb) { 3669 int n = mBluetoothConnectionCallbacks.beginBroadcast(); 3670 Log.d(TAG, "aclStateChangeBroadcastCallback() - Broadcasting to " + n + " receivers."); 3671 for (int i = 0; i < n; i++) { 3672 cb.accept(mBluetoothConnectionCallbacks.getBroadcastItem(i)); 3673 } 3674 mBluetoothConnectionCallbacks.finishBroadcast(); 3675 } 3676 3677 /** 3678 * Converts HCI disconnect reasons to Android disconnect reasons. 3679 * 3680 * <p>The HCI Error Codes used for ACL disconnect reasons propagated up from native code were 3681 * copied from: packages/modules/Bluetooth/system/stack/include/hci_error_code.h 3682 * 3683 * <p>These error codes are specified and described in Bluetooth Core Spec v5.1, Vol 2, Part D. 3684 * 3685 * @param hciReason is the raw HCI disconnect reason from native. 3686 * @return the Android disconnect reason for apps. 3687 */ 3688 static @BluetoothAdapter.BluetoothConnectionCallback.DisconnectReason int hciToAndroidDisconnectReason(int hciReason)3689 hciToAndroidDisconnectReason(int hciReason) { 3690 switch (hciReason) { 3691 case /*HCI_SUCCESS*/ 0x00: 3692 case /*HCI_ERR_UNSPECIFIED*/ 0x1F: 3693 case /*HCI_ERR_UNDEFINED*/ 0xff: 3694 return BluetoothStatusCodes.ERROR_UNKNOWN; 3695 case /*HCI_ERR_ILLEGAL_COMMAND*/ 0x01: 3696 case /*HCI_ERR_NO_CONNECTION*/ 0x02: 3697 case /*HCI_ERR_HW_FAILURE*/ 0x03: 3698 case /*HCI_ERR_DIFF_TRANSACTION_COLLISION*/ 0x2A: 3699 case /*HCI_ERR_ROLE_SWITCH_PENDING*/ 0x32: 3700 case /*HCI_ERR_ROLE_SWITCH_FAILED*/ 0x35: 3701 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_LOCAL; 3702 case /*HCI_ERR_PAGE_TIMEOUT*/ 0x04: 3703 case /*HCI_ERR_CONNECTION_TOUT*/ 0x08: 3704 case /*HCI_ERR_HOST_TIMEOUT*/ 0x10: 3705 case /*HCI_ERR_LMP_RESPONSE_TIMEOUT*/ 0x22: 3706 case /*HCI_ERR_ADVERTISING_TIMEOUT*/ 0x3C: 3707 case /*HCI_ERR_CONN_FAILED_ESTABLISHMENT*/ 0x3E: 3708 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_TIMEOUT; 3709 case /*HCI_ERR_AUTH_FAILURE*/ 0x05: 3710 case /*HCI_ERR_KEY_MISSING*/ 0x06: 3711 case /*HCI_ERR_HOST_REJECT_SECURITY*/ 0x0E: 3712 case /*HCI_ERR_REPEATED_ATTEMPTS*/ 0x17: 3713 case /*HCI_ERR_PAIRING_NOT_ALLOWED*/ 0x18: 3714 case /*HCI_ERR_ENCRY_MODE_NOT_ACCEPTABLE*/ 0x25: 3715 case /*HCI_ERR_UNIT_KEY_USED*/ 0x26: 3716 case /*HCI_ERR_PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED*/ 0x29: 3717 case /*HCI_ERR_INSUFFICIENT_SECURITY*/ 0x2F: 3718 case /*HCI_ERR_HOST_BUSY_PAIRING*/ 0x38: 3719 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_SECURITY; 3720 case /*HCI_ERR_MEMORY_FULL*/ 0x07: 3721 case /*HCI_ERR_MAX_NUM_OF_CONNECTIONS*/ 0x09: 3722 case /*HCI_ERR_MAX_NUM_OF_SCOS*/ 0x0A: 3723 case /*HCI_ERR_COMMAND_DISALLOWED*/ 0x0C: 3724 case /*HCI_ERR_HOST_REJECT_RESOURCES*/ 0x0D: 3725 case /*HCI_ERR_LIMIT_REACHED*/ 0x43: 3726 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_RESOURCE_LIMIT_REACHED; 3727 case /*HCI_ERR_CONNECTION_EXISTS*/ 0x0B: 3728 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_CONNECTION_ALREADY_EXISTS; 3729 case /*HCI_ERR_HOST_REJECT_DEVICE*/ 0x0F: 3730 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_SYSTEM_POLICY; 3731 case /*HCI_ERR_ILLEGAL_PARAMETER_FMT*/ 0x12: 3732 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_BAD_PARAMETERS; 3733 case /*HCI_ERR_PEER_USER*/ 0x13: 3734 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_REMOTE_REQUEST; 3735 case /*HCI_ERR_REMOTE_POWER_OFF*/ 0x15: 3736 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_REMOTE_REQUEST; 3737 case /*HCI_ERR_CONN_CAUSE_LOCAL_HOST*/ 0x16: 3738 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_LOCAL_REQUEST; 3739 case /*HCI_ERR_UNSUPPORTED_REM_FEATURE*/ 0x1A: 3740 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_REMOTE; 3741 case /*HCI_ERR_UNACCEPT_CONN_INTERVAL*/ 0x3B: 3742 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_BAD_PARAMETERS; 3743 default: 3744 Log.e(TAG, "Invalid HCI disconnect reason: " + hciReason); 3745 return BluetoothStatusCodes.ERROR_UNKNOWN; 3746 } 3747 } 3748 logUserBondResponse(BluetoothDevice device, boolean accepted, AttributionSource source)3749 void logUserBondResponse(BluetoothDevice device, boolean accepted, AttributionSource source) { 3750 final long token = Binder.clearCallingIdentity(); 3751 try { 3752 MetricsLogger.getInstance() 3753 .logBluetoothEvent( 3754 device, 3755 BluetoothStatsLog 3756 .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__USER_CONF_REQUEST, 3757 accepted 3758 ? BluetoothStatsLog 3759 .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__SUCCESS 3760 : BluetoothStatsLog 3761 .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__FAIL, 3762 source.getUid()); 3763 } finally { 3764 Binder.restoreCallingIdentity(token); 3765 } 3766 } 3767 getPhonebookAccessPermission(BluetoothDevice device)3768 public int getPhonebookAccessPermission(BluetoothDevice device) { 3769 return getDeviceAccessFromPrefs(device, PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE); 3770 } 3771 getMessageAccessPermission(BluetoothDevice device)3772 public int getMessageAccessPermission(BluetoothDevice device) { 3773 return getDeviceAccessFromPrefs(device, MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE); 3774 } 3775 getSimAccessPermission(BluetoothDevice device)3776 public int getSimAccessPermission(BluetoothDevice device) { 3777 return getDeviceAccessFromPrefs(device, SIM_ACCESS_PERMISSION_PREFERENCE_FILE); 3778 } 3779 getDeviceAccessFromPrefs(BluetoothDevice device, String prefFile)3780 int getDeviceAccessFromPrefs(BluetoothDevice device, String prefFile) { 3781 SharedPreferences prefs = getSharedPreferences(prefFile, Context.MODE_PRIVATE); 3782 if (!prefs.contains(device.getAddress())) { 3783 return BluetoothDevice.ACCESS_UNKNOWN; 3784 } 3785 return prefs.getBoolean(device.getAddress(), false) 3786 ? BluetoothDevice.ACCESS_ALLOWED 3787 : BluetoothDevice.ACCESS_REJECTED; 3788 } 3789 setDeviceAccessFromPrefs(BluetoothDevice device, int value, String prefFile)3790 void setDeviceAccessFromPrefs(BluetoothDevice device, int value, String prefFile) { 3791 SharedPreferences pref = getSharedPreferences(prefFile, Context.MODE_PRIVATE); 3792 SharedPreferences.Editor editor = pref.edit(); 3793 if (value == BluetoothDevice.ACCESS_UNKNOWN) { 3794 editor.remove(device.getAddress()); 3795 } else { 3796 editor.putBoolean(device.getAddress(), value == BluetoothDevice.ACCESS_ALLOWED); 3797 } 3798 editor.apply(); 3799 } 3800 setPhonebookAccessPermission(BluetoothDevice device, int value)3801 public void setPhonebookAccessPermission(BluetoothDevice device, int value) { 3802 Log.d( 3803 TAG, 3804 "setPhonebookAccessPermission device=" 3805 + ((device == null) ? "null" : device.getAnonymizedAddress()) 3806 + ", value=" 3807 + value 3808 + ", callingUid=" 3809 + Binder.getCallingUid()); 3810 setDeviceAccessFromPrefs(device, value, PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE); 3811 } 3812 setMessageAccessPermission(BluetoothDevice device, int value)3813 public void setMessageAccessPermission(BluetoothDevice device, int value) { 3814 setDeviceAccessFromPrefs(device, value, MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE); 3815 } 3816 setSimAccessPermission(BluetoothDevice device, int value)3817 public void setSimAccessPermission(BluetoothDevice device, int value) { 3818 setDeviceAccessFromPrefs(device, value, SIM_ACCESS_PERMISSION_PREFERENCE_FILE); 3819 } 3820 isRpaOffloadSupported()3821 public boolean isRpaOffloadSupported() { 3822 return mAdapterProperties.isRpaOffloadSupported(); 3823 } 3824 getNumOfOffloadedIrkSupported()3825 public int getNumOfOffloadedIrkSupported() { 3826 return mAdapterProperties.getNumOfOffloadedIrkSupported(); 3827 } 3828 getNumOfOffloadedScanFilterSupported()3829 public int getNumOfOffloadedScanFilterSupported() { 3830 return mAdapterProperties.getNumOfOffloadedScanFilterSupported(); 3831 } 3832 getOffloadedScanResultStorage()3833 public int getOffloadedScanResultStorage() { 3834 return mAdapterProperties.getOffloadedScanResultStorage(); 3835 } 3836 isLe2MPhySupported()3837 public boolean isLe2MPhySupported() { 3838 return mAdapterProperties.isLe2MPhySupported(); 3839 } 3840 isLeCodedPhySupported()3841 public boolean isLeCodedPhySupported() { 3842 return mAdapterProperties.isLeCodedPhySupported(); 3843 } 3844 isLeExtendedAdvertisingSupported()3845 public boolean isLeExtendedAdvertisingSupported() { 3846 return mAdapterProperties.isLeExtendedAdvertisingSupported(); 3847 } 3848 isLePeriodicAdvertisingSupported()3849 public boolean isLePeriodicAdvertisingSupported() { 3850 return mAdapterProperties.isLePeriodicAdvertisingSupported(); 3851 } 3852 3853 /** 3854 * Check if the LE audio broadcast source feature is supported. 3855 * 3856 * @return true, if the LE audio broadcast source is supported 3857 */ isLeAudioBroadcastSourceSupported()3858 public boolean isLeAudioBroadcastSourceSupported() { 3859 return mAdapterProperties.isLePeriodicAdvertisingSupported() 3860 && mAdapterProperties.isLeExtendedAdvertisingSupported() 3861 && mAdapterProperties.isLeIsochronousBroadcasterSupported(); 3862 } 3863 3864 /** 3865 * Check if the LE audio broadcast assistant feature is supported. 3866 * 3867 * @return true, if the LE audio broadcast assistant is supported 3868 */ isLeAudioBroadcastAssistantSupported()3869 public boolean isLeAudioBroadcastAssistantSupported() { 3870 return mAdapterProperties.isLePeriodicAdvertisingSupported() 3871 && mAdapterProperties.isLeExtendedAdvertisingSupported() 3872 && (mAdapterProperties.isLePeriodicAdvertisingSyncTransferSenderSupported() 3873 || mAdapterProperties 3874 .isLePeriodicAdvertisingSyncTransferRecipientSupported()); 3875 } 3876 3877 /** 3878 * Check if the LE channel sounding feature is supported. 3879 * 3880 * @return true, if the LE channel sounding is supported 3881 */ isLeChannelSoundingSupported()3882 public boolean isLeChannelSoundingSupported() { 3883 return mAdapterProperties.isLeChannelSoundingSupported(); 3884 } 3885 getSupportedProfilesBitMask()3886 public long getSupportedProfilesBitMask() { 3887 return Config.getSupportedProfilesBitMask(); 3888 } 3889 3890 /** 3891 * Check if the LE audio CIS central feature is supported. 3892 * 3893 * @return true, if the LE audio CIS central is supported 3894 */ isLeConnectedIsochronousStreamCentralSupported()3895 public boolean isLeConnectedIsochronousStreamCentralSupported() { 3896 return mAdapterProperties.isLeConnectedIsochronousStreamCentralSupported(); 3897 } 3898 getLeMaximumAdvertisingDataLength()3899 public int getLeMaximumAdvertisingDataLength() { 3900 return mAdapterProperties.getLeMaximumAdvertisingDataLength(); 3901 } 3902 3903 /** 3904 * Get the maximum number of connected audio devices. 3905 * 3906 * @return the maximum number of connected audio devices 3907 */ getMaxConnectedAudioDevices()3908 public int getMaxConnectedAudioDevices() { 3909 return mAdapterProperties.getMaxConnectedAudioDevices(); 3910 } 3911 3912 /** 3913 * Check whether A2DP offload is enabled. 3914 * 3915 * @return true if A2DP offload is enabled 3916 */ isA2dpOffloadEnabled()3917 public boolean isA2dpOffloadEnabled() { 3918 return mAdapterProperties.isA2dpOffloadEnabled(); 3919 } 3920 3921 /** Register a bluetooth state callback */ registerBluetoothStateCallback(Executor executor, BluetoothStateCallback callback)3922 public void registerBluetoothStateCallback(Executor executor, BluetoothStateCallback callback) { 3923 mLocalCallbacks.put(callback, executor); 3924 } 3925 3926 /** Unregister a bluetooth state callback */ unregisterBluetoothStateCallback(BluetoothStateCallback callback)3927 public void unregisterBluetoothStateCallback(BluetoothStateCallback callback) { 3928 mLocalCallbacks.remove(callback); 3929 } 3930 registerRemoteCallback(IBluetoothCallback callback)3931 void registerRemoteCallback(IBluetoothCallback callback) { 3932 mSystemServerCallbacks.register(callback); 3933 } 3934 unregisterRemoteCallback(IBluetoothCallback callback)3935 void unregisterRemoteCallback(IBluetoothCallback callback) { 3936 mSystemServerCallbacks.unregister(callback); 3937 } 3938 bleOnToOn()3939 void bleOnToOn() { 3940 mAdapterStateMachine.sendMessage(AdapterState.USER_TURN_ON); 3941 } 3942 bleOnToOff()3943 void bleOnToOff() { 3944 mAdapterStateMachine.sendMessage(AdapterState.BLE_TURN_OFF); 3945 } 3946 factoryReset()3947 boolean factoryReset() { 3948 mDatabaseManager.factoryReset(); 3949 3950 if (mBluetoothKeystoreService != null) { 3951 mBluetoothKeystoreService.factoryReset(); 3952 } 3953 3954 if (mBtCompanionManager != null) { 3955 mBtCompanionManager.factoryReset(); 3956 } 3957 3958 if (Flags.gattClearCacheOnFactoryReset()) { 3959 clearStorage(); 3960 } 3961 3962 return mNativeInterface.factoryReset(); 3963 } 3964 getScanMode()3965 int getScanMode() { 3966 return mScanMode; 3967 } 3968 setScanMode(int mode, String from)3969 boolean setScanMode(int mode, String from) { 3970 mScanModeChanges.add(from + ": " + scanModeName(mode)); 3971 if (!mNativeInterface.setScanMode(convertScanModeToHal(mode))) { 3972 return false; 3973 } 3974 mScanMode = mode; 3975 Intent intent = 3976 new Intent(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED) 3977 .putExtra(BluetoothAdapter.EXTRA_SCAN_MODE, mScanMode) 3978 .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 3979 sendBroadcast(intent, BLUETOOTH_SCAN, Utils.getTempBroadcastOptions().toBundle()); 3980 return true; 3981 } 3982 reportActivityInfo()3983 BluetoothActivityEnergyInfo reportActivityInfo() { 3984 if (mAdapterProperties.getState() != BluetoothAdapter.STATE_ON 3985 || !mAdapterProperties.isActivityAndEnergyReportingSupported()) { 3986 return null; 3987 } 3988 3989 // Pull the data. The callback will notify mEnergyInfoLock. 3990 mNativeInterface.readEnergyInfo(); 3991 3992 synchronized (mEnergyInfoLock) { 3993 long now = System.currentTimeMillis(); 3994 final long deadline = now + CONTROLLER_ENERGY_UPDATE_TIMEOUT_MILLIS; 3995 while (now < deadline) { 3996 try { 3997 mEnergyInfoLock.wait(deadline - now); 3998 break; 3999 } catch (InterruptedException e) { 4000 now = System.currentTimeMillis(); 4001 } 4002 } 4003 4004 final BluetoothActivityEnergyInfo info = 4005 new BluetoothActivityEnergyInfo( 4006 SystemClock.elapsedRealtime(), 4007 mStackReportedState, 4008 mTxTimeTotalMs, 4009 mRxTimeTotalMs, 4010 mIdleTimeTotalMs, 4011 mEnergyUsedTotalVoltAmpSecMicro); 4012 4013 // Copy the traffic objects whose byte counts are > 0 4014 final List<UidTraffic> result = new ArrayList<>(); 4015 for (int i = 0; i < mUidTraffic.size(); i++) { 4016 final UidTraffic traffic = mUidTraffic.valueAt(i); 4017 if (traffic.getTxBytes() != 0 || traffic.getRxBytes() != 0) { 4018 result.add(traffic.clone()); 4019 } 4020 } 4021 4022 info.setUidTraffic(result); 4023 4024 return info; 4025 } 4026 } 4027 getTotalNumOfTrackableAdvertisements()4028 public int getTotalNumOfTrackableAdvertisements() { 4029 return mAdapterProperties.getTotalNumOfTrackableAdvertisements(); 4030 } 4031 4032 /** 4033 * Return if offloaded TDS filter is supported. 4034 * 4035 * @return {@code BluetoothStatusCodes.FEATURE_SUPPORTED} if supported 4036 */ getOffloadedTransportDiscoveryDataScanSupported()4037 public int getOffloadedTransportDiscoveryDataScanSupported() { 4038 if (mAdapterProperties.isOffloadedTransportDiscoveryDataScanSupported()) { 4039 return BluetoothStatusCodes.FEATURE_SUPPORTED; 4040 } 4041 return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED; 4042 } 4043 getBluetoothGatt()4044 IBinder getBluetoothGatt() { 4045 return mGattService == null ? null : mGattService.getBinder(); 4046 } 4047 getBluetoothGattService()4048 public GattService getBluetoothGattService() { 4049 return mGattService; 4050 } 4051 getBluetoothScan()4052 IBinder getBluetoothScan() { 4053 ScanController controller = getBluetoothScanController(); 4054 return controller == null ? null : controller.getBinder(); 4055 } 4056 4057 @Nullable getBluetoothScanController()4058 public ScanController getBluetoothScanController() { 4059 if (Flags.onlyStartScanDuringBleOn()) { 4060 return mScanController; 4061 } else { 4062 return mGattService == null ? null : mGattService.getScanController(); 4063 } 4064 } 4065 4066 @Nullable getBluetoothAdvertise()4067 IBinder getBluetoothAdvertise() { 4068 return mGattService == null ? null : mGattService.getBluetoothAdvertise(); 4069 } 4070 4071 @Nullable getDistanceMeasurement()4072 IBinder getDistanceMeasurement() { 4073 return mGattService == null ? null : mGattService.getDistanceMeasurement(); 4074 } 4075 4076 @RequiresPermission(BLUETOOTH_CONNECT) unregAllGattClient(AttributionSource source)4077 void unregAllGattClient(AttributionSource source) { 4078 if (mGattService != null) { 4079 mGattService.unregAll(source); 4080 } 4081 } 4082 getProfile(int profileId)4083 IBinder getProfile(int profileId) { 4084 if (getState() == BluetoothAdapter.STATE_TURNING_ON) { 4085 return null; 4086 } 4087 4088 // LE_AUDIO_BROADCAST is not associated with a service and use LE_AUDIO's Binder 4089 if (profileId == BluetoothProfile.LE_AUDIO_BROADCAST) { 4090 profileId = BluetoothProfile.LE_AUDIO; 4091 } 4092 4093 ProfileService profile = mStartedProfiles.get(profileId); 4094 if (profile != null) { 4095 return profile.getBinder(); 4096 } else { 4097 return null; 4098 } 4099 } 4100 isMediaProfileConnected()4101 boolean isMediaProfileConnected() { 4102 if (mA2dpService != null && mA2dpService.getConnectedDevices().size() > 0) { 4103 Log.d(TAG, "isMediaProfileConnected. A2dp is connected"); 4104 return true; 4105 } else if (mHearingAidService != null 4106 && mHearingAidService.getConnectedDevices().size() > 0) { 4107 Log.d(TAG, "isMediaProfileConnected. HearingAid is connected"); 4108 return true; 4109 } else if (mLeAudioService != null && mLeAudioService.getConnectedDevices().size() > 0) { 4110 Log.d(TAG, "isMediaProfileConnected. LeAudio is connected"); 4111 return true; 4112 } else { 4113 Log.d( 4114 TAG, 4115 "isMediaProfileConnected: no Media connected." 4116 + (" A2dp=" + mA2dpService) 4117 + (" HearingAid=" + mHearingAidService) 4118 + (" LeAudio=" + mLeAudioService)); 4119 return false; 4120 } 4121 } 4122 updatePhonePolicyOnAclConnect(BluetoothDevice device)4123 void updatePhonePolicyOnAclConnect(BluetoothDevice device) { 4124 mPhonePolicy.ifPresent(policy -> policy.handleAclConnected(device)); 4125 } 4126 4127 /** 4128 * Notify {@link BluetoothProfile} when ACL connection disconnects from {@link BluetoothDevice} 4129 * for a given {@code transport}. 4130 */ notifyAclDisconnected(BluetoothDevice device, int transport)4131 public void notifyAclDisconnected(BluetoothDevice device, int transport) { 4132 if (mMapService != null && mMapService.isAvailable()) { 4133 mMapService.aclDisconnected(device); 4134 } 4135 if (mMapClientService != null && mMapClientService.isAvailable()) { 4136 mMapClientService.aclDisconnected(device, transport); 4137 } 4138 if (mSapService != null && mSapService.isAvailable()) { 4139 mSapService.aclDisconnected(device); 4140 } 4141 if (mPbapClientService != null && mPbapClientService.isAvailable()) { 4142 mPbapClientService.aclDisconnected(device, transport); 4143 } 4144 } 4145 4146 /** 4147 * Notify GATT of a Bluetooth profile's connection state change for a given {@link 4148 * BluetoothProfile}. 4149 */ notifyProfileConnectionStateChangeToGatt(int profile, int fromState, int toState)4150 public void notifyProfileConnectionStateChangeToGatt(int profile, int fromState, int toState) { 4151 if (mGattService == null) { 4152 Log.w(TAG, "GATT Service is not running!"); 4153 return; 4154 } 4155 ScanController controller = getBluetoothScanController(); 4156 if (controller != null) { 4157 controller.notifyProfileConnectionStateChange(profile, fromState, toState); 4158 } 4159 } 4160 4161 /** 4162 * Handle Bluetooth app state when connection state changes for a given {@code profile}. 4163 * 4164 * <p>Currently this function is limited to handling Phone policy but the eventual goal is to 4165 * move all connection logic here. 4166 */ handleProfileConnectionStateChange( int profile, BluetoothDevice device, int fromState, int toState)4167 public void handleProfileConnectionStateChange( 4168 int profile, BluetoothDevice device, int fromState, int toState) { 4169 mPhonePolicy.ifPresent( 4170 policy -> 4171 policy.profileConnectionStateChanged(profile, device, fromState, toState)); 4172 } 4173 4174 /** Handle Bluetooth app state when active device changes for a given {@code profile}. */ handleActiveDeviceChange(int profile, BluetoothDevice device)4175 public void handleActiveDeviceChange(int profile, BluetoothDevice device) { 4176 mActiveDeviceManager.profileActiveDeviceChanged(profile, device); 4177 mSilenceDeviceManager.profileActiveDeviceChanged(profile, device); 4178 mPhonePolicy.ifPresent(policy -> policy.profileActiveDeviceChanged(profile, device)); 4179 } 4180 4181 /** Notify MAP and Pbap when a new sdp search record is found. */ sendSdpSearchRecord( BluetoothDevice device, int status, Parcelable record, ParcelUuid uuid)4182 public void sendSdpSearchRecord( 4183 BluetoothDevice device, int status, Parcelable record, ParcelUuid uuid) { 4184 if (mMapService != null && mMapService.isAvailable()) { 4185 mMapService.receiveSdpSearchRecord(status, record, uuid); 4186 } 4187 if (mMapClientService != null && mMapClientService.isAvailable()) { 4188 mMapClientService.receiveSdpSearchRecord(device, status, record, uuid); 4189 } 4190 if (mPbapClientService != null && mPbapClientService.isAvailable()) { 4191 mPbapClientService.receiveSdpSearchRecord(device, status, record, uuid); 4192 } 4193 } 4194 4195 /** Handle Bluetooth profiles when bond state changes with a {@link BluetoothDevice} */ handleBondStateChanged(BluetoothDevice device, int fromState, int toState)4196 public void handleBondStateChanged(BluetoothDevice device, int fromState, int toState) { 4197 if (mHeadsetService != null && mHeadsetService.isAvailable()) { 4198 mHeadsetService.handleBondStateChanged(device, fromState, toState); 4199 } 4200 if (mA2dpService != null && mA2dpService.isAvailable()) { 4201 mA2dpService.handleBondStateChanged(device, fromState, toState); 4202 } 4203 if (mLeAudioService != null && mLeAudioService.isAvailable()) { 4204 mLeAudioService.handleBondStateChanged(device, fromState, toState); 4205 } 4206 if (mHearingAidService != null && mHearingAidService.isAvailable()) { 4207 mHearingAidService.handleBondStateChanged(device, fromState, toState); 4208 } 4209 if (mHapClientService != null && mHapClientService.isAvailable()) { 4210 mHapClientService.handleBondStateChanged(device, fromState, toState); 4211 } 4212 if (mBassClientService != null && mBassClientService.isAvailable()) { 4213 mBassClientService.handleBondStateChanged(device, fromState, toState); 4214 } 4215 if (mBatteryService != null && mBatteryService.isAvailable()) { 4216 mBatteryService.handleBondStateChanged(device, fromState, toState); 4217 } 4218 if (mVolumeControlService != null && mVolumeControlService.isAvailable()) { 4219 mVolumeControlService.handleBondStateChanged(device, fromState, toState); 4220 } 4221 if (mPbapService != null && mPbapService.isAvailable()) { 4222 mPbapService.handleBondStateChanged(device, fromState, toState); 4223 } 4224 if (mCsipSetCoordinatorService != null && mCsipSetCoordinatorService.isAvailable()) { 4225 mCsipSetCoordinatorService.handleBondStateChanged(device, fromState, toState); 4226 } 4227 mDatabaseManager.handleBondStateChanged(device, fromState, toState); 4228 4229 if (toState == BOND_NONE) { 4230 // Remove the permissions for unbonded devices 4231 setMessageAccessPermission(device, BluetoothDevice.ACCESS_UNKNOWN); 4232 setPhonebookAccessPermission(device, BluetoothDevice.ACCESS_UNKNOWN); 4233 setSimAccessPermission(device, BluetoothDevice.ACCESS_UNKNOWN); 4234 } 4235 } 4236 convertScanModeToHal(int mode)4237 static int convertScanModeToHal(int mode) { 4238 switch (mode) { 4239 case SCAN_MODE_NONE: 4240 return AbstractionLayer.BT_SCAN_MODE_NONE; 4241 case SCAN_MODE_CONNECTABLE: 4242 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE; 4243 case SCAN_MODE_CONNECTABLE_DISCOVERABLE: 4244 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE; 4245 } 4246 return -1; 4247 } 4248 convertScanModeFromHal(int mode)4249 static int convertScanModeFromHal(int mode) { 4250 switch (mode) { 4251 case AbstractionLayer.BT_SCAN_MODE_NONE: 4252 return SCAN_MODE_NONE; 4253 case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE: 4254 return SCAN_MODE_CONNECTABLE; 4255 case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE: 4256 return SCAN_MODE_CONNECTABLE_DISCOVERABLE; 4257 } 4258 return -1; 4259 } 4260 4261 // This function is called from JNI. It allows native code to acquire a single wake lock. 4262 // If the wake lock is already held, this function returns success. Although this function 4263 // only supports acquiring a single wake lock at a time right now, it will eventually be 4264 // extended to allow acquiring an arbitrary number of wake locks. The current interface 4265 // takes |lockName| as a parameter in anticipation of that implementation. acquireWakeLock(String lockName)4266 boolean acquireWakeLock(String lockName) { 4267 synchronized (this) { 4268 if (mWakeLock == null) { 4269 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, lockName); 4270 } 4271 4272 if (!mWakeLock.isHeld()) { 4273 mWakeLock.acquire(); 4274 } 4275 } 4276 return true; 4277 } 4278 4279 // This function is called from JNI. It allows native code to release a wake lock acquired 4280 // by |acquireWakeLock|. If the wake lock is not held, this function returns failure. 4281 // Note that the release() call is also invoked by {@link #cleanup()} so a synchronization is 4282 // needed here. See the comment for |acquireWakeLock| for an explanation of the interface. releaseWakeLock(String lockName)4283 boolean releaseWakeLock(String lockName) { 4284 synchronized (this) { 4285 if (mWakeLock == null) { 4286 Log.e(TAG, "Repeated wake lock release; aborting release: " + lockName); 4287 return false; 4288 } 4289 4290 if (mWakeLock.isHeld()) { 4291 mWakeLock.release(); 4292 } 4293 } 4294 return true; 4295 } 4296 energyInfoCallbackInternal( int status, int ctrlState, long txTime, long rxTime, long idleTime, long energyUsed, UidTraffic[] data)4297 void energyInfoCallbackInternal( 4298 int status, 4299 int ctrlState, 4300 long txTime, 4301 long rxTime, 4302 long idleTime, 4303 long energyUsed, 4304 UidTraffic[] data) { 4305 // Energy is product of mA, V and ms. If the chipset doesn't 4306 // report it, we have to compute it from time 4307 if (energyUsed == 0) { 4308 try { 4309 final long txMah = Math.multiplyExact(txTime, getTxCurrentMa()); 4310 final long rxMah = Math.multiplyExact(rxTime, getRxCurrentMa()); 4311 final long idleMah = Math.multiplyExact(idleTime, getIdleCurrentMa()); 4312 energyUsed = 4313 (long) 4314 (Math.addExact(Math.addExact(txMah, rxMah), idleMah) 4315 * getOperatingVolt()); 4316 } catch (ArithmeticException e) { 4317 Log.wtf(TAG, "overflow in bluetooth energy callback", e); 4318 // Energy is already 0 if the exception was thrown. 4319 } 4320 } 4321 4322 synchronized (mEnergyInfoLock) { 4323 mStackReportedState = ctrlState; 4324 long totalTxTimeMs; 4325 long totalRxTimeMs; 4326 long totalIdleTimeMs; 4327 long totalEnergy; 4328 try { 4329 totalTxTimeMs = Math.addExact(mTxTimeTotalMs, txTime); 4330 totalRxTimeMs = Math.addExact(mRxTimeTotalMs, rxTime); 4331 totalIdleTimeMs = Math.addExact(mIdleTimeTotalMs, idleTime); 4332 totalEnergy = Math.addExact(mEnergyUsedTotalVoltAmpSecMicro, energyUsed); 4333 } catch (ArithmeticException e) { 4334 // This could be because we accumulated a lot of time, or we got a very strange 4335 // value from the controller (more likely). Discard this data. 4336 Log.wtf(TAG, "overflow in bluetooth energy callback", e); 4337 totalTxTimeMs = mTxTimeTotalMs; 4338 totalRxTimeMs = mRxTimeTotalMs; 4339 totalIdleTimeMs = mIdleTimeTotalMs; 4340 totalEnergy = mEnergyUsedTotalVoltAmpSecMicro; 4341 } 4342 4343 mTxTimeTotalMs = totalTxTimeMs; 4344 mRxTimeTotalMs = totalRxTimeMs; 4345 mIdleTimeTotalMs = totalIdleTimeMs; 4346 mEnergyUsedTotalVoltAmpSecMicro = totalEnergy; 4347 4348 for (UidTraffic traffic : data) { 4349 UidTraffic existingTraffic = mUidTraffic.get(traffic.getUid()); 4350 if (existingTraffic == null) { 4351 mUidTraffic.put(traffic.getUid(), traffic); 4352 } else { 4353 existingTraffic.addRxBytes(traffic.getRxBytes()); 4354 existingTraffic.addTxBytes(traffic.getTxBytes()); 4355 } 4356 } 4357 mEnergyInfoLock.notifyAll(); 4358 } 4359 } 4360 energyInfoCallback( int status, int ctrlState, long txTime, long rxTime, long idleTime, long energyUsed, UidTraffic[] data)4361 void energyInfoCallback( 4362 int status, 4363 int ctrlState, 4364 long txTime, 4365 long rxTime, 4366 long idleTime, 4367 long energyUsed, 4368 UidTraffic[] data) { 4369 energyInfoCallbackInternal(status, ctrlState, txTime, rxTime, idleTime, energyUsed, data); 4370 Log.v( 4371 TAG, 4372 "energyInfoCallback()" 4373 + (" status = " + status) 4374 + (" txTime = " + txTime) 4375 + (" rxTime = " + rxTime) 4376 + (" idleTime = " + idleTime) 4377 + (" energyUsed = " + energyUsed) 4378 + (" ctrlState = " + Utils.formatSimple("0x%08x", ctrlState)) 4379 + (" traffic = " + Arrays.toString(data))); 4380 } 4381 4382 /** Update metadata change to registered listeners */ onMetadataChanged(BluetoothDevice device, int key, byte[] value)4383 public void onMetadataChanged(BluetoothDevice device, int key, byte[] value) { 4384 mHandler.post(() -> onMetadataChangedInternal(device, key, value)); 4385 } 4386 onMetadataChangedInternal(BluetoothDevice device, int key, byte[] value)4387 private void onMetadataChangedInternal(BluetoothDevice device, int key, byte[] value) { 4388 String info = "onMetadataChangedInternal(" + device + ", " + key + ")"; 4389 4390 // pass just interesting metadata to native, to reduce spam 4391 if (key == BluetoothDevice.METADATA_LE_AUDIO) { 4392 mNativeInterface.metadataChanged(device, key, value); 4393 } 4394 4395 RemoteCallbackList<IBluetoothMetadataListener> list = mMetadataListeners.get(device); 4396 if (list == null) { 4397 Log.d(TAG, info + ": No registered listener"); 4398 return; 4399 } 4400 int n = list.beginBroadcast(); 4401 Log.d(TAG, info + ": Broadcast to " + n + " receivers"); 4402 for (int i = 0; i < n; i++) { 4403 try { 4404 list.getBroadcastItem(i).onMetadataChanged(device, key, value); 4405 } catch (RemoteException e) { 4406 Log.d(TAG, info + ": Callback #" + i + " failed (" + e + ")"); 4407 } 4408 } 4409 list.finishBroadcast(); 4410 } 4411 getIdleCurrentMa()4412 private static int getIdleCurrentMa() { 4413 return BluetoothProperties.getHardwareIdleCurrentMa().orElse(0); 4414 } 4415 getTxCurrentMa()4416 private static int getTxCurrentMa() { 4417 return BluetoothProperties.getHardwareTxCurrentMa().orElse(0); 4418 } 4419 getRxCurrentMa()4420 private static int getRxCurrentMa() { 4421 return BluetoothProperties.getHardwareRxCurrentMa().orElse(0); 4422 } 4423 getOperatingVolt()4424 private static double getOperatingVolt() { 4425 return BluetoothProperties.getHardwareOperatingVoltageMv().orElse(0) / 1000.0; 4426 } 4427 scanModeName(int scanMode)4428 private static String scanModeName(int scanMode) { 4429 return switch (scanMode) { 4430 case SCAN_MODE_NONE -> "SCAN_MODE_NONE"; 4431 case SCAN_MODE_CONNECTABLE -> "SCAN_MODE_CONNECTABLE"; 4432 case SCAN_MODE_CONNECTABLE_DISCOVERABLE -> "SCAN_MODE_CONNECTABLE_DISCOVERABLE"; 4433 default -> "Unknown Scan Mode " + scanMode; 4434 }; 4435 } 4436 4437 @Override dump(FileDescriptor fd, PrintWriter writer, String[] args)4438 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 4439 if (args.length == 0) { 4440 writer.println("Skipping dump in APP SERVICES, see bluetooth_manager section."); 4441 writer.println("Use --print argument for dumpsys direct from AdapterService."); 4442 return; 4443 } 4444 4445 if ("set-test-mode".equals(args[0])) { 4446 final boolean testModeEnabled = "enabled".equalsIgnoreCase(args[1]); 4447 for (ProfileService profile : mRunningProfiles) { 4448 profile.setTestModeEnabled(testModeEnabled); 4449 } 4450 if (Flags.onlyStartScanDuringBleOn() && mScanController != null) { 4451 mScanController.setTestModeEnabled(testModeEnabled); 4452 } 4453 mTestModeEnabled = testModeEnabled; 4454 return; 4455 } 4456 4457 writer.println(); 4458 mAdapterProperties.dump(fd, writer, args); 4459 4460 writer.println("ScanMode: " + scanModeName(getScanMode())); 4461 StringBuilder sb = new StringBuilder(); 4462 mScanModeChanges.dump(sb); 4463 writer.println(sb.toString()); 4464 writer.println(); 4465 writer.println("sSnoopLogSettingAtEnable = " + sSnoopLogSettingAtEnable); 4466 writer.println("sDefaultSnoopLogSettingAtEnable = " + sDefaultSnoopLogSettingAtEnable); 4467 4468 writer.println(); 4469 writer.println("Enabled Profile Services:"); 4470 for (int profileId : Config.getSupportedProfiles()) { 4471 writer.println(" " + BluetoothProfile.getProfileName(profileId)); 4472 } 4473 writer.println(); 4474 4475 writer.println("LE Gatt clients controlling AutoActiveMode:"); 4476 for (Pair<Integer, BluetoothDevice> pair : mLeGattClientsControllingAutoActiveMode) { 4477 writer.println(" clientIf:" + pair.first + " " + pair.second); 4478 } 4479 writer.println(); 4480 4481 mAdapterStateMachine.dump(fd, writer, args); 4482 4483 sb = new StringBuilder(); 4484 4485 mSilenceDeviceManager.dump(sb); 4486 mDatabaseManager.dump(sb); 4487 4488 for (ProfileService profile : mRegisteredProfiles) { 4489 profile.dump(sb); 4490 } 4491 if (Flags.onlyStartScanDuringBleOn()) { 4492 ScanController scanController = mScanController; 4493 if (scanController != null) { 4494 scanController.dumpRegisterId(sb); 4495 scanController.dump(sb); 4496 } 4497 } 4498 4499 writer.write(sb.toString()); 4500 4501 final int currentState = mAdapterProperties.getState(); 4502 if (currentState == BluetoothAdapter.STATE_OFF 4503 || currentState == BluetoothAdapter.STATE_BLE_TURNING_ON 4504 || currentState == BluetoothAdapter.STATE_TURNING_OFF 4505 || currentState == BluetoothAdapter.STATE_BLE_TURNING_OFF) { 4506 writer.println(); 4507 writer.println("Impossible to dump native stack. state=" + nameForState(currentState)); 4508 writer.println(); 4509 writer.flush(); 4510 } else { 4511 writer.flush(); 4512 mNativeInterface.dump(fd, args); 4513 } 4514 } 4515 4516 private final Object mDeviceConfigLock = new Object(); 4517 4518 /** 4519 * Predicate that can be applied to names to determine if a device is well-known to be used for 4520 * physical location. 4521 */ 4522 @GuardedBy("mDeviceConfigLock") 4523 private Predicate<String> mLocationDenylistName = (v) -> false; 4524 4525 /** 4526 * Predicate that can be applied to MAC addresses to determine if a device is well-known to be 4527 * used for physical location. 4528 */ 4529 @GuardedBy("mDeviceConfigLock") 4530 private Predicate<byte[]> mLocationDenylistMac = (v) -> false; 4531 4532 /** 4533 * Predicate that can be applied to Advertising Data payloads to determine if a device is 4534 * well-known to be used for physical location. 4535 */ 4536 @GuardedBy("mDeviceConfigLock") 4537 private Predicate<byte[]> mLocationDenylistAdvertisingData = (v) -> false; 4538 4539 @GuardedBy("mDeviceConfigLock") 4540 private int mScanQuotaCount = DeviceConfigListener.DEFAULT_SCAN_QUOTA_COUNT; 4541 4542 @GuardedBy("mDeviceConfigLock") 4543 private long mScanQuotaWindowMillis = DeviceConfigListener.DEFAULT_SCAN_QUOTA_WINDOW_MILLIS; 4544 4545 @GuardedBy("mDeviceConfigLock") 4546 private long mScanTimeoutMillis = DeviceConfigListener.DEFAULT_SCAN_TIMEOUT_MILLIS; 4547 4548 @GuardedBy("mDeviceConfigLock") 4549 private int mScanUpgradeDurationMillis = 4550 DeviceConfigListener.DEFAULT_SCAN_UPGRADE_DURATION_MILLIS; 4551 4552 @GuardedBy("mDeviceConfigLock") 4553 private int mScanDowngradeDurationMillis = 4554 DeviceConfigListener.DEFAULT_SCAN_DOWNGRADE_DURATION_BT_CONNECTING_MILLIS; 4555 4556 @GuardedBy("mDeviceConfigLock") 4557 private int mScreenOffLowPowerWindowMillis = 4558 ScanManager.SCAN_MODE_SCREEN_OFF_LOW_POWER_WINDOW_MS; 4559 4560 @GuardedBy("mDeviceConfigLock") 4561 private int mScreenOffLowPowerIntervalMillis = 4562 ScanManager.SCAN_MODE_SCREEN_OFF_LOW_POWER_INTERVAL_MS; 4563 4564 @GuardedBy("mDeviceConfigLock") 4565 private int mScreenOffBalancedWindowMillis = 4566 ScanManager.SCAN_MODE_SCREEN_OFF_BALANCED_WINDOW_MS; 4567 4568 @GuardedBy("mDeviceConfigLock") 4569 private int mScreenOffBalancedIntervalMillis = 4570 ScanManager.SCAN_MODE_SCREEN_OFF_BALANCED_INTERVAL_MS; 4571 4572 @GuardedBy("mDeviceConfigLock") 4573 private String mLeAudioAllowList; 4574 getLocationDenylistName()4575 public @NonNull Predicate<String> getLocationDenylistName() { 4576 synchronized (mDeviceConfigLock) { 4577 return mLocationDenylistName; 4578 } 4579 } 4580 getLocationDenylistMac()4581 public @NonNull Predicate<byte[]> getLocationDenylistMac() { 4582 synchronized (mDeviceConfigLock) { 4583 return mLocationDenylistMac; 4584 } 4585 } 4586 getLocationDenylistAdvertisingData()4587 public @NonNull Predicate<byte[]> getLocationDenylistAdvertisingData() { 4588 synchronized (mDeviceConfigLock) { 4589 return mLocationDenylistAdvertisingData; 4590 } 4591 } 4592 4593 /** Returns scan quota count. */ getScanQuotaCount()4594 public int getScanQuotaCount() { 4595 synchronized (mDeviceConfigLock) { 4596 return mScanQuotaCount; 4597 } 4598 } 4599 4600 /** Returns scan quota window in millis. */ getScanQuotaWindowMillis()4601 public long getScanQuotaWindowMillis() { 4602 synchronized (mDeviceConfigLock) { 4603 return mScanQuotaWindowMillis; 4604 } 4605 } 4606 4607 /** Returns scan timeout in millis. */ getScanTimeoutMillis()4608 public long getScanTimeoutMillis() { 4609 synchronized (mDeviceConfigLock) { 4610 return mScanTimeoutMillis; 4611 } 4612 } 4613 4614 /** Returns scan upgrade duration in millis. */ getScanUpgradeDurationMillis()4615 public int getScanUpgradeDurationMillis() { 4616 synchronized (mDeviceConfigLock) { 4617 return mScanUpgradeDurationMillis; 4618 } 4619 } 4620 4621 /** Returns scan downgrade duration in millis. */ getScanDowngradeDurationMillis()4622 public int getScanDowngradeDurationMillis() { 4623 synchronized (mDeviceConfigLock) { 4624 return mScanDowngradeDurationMillis; 4625 } 4626 } 4627 4628 /** Returns SCREEN_OFF_BALANCED scan window in millis. */ getScreenOffBalancedWindowMillis()4629 public int getScreenOffBalancedWindowMillis() { 4630 synchronized (mDeviceConfigLock) { 4631 return mScreenOffBalancedWindowMillis; 4632 } 4633 } 4634 4635 /** Returns SCREEN_OFF_BALANCED scan interval in millis. */ getScreenOffBalancedIntervalMillis()4636 public int getScreenOffBalancedIntervalMillis() { 4637 synchronized (mDeviceConfigLock) { 4638 return mScreenOffBalancedIntervalMillis; 4639 } 4640 } 4641 4642 /** Returns SCREEN_OFF low power scan window in millis. */ getScreenOffLowPowerWindowMillis()4643 public int getScreenOffLowPowerWindowMillis() { 4644 synchronized (mDeviceConfigLock) { 4645 return mScreenOffLowPowerWindowMillis; 4646 } 4647 } 4648 4649 /** Returns SCREEN_OFF low power scan interval in millis. */ getScreenOffLowPowerIntervalMillis()4650 public int getScreenOffLowPowerIntervalMillis() { 4651 synchronized (mDeviceConfigLock) { 4652 return mScreenOffLowPowerIntervalMillis; 4653 } 4654 } 4655 4656 @VisibleForTesting 4657 public class DeviceConfigListener implements DeviceConfig.OnPropertiesChangedListener { 4658 private static final String LOCATION_DENYLIST_NAME = "location_denylist_name"; 4659 private static final String LOCATION_DENYLIST_MAC = "location_denylist_mac"; 4660 private static final String LOCATION_DENYLIST_ADVERTISING_DATA = 4661 "location_denylist_advertising_data"; 4662 private static final String SCAN_QUOTA_COUNT = "scan_quota_count"; 4663 private static final String SCAN_QUOTA_WINDOW_MILLIS = "scan_quota_window_millis"; 4664 private static final String SCAN_TIMEOUT_MILLIS = "scan_timeout_millis"; 4665 private static final String SCAN_UPGRADE_DURATION_MILLIS = "scan_upgrade_duration_millis"; 4666 private static final String SCAN_DOWNGRADE_DURATION_MILLIS = 4667 "scan_downgrade_duration_millis"; 4668 private static final String SCREEN_OFF_LOW_POWER_WINDOW_MILLIS = 4669 "screen_off_low_power_window_millis"; 4670 private static final String SCREEN_OFF_LOW_POWER_INTERVAL_MILLIS = 4671 "screen_off_low_power_interval_millis"; 4672 private static final String SCREEN_OFF_BALANCED_WINDOW_MILLIS = 4673 "screen_off_balanced_window_millis"; 4674 private static final String SCREEN_OFF_BALANCED_INTERVAL_MILLIS = 4675 "screen_off_balanced_interval_millis"; 4676 private static final String LE_AUDIO_ALLOW_LIST = "le_audio_allow_list"; 4677 4678 /** 4679 * Default denylist which matches Eddystone (except for Eddystone-E2EE-EID) and iBeacon 4680 * payloads. 4681 */ 4682 private static final String DEFAULT_LOCATION_DENYLIST_ADVERTISING_DATA = 4683 "⊈0016AAFE40/00FFFFFFF0,⊆0016AAFE/00FFFFFF,⊆00FF4C0002/00FFFFFFFF"; 4684 4685 private static final int DEFAULT_SCAN_QUOTA_COUNT = 5; 4686 private static final long DEFAULT_SCAN_QUOTA_WINDOW_MILLIS = 30 * SECOND_IN_MILLIS; 4687 4688 @VisibleForTesting 4689 public static final long DEFAULT_SCAN_TIMEOUT_MILLIS = 10 * MINUTE_IN_MILLIS; 4690 4691 @VisibleForTesting 4692 public static final int DEFAULT_SCAN_UPGRADE_DURATION_MILLIS = (int) SECOND_IN_MILLIS * 6; 4693 4694 @VisibleForTesting 4695 public static final int DEFAULT_SCAN_DOWNGRADE_DURATION_BT_CONNECTING_MILLIS = 4696 (int) SECOND_IN_MILLIS * 6; 4697 start()4698 public void start() { 4699 DeviceConfig.addOnPropertiesChangedListener( 4700 DeviceConfig.NAMESPACE_BLUETOOTH, BackgroundThread.getExecutor(), this); 4701 onPropertiesChanged(DeviceConfig.getProperties(DeviceConfig.NAMESPACE_BLUETOOTH)); 4702 } 4703 4704 @Override onPropertiesChanged(DeviceConfig.Properties properties)4705 public void onPropertiesChanged(DeviceConfig.Properties properties) { 4706 synchronized (mDeviceConfigLock) { 4707 final String name = properties.getString(LOCATION_DENYLIST_NAME, null); 4708 mLocationDenylistName = 4709 !TextUtils.isEmpty(name) 4710 ? Pattern.compile(name).asPredicate() 4711 : (v) -> false; 4712 mLocationDenylistMac = 4713 BytesMatcher.decode(properties.getString(LOCATION_DENYLIST_MAC, null)); 4714 mLocationDenylistAdvertisingData = 4715 BytesMatcher.decode( 4716 properties.getString( 4717 LOCATION_DENYLIST_ADVERTISING_DATA, 4718 DEFAULT_LOCATION_DENYLIST_ADVERTISING_DATA)); 4719 mScanQuotaCount = properties.getInt(SCAN_QUOTA_COUNT, DEFAULT_SCAN_QUOTA_COUNT); 4720 mScanQuotaWindowMillis = 4721 properties.getLong( 4722 SCAN_QUOTA_WINDOW_MILLIS, DEFAULT_SCAN_QUOTA_WINDOW_MILLIS); 4723 mScanTimeoutMillis = 4724 properties.getLong(SCAN_TIMEOUT_MILLIS, DEFAULT_SCAN_TIMEOUT_MILLIS); 4725 mScanUpgradeDurationMillis = 4726 properties.getInt( 4727 SCAN_UPGRADE_DURATION_MILLIS, DEFAULT_SCAN_UPGRADE_DURATION_MILLIS); 4728 mScanDowngradeDurationMillis = 4729 properties.getInt( 4730 SCAN_DOWNGRADE_DURATION_MILLIS, 4731 DEFAULT_SCAN_DOWNGRADE_DURATION_BT_CONNECTING_MILLIS); 4732 mScreenOffLowPowerWindowMillis = 4733 properties.getInt( 4734 SCREEN_OFF_LOW_POWER_WINDOW_MILLIS, 4735 ScanManager.SCAN_MODE_SCREEN_OFF_LOW_POWER_WINDOW_MS); 4736 mScreenOffLowPowerIntervalMillis = 4737 properties.getInt( 4738 SCREEN_OFF_LOW_POWER_INTERVAL_MILLIS, 4739 ScanManager.SCAN_MODE_SCREEN_OFF_LOW_POWER_INTERVAL_MS); 4740 mScreenOffBalancedWindowMillis = 4741 properties.getInt( 4742 SCREEN_OFF_BALANCED_WINDOW_MILLIS, 4743 ScanManager.SCAN_MODE_SCREEN_OFF_BALANCED_WINDOW_MS); 4744 mScreenOffBalancedIntervalMillis = 4745 properties.getInt( 4746 SCREEN_OFF_BALANCED_INTERVAL_MILLIS, 4747 ScanManager.SCAN_MODE_SCREEN_OFF_BALANCED_INTERVAL_MS); 4748 mLeAudioAllowList = properties.getString(LE_AUDIO_ALLOW_LIST, ""); 4749 4750 if (!mLeAudioAllowList.isEmpty()) { 4751 List<String> leAudioAllowlistFromDeviceConfig = 4752 Arrays.asList(mLeAudioAllowList.split(",")); 4753 BluetoothProperties.le_audio_allow_list(leAudioAllowlistFromDeviceConfig); 4754 } 4755 4756 List<String> leAudioAllowlistProp = BluetoothProperties.le_audio_allow_list(); 4757 if (leAudioAllowlistProp != null && !leAudioAllowlistProp.isEmpty()) { 4758 mLeAudioAllowDevices.clear(); 4759 mLeAudioAllowDevices.addAll(leAudioAllowlistProp); 4760 } 4761 } 4762 } 4763 } 4764 4765 /** A callback that will be called when AdapterState is changed */ 4766 public interface BluetoothStateCallback { 4767 /** 4768 * Called when the status of bluetooth adapter is changing. {@code prevState} and {@code 4769 * newState} takes one of following values defined in BluetoothAdapter.java: STATE_OFF, 4770 * STATE_TURNING_ON, STATE_ON, STATE_TURNING_OFF, STATE_BLE_TURNING_ON, STATE_BLE_ON, 4771 * STATE_BLE_TURNING_OFF 4772 * 4773 * @param prevState the previous Bluetooth state. 4774 * @param newState the new Bluetooth state. 4775 */ onBluetoothStateChange(int prevState, int newState)4776 void onBluetoothStateChange(int prevState, int newState); 4777 } 4778 4779 /** 4780 * Obfuscate Bluetooth MAC address into a PII free ID string 4781 * 4782 * @param device Bluetooth device whose MAC address will be obfuscated 4783 * @return a byte array that is unique to this MAC address on this device, or empty byte array 4784 * when either device is null or obfuscateAddressNative fails 4785 */ obfuscateAddress(BluetoothDevice device)4786 public byte[] obfuscateAddress(BluetoothDevice device) { 4787 if (device == null) { 4788 return new byte[0]; 4789 } 4790 return mNativeInterface.obfuscateAddress(Utils.getByteAddress(device)); 4791 } 4792 4793 /** 4794 * Get dynamic audio buffer size supported type 4795 * 4796 * @return support 4797 * <p>Possible values are {@link BluetoothA2dp#DYNAMIC_BUFFER_SUPPORT_NONE}, {@link 4798 * BluetoothA2dp#DYNAMIC_BUFFER_SUPPORT_A2DP_OFFLOAD}, {@link 4799 * BluetoothA2dp#DYNAMIC_BUFFER_SUPPORT_A2DP_SOFTWARE_ENCODING}. 4800 */ getDynamicBufferSupport()4801 public int getDynamicBufferSupport() { 4802 return mAdapterProperties.getDynamicBufferSupport(); 4803 } 4804 4805 /** 4806 * Get dynamic audio buffer size 4807 * 4808 * @return BufferConstraints 4809 */ getBufferConstraints()4810 public BufferConstraints getBufferConstraints() { 4811 return mAdapterProperties.getBufferConstraints(); 4812 } 4813 4814 /** 4815 * Set dynamic audio buffer size 4816 * 4817 * @param codec Audio codec 4818 * @param value buffer millis 4819 * @return true if the settings is successful, false otherwise 4820 */ setBufferLengthMillis(int codec, int value)4821 public boolean setBufferLengthMillis(int codec, int value) { 4822 return mAdapterProperties.setBufferLengthMillis(codec, value); 4823 } 4824 4825 /** 4826 * Get an incremental id of Bluetooth metrics and log 4827 * 4828 * @param device Bluetooth device 4829 * @return int of id for Bluetooth metrics and logging, 0 if the device is invalid 4830 */ getMetricId(BluetoothDevice device)4831 public int getMetricId(BluetoothDevice device) { 4832 if (device == null) { 4833 return 0; 4834 } 4835 return mNativeInterface.getMetricId(Utils.getByteAddress(device)); 4836 } 4837 getCompanionManager()4838 public CompanionManager getCompanionManager() { 4839 return mBtCompanionManager; 4840 } 4841 4842 /** 4843 * Call for the AdapterService receives bond state change 4844 * 4845 * @param device Bluetooth device 4846 * @param state bond state 4847 */ onBondStateChanged(BluetoothDevice device, int state)4848 public void onBondStateChanged(BluetoothDevice device, int state) { 4849 if (mBtCompanionManager != null) { 4850 mBtCompanionManager.onBondStateChanged(device, state); 4851 } 4852 } 4853 4854 /** 4855 * Get audio policy feature support status 4856 * 4857 * @param device Bluetooth device to be checked for audio policy support 4858 * @return int status of the remote support for audio policy feature 4859 */ isRequestAudioPolicyAsSinkSupported(BluetoothDevice device)4860 public int isRequestAudioPolicyAsSinkSupported(BluetoothDevice device) { 4861 if (mHeadsetClientService != null) { 4862 return mHeadsetClientService.getAudioPolicyRemoteSupported(device); 4863 } else { 4864 Log.e(TAG, "No audio transport connected"); 4865 return BluetoothStatusCodes.FEATURE_NOT_CONFIGURED; 4866 } 4867 } 4868 4869 /** 4870 * Set audio policy for remote device 4871 * 4872 * @param device Bluetooth device to be set policy for 4873 * @return int result status for requestAudioPolicyAsSink API 4874 */ requestAudioPolicyAsSink(BluetoothDevice device, BluetoothSinkAudioPolicy policies)4875 public int requestAudioPolicyAsSink(BluetoothDevice device, BluetoothSinkAudioPolicy policies) { 4876 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 4877 if (deviceProp == null) { 4878 return BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED; 4879 } 4880 4881 if (mHeadsetClientService != null) { 4882 if (isRequestAudioPolicyAsSinkSupported(device) 4883 != BluetoothStatusCodes.FEATURE_SUPPORTED) { 4884 throw new UnsupportedOperationException( 4885 "Request Audio Policy As Sink not supported"); 4886 } 4887 deviceProp.setHfAudioPolicyForRemoteAg(policies); 4888 mHeadsetClientService.setAudioPolicy(device, policies); 4889 return BluetoothStatusCodes.SUCCESS; 4890 } else { 4891 Log.e(TAG, "HeadsetClient not connected"); 4892 return BluetoothStatusCodes.ERROR_PROFILE_NOT_CONNECTED; 4893 } 4894 } 4895 4896 /** 4897 * Get audio policy for remote device 4898 * 4899 * @param device Bluetooth device to be set policy for 4900 * @return {@link BluetoothSinkAudioPolicy} policy stored for the device 4901 */ getRequestedAudioPolicyAsSink(BluetoothDevice device)4902 public BluetoothSinkAudioPolicy getRequestedAudioPolicyAsSink(BluetoothDevice device) { 4903 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 4904 if (deviceProp == null) { 4905 return null; 4906 } 4907 4908 if (mHeadsetClientService != null) { 4909 return deviceProp.getHfAudioPolicyForRemoteAg(); 4910 } else { 4911 Log.e(TAG, "HeadsetClient not connected"); 4912 return null; 4913 } 4914 } 4915 4916 /** 4917 * Allow audio low latency 4918 * 4919 * @param allowed true if audio low latency is being allowed 4920 * @param device device whose audio low latency will be allowed or disallowed 4921 * @return boolean true if audio low latency is successfully allowed or disallowed 4922 */ allowLowLatencyAudio(boolean allowed, BluetoothDevice device)4923 public boolean allowLowLatencyAudio(boolean allowed, BluetoothDevice device) { 4924 return mNativeInterface.allowLowLatencyAudio(allowed, Utils.getByteAddress(device)); 4925 } 4926 4927 /** 4928 * get remote PBAP PCE version. 4929 * 4930 * @param address of remote device 4931 * @return int value other than 0 if remote PBAP PCE version is found 4932 */ getRemotePbapPceVersion(String address)4933 public int getRemotePbapPceVersion(String address) { 4934 return mNativeInterface.getRemotePbapPceVersion(address); 4935 } 4936 4937 /** 4938 * check, if PBAP PSE dynamic version upgrade is enabled. 4939 * 4940 * @return true/false. 4941 */ pbapPseDynamicVersionUpgradeIsEnabled()4942 public boolean pbapPseDynamicVersionUpgradeIsEnabled() { 4943 return mNativeInterface.pbapPseDynamicVersionUpgradeIsEnabled(); 4944 } 4945 4946 /** Sets the battery level of the remote device */ setBatteryLevel(BluetoothDevice device, int batteryLevel, boolean isBas)4947 public void setBatteryLevel(BluetoothDevice device, int batteryLevel, boolean isBas) { 4948 if (batteryLevel == BATTERY_LEVEL_UNKNOWN) { 4949 mRemoteDevices.resetBatteryLevel(device, isBas); 4950 } else { 4951 mRemoteDevices.updateBatteryLevel(device, batteryLevel, isBas); 4952 } 4953 } 4954 interopMatchAddr(InteropFeature feature, String address)4955 public boolean interopMatchAddr(InteropFeature feature, String address) { 4956 return mNativeInterface.interopMatchAddr(feature.name(), address); 4957 } 4958 interopMatchName(InteropFeature feature, String name)4959 public boolean interopMatchName(InteropFeature feature, String name) { 4960 return mNativeInterface.interopMatchName(feature.name(), name); 4961 } 4962 interopMatchAddrOrName(InteropFeature feature, String address)4963 public boolean interopMatchAddrOrName(InteropFeature feature, String address) { 4964 return mNativeInterface.interopMatchAddrOrName(feature.name(), address); 4965 } 4966 interopDatabaseAddAddr(InteropFeature feature, String address, int length)4967 public void interopDatabaseAddAddr(InteropFeature feature, String address, int length) { 4968 mNativeInterface.interopDatabaseAddRemoveAddr(true, feature.name(), address, length); 4969 } 4970 interopDatabaseRemoveAddr(InteropFeature feature, String address)4971 public void interopDatabaseRemoveAddr(InteropFeature feature, String address) { 4972 mNativeInterface.interopDatabaseAddRemoveAddr(false, feature.name(), address, 0); 4973 } 4974 interopDatabaseAddName(InteropFeature feature, String name)4975 public void interopDatabaseAddName(InteropFeature feature, String name) { 4976 mNativeInterface.interopDatabaseAddRemoveName(true, feature.name(), name); 4977 } 4978 interopDatabaseRemoveName(InteropFeature feature, String name)4979 public void interopDatabaseRemoveName(InteropFeature feature, String name) { 4980 mNativeInterface.interopDatabaseAddRemoveName(false, feature.name(), name); 4981 } 4982 4983 /** 4984 * Checks the remote device is in the LE Audio allow list or not. 4985 * 4986 * @param device the device to check 4987 * @return boolean true if the device is in the allow list, false otherwise. 4988 */ isLeAudioAllowed(BluetoothDevice device)4989 public boolean isLeAudioAllowed(BluetoothDevice device) { 4990 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 4991 4992 if (deviceProp == null 4993 || deviceProp.getModelName() == null 4994 || !mLeAudioAllowDevices.contains(deviceProp.getModelName())) { 4995 4996 return false; 4997 } 4998 4999 return true; 5000 } 5001 5002 /** 5003 * Get type of the remote device 5004 * 5005 * @param device the device to check 5006 * @return int device type 5007 */ getRemoteType(BluetoothDevice device)5008 public int getRemoteType(BluetoothDevice device) { 5009 return mRemoteDevices.getType(device); 5010 } 5011 5012 /** 5013 * Sends service discovery UUIDs internally within the stack. This is meant to remove internal 5014 * dependencies on the broadcast {@link BluetoothDevice#ACTION_UUID}. 5015 * 5016 * @param device is the remote device whose UUIDs have been discovered 5017 * @param uuids are the services supported on the remote device 5018 */ sendUuidsInternal(BluetoothDevice device, ParcelUuid[] uuids)5019 void sendUuidsInternal(BluetoothDevice device, ParcelUuid[] uuids) { 5020 if (device == null) { 5021 Log.w(TAG, "sendUuidsInternal: null device"); 5022 return; 5023 } 5024 if (uuids == null) { 5025 Log.w(TAG, "sendUuidsInternal: uuids is null"); 5026 return; 5027 } 5028 Log.i(TAG, "sendUuidsInternal: Received service discovery UUIDs for device " + device); 5029 for (int i = 0; i < uuids.length; i++) { 5030 Log.d(TAG, "sendUuidsInternal: index=" + i + " uuid=" + uuids[i]); 5031 } 5032 mPhonePolicy.ifPresent(policy -> policy.onUuidsDiscovered(device, uuids)); 5033 } 5034 5035 /** Clear storage */ clearStorage()5036 void clearStorage() { 5037 deleteDirectoryContents("/data/misc/bluedroid/"); 5038 deleteDirectoryContents("/data/misc/bluetooth/"); 5039 } 5040 deleteDirectoryContents(String dirPath)5041 private static void deleteDirectoryContents(String dirPath) { 5042 Path directoryPath = Paths.get(dirPath); 5043 try { 5044 Files.walkFileTree( 5045 directoryPath, 5046 new SimpleFileVisitor<Path>() { 5047 @Override 5048 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) 5049 throws IOException { 5050 Files.delete(file); 5051 return FileVisitResult.CONTINUE; 5052 } 5053 5054 @Override 5055 public FileVisitResult postVisitDirectory(Path dir, IOException ex) 5056 throws IOException { 5057 if (ex != null) { 5058 Log.e(TAG, "Error happened while removing contents. ", ex); 5059 } 5060 5061 if (!dir.equals(directoryPath)) { 5062 try { 5063 Files.delete(dir); 5064 } catch (Exception e) { 5065 Log.e(TAG, "Error happened while removing directory: ", e); 5066 } 5067 } 5068 return FileVisitResult.CONTINUE; 5069 } 5070 }); 5071 Log.i(TAG, "deleteDirectoryContents() completed. Path: " + dirPath); 5072 } catch (Exception e) { 5073 Log.e(TAG, "Error happened while removing contents: ", e); 5074 } 5075 } 5076 5077 /** Get the number of the supported offloaded LE COC sockets. */ getNumberOfSupportedOffloadedLeCocSockets()5078 public int getNumberOfSupportedOffloadedLeCocSockets() { 5079 return mAdapterProperties.getNumberOfSupportedOffloadedLeCocSockets(); 5080 } 5081 5082 /** Check if the offloaded LE COC socket is supported. */ isLeCocSocketOffloadSupported()5083 public boolean isLeCocSocketOffloadSupported() { 5084 int val = getNumberOfSupportedOffloadedLeCocSockets(); 5085 return val > 0; 5086 } 5087 5088 /** Get the number of the supported offloaded RFCOMM sockets. */ getNumberOfSupportedOffloadedRfcommSockets()5089 public int getNumberOfSupportedOffloadedRfcommSockets() { 5090 return mAdapterProperties.getNumberOfSupportedOffloadedRfcommSockets(); 5091 } 5092 5093 /** Check if the offloaded RFCOMM socket is supported. */ isRfcommSocketOffloadSupported()5094 public boolean isRfcommSocketOffloadSupported() { 5095 int val = getNumberOfSupportedOffloadedRfcommSockets(); 5096 return val > 0; 5097 } 5098 } 5099