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.bluetooth.BluetoothDevice.BATTERY_LEVEL_UNKNOWN; 21 import static android.bluetooth.BluetoothDevice.TRANSPORT_AUTO; 22 import static android.bluetooth.IBluetoothLeAudio.LE_AUDIO_GROUP_ID_INVALID; 23 import static android.text.format.DateUtils.MINUTE_IN_MILLIS; 24 import static android.text.format.DateUtils.SECOND_IN_MILLIS; 25 26 import static com.android.bluetooth.ChangeIds.ENFORCE_CONNECT; 27 import static com.android.bluetooth.Utils.callerIsSystem; 28 import static com.android.bluetooth.Utils.callerIsSystemOrActiveOrManagedUser; 29 import static com.android.bluetooth.Utils.enforceBluetoothPrivilegedPermission; 30 import static com.android.bluetooth.Utils.enforceCdmAssociation; 31 import static com.android.bluetooth.Utils.enforceDumpPermission; 32 import static com.android.bluetooth.Utils.enforceLocalMacAddressPermission; 33 import static com.android.bluetooth.Utils.getBytesFromAddress; 34 import static com.android.bluetooth.Utils.hasBluetoothPrivilegedPermission; 35 import static com.android.bluetooth.Utils.isDualModeAudioEnabled; 36 import static com.android.bluetooth.Utils.isPackageNameAccurate; 37 38 import static java.util.Objects.requireNonNull; 39 40 import android.annotation.NonNull; 41 import android.annotation.Nullable; 42 import android.annotation.RequiresPermission; 43 import android.annotation.SuppressLint; 44 import android.app.AppOpsManager; 45 import android.app.PendingIntent; 46 import android.app.Service; 47 import android.app.admin.DevicePolicyManager; 48 import android.app.compat.CompatChanges; 49 import android.bluetooth.BluetoothA2dp; 50 import android.bluetooth.BluetoothActivityEnergyInfo; 51 import android.bluetooth.BluetoothAdapter; 52 import android.bluetooth.BluetoothAdapter.ActiveDeviceProfile; 53 import android.bluetooth.BluetoothAdapter.ActiveDeviceUse; 54 import android.bluetooth.BluetoothDevice; 55 import android.bluetooth.BluetoothFrameworkInitializer; 56 import android.bluetooth.BluetoothMap; 57 import android.bluetooth.BluetoothProfile; 58 import android.bluetooth.BluetoothProtoEnums; 59 import android.bluetooth.BluetoothQualityReport; 60 import android.bluetooth.BluetoothSap; 61 import android.bluetooth.BluetoothServerSocket; 62 import android.bluetooth.BluetoothSinkAudioPolicy; 63 import android.bluetooth.BluetoothSocket; 64 import android.bluetooth.BluetoothStatusCodes; 65 import android.bluetooth.BluetoothUuid; 66 import android.bluetooth.BufferConstraints; 67 import android.bluetooth.IBluetooth; 68 import android.bluetooth.IBluetoothActivityEnergyInfoListener; 69 import android.bluetooth.IBluetoothCallback; 70 import android.bluetooth.IBluetoothConnectionCallback; 71 import android.bluetooth.IBluetoothMetadataListener; 72 import android.bluetooth.IBluetoothOobDataCallback; 73 import android.bluetooth.IBluetoothPreferredAudioProfilesCallback; 74 import android.bluetooth.IBluetoothQualityReportReadyCallback; 75 import android.bluetooth.IBluetoothSocketManager; 76 import android.bluetooth.IncomingRfcommSocketInfo; 77 import android.bluetooth.OobData; 78 import android.bluetooth.UidTraffic; 79 import android.bluetooth.rfcomm.BluetoothRfcommProtoEnums; 80 import android.companion.CompanionDeviceManager; 81 import android.content.AttributionSource; 82 import android.content.Context; 83 import android.content.Intent; 84 import android.content.SharedPreferences; 85 import android.content.pm.PackageManager; 86 import android.os.AsyncTask; 87 import android.os.BatteryStatsManager; 88 import android.os.Binder; 89 import android.os.Build; 90 import android.os.Bundle; 91 import android.os.Handler; 92 import android.os.IBinder; 93 import android.os.Looper; 94 import android.os.Message; 95 import android.os.ParcelUuid; 96 import android.os.Parcelable; 97 import android.os.PowerManager; 98 import android.os.Process; 99 import android.os.RemoteCallbackList; 100 import android.os.RemoteException; 101 import android.os.SystemClock; 102 import android.os.UserHandle; 103 import android.os.UserManager; 104 import android.provider.DeviceConfig; 105 import android.provider.Settings; 106 import android.sysprop.BluetoothProperties; 107 import android.text.TextUtils; 108 import android.util.Base64; 109 import android.util.Log; 110 import android.util.SparseArray; 111 112 import com.android.bluetooth.BluetoothMetricsProto; 113 import com.android.bluetooth.BluetoothStatsLog; 114 import com.android.bluetooth.R; 115 import com.android.bluetooth.Utils; 116 import com.android.bluetooth.a2dp.A2dpService; 117 import com.android.bluetooth.a2dpsink.A2dpSinkService; 118 import com.android.bluetooth.avrcp.AvrcpTargetService; 119 import com.android.bluetooth.avrcpcontroller.AvrcpControllerService; 120 import com.android.bluetooth.bas.BatteryService; 121 import com.android.bluetooth.bass_client.BassClientService; 122 import com.android.bluetooth.btservice.InteropUtil.InteropFeature; 123 import com.android.bluetooth.btservice.RemoteDevices.DeviceProperties; 124 import com.android.bluetooth.btservice.bluetoothkeystore.BluetoothKeystoreNativeInterface; 125 import com.android.bluetooth.btservice.bluetoothkeystore.BluetoothKeystoreService; 126 import com.android.bluetooth.btservice.storage.DatabaseManager; 127 import com.android.bluetooth.btservice.storage.MetadataDatabase; 128 import com.android.bluetooth.csip.CsipSetCoordinatorService; 129 import com.android.bluetooth.flags.Flags; 130 import com.android.bluetooth.gatt.GattService; 131 import com.android.bluetooth.hap.HapClientService; 132 import com.android.bluetooth.hearingaid.HearingAidService; 133 import com.android.bluetooth.hfp.HeadsetService; 134 import com.android.bluetooth.hfpclient.HeadsetClientService; 135 import com.android.bluetooth.hid.HidDeviceService; 136 import com.android.bluetooth.hid.HidHostService; 137 import com.android.bluetooth.le_audio.LeAudioService; 138 import com.android.bluetooth.le_scan.ScanController; 139 import com.android.bluetooth.le_scan.ScanManager; 140 import com.android.bluetooth.map.BluetoothMapService; 141 import com.android.bluetooth.mapclient.MapClientService; 142 import com.android.bluetooth.mcp.McpService; 143 import com.android.bluetooth.opp.BluetoothOppService; 144 import com.android.bluetooth.pan.PanService; 145 import com.android.bluetooth.pbap.BluetoothPbapService; 146 import com.android.bluetooth.pbapclient.PbapClientService; 147 import com.android.bluetooth.sap.SapService; 148 import com.android.bluetooth.sdp.SdpManager; 149 import com.android.bluetooth.tbs.TbsService; 150 import com.android.bluetooth.telephony.BluetoothInCallService; 151 import com.android.bluetooth.vc.VolumeControlService; 152 import com.android.internal.annotations.GuardedBy; 153 import com.android.internal.annotations.VisibleForTesting; 154 import com.android.modules.expresslog.Counter; 155 import com.android.modules.utils.BackgroundThread; 156 import com.android.modules.utils.BytesMatcher; 157 158 import libcore.util.SneakyThrow; 159 160 import com.google.protobuf.InvalidProtocolBufferException; 161 162 import java.io.FileDescriptor; 163 import java.io.FileOutputStream; 164 import java.io.IOException; 165 import java.io.PrintWriter; 166 import java.time.Duration; 167 import java.util.ArrayDeque; 168 import java.util.ArrayList; 169 import java.util.Arrays; 170 import java.util.Collections; 171 import java.util.HashMap; 172 import java.util.HashSet; 173 import java.util.Iterator; 174 import java.util.List; 175 import java.util.Map; 176 import java.util.Set; 177 import java.util.UUID; 178 import java.util.concurrent.ConcurrentHashMap; 179 import java.util.concurrent.ConcurrentLinkedQueue; 180 import java.util.concurrent.Executor; 181 import java.util.function.Function; 182 import java.util.function.Predicate; 183 import java.util.regex.Pattern; 184 import java.util.stream.Collectors; 185 186 public class AdapterService extends Service { 187 private static final String TAG = "BluetoothAdapterService"; 188 189 private static final int MESSAGE_PROFILE_SERVICE_STATE_CHANGED = 1; 190 private static final int MESSAGE_PROFILE_SERVICE_REGISTERED = 2; 191 private static final int MESSAGE_PROFILE_SERVICE_UNREGISTERED = 3; 192 private static final int MESSAGE_PREFERRED_AUDIO_PROFILES_AUDIO_FRAMEWORK_TIMEOUT = 4; 193 194 private static final int CONTROLLER_ENERGY_UPDATE_TIMEOUT_MILLIS = 100; 195 private static final int MIN_ADVT_INSTANCES_FOR_MA = 5; 196 private static final int MIN_OFFLOADED_FILTERS = 10; 197 private static final int MIN_OFFLOADED_SCAN_STORAGE_BYTES = 1024; 198 199 private static final Duration PENDING_SOCKET_HANDOFF_TIMEOUT = Duration.ofMinutes(1); 200 private static final Duration GENERATE_LOCAL_OOB_DATA_TIMEOUT = Duration.ofSeconds(2); 201 private static final Duration PREFERRED_AUDIO_PROFILE_CHANGE_TIMEOUT = Duration.ofSeconds(10); 202 203 static final String PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE = "phonebook_access_permission"; 204 static final String MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE = "message_access_permission"; 205 static final String SIM_ACCESS_PERMISSION_PREFERENCE_FILE = "sim_access_permission"; 206 207 private static BluetoothProperties.snoop_log_mode_values sSnoopLogSettingAtEnable = 208 BluetoothProperties.snoop_log_mode_values.EMPTY; 209 private static String sDefaultSnoopLogSettingAtEnable = "empty"; 210 private static boolean sSnoopLogFilterHeadersSettingAtEnable = false; 211 private static boolean sSnoopLogFilterProfileA2dpSettingAtEnable = false; 212 private static boolean sSnoopLogFilterProfileRfcommSettingAtEnable = false; 213 214 private static BluetoothProperties.snoop_log_filter_profile_pbap_values 215 sSnoopLogFilterProfilePbapModeSettingAtEnable = 216 BluetoothProperties.snoop_log_filter_profile_pbap_values.EMPTY; 217 private static BluetoothProperties.snoop_log_filter_profile_map_values 218 sSnoopLogFilterProfileMapModeSettingAtEnable = 219 BluetoothProperties.snoop_log_filter_profile_map_values.EMPTY; 220 221 private static AdapterService sAdapterService; 222 223 private final Object mEnergyInfoLock = new Object(); 224 private final SparseArray<UidTraffic> mUidTraffic = new SparseArray<>(); 225 226 private final Map<Integer, ProfileService> mStartedProfiles = new HashMap<>(); 227 private final List<ProfileService> mRegisteredProfiles = new ArrayList<>(); 228 private final List<ProfileService> mRunningProfiles = new ArrayList<>(); 229 230 private final List<DiscoveringPackage> mDiscoveringPackages = new ArrayList<>(); 231 232 private final AdapterNativeInterface mNativeInterface = AdapterNativeInterface.getInstance(); 233 234 private final Map<BluetoothDevice, List<IBluetoothMetadataListener>> mMetadataListeners = 235 new HashMap<>(); 236 237 // Map<groupId, PendingAudioProfilePreferenceRequest> 238 @GuardedBy("mCsipGroupsPendingAudioProfileChanges") 239 private final Map<Integer, PendingAudioProfilePreferenceRequest> 240 mCsipGroupsPendingAudioProfileChanges = new HashMap<>(); 241 242 private final Map<BluetoothStateCallback, Executor> mLocalCallbacks = new ConcurrentHashMap<>(); 243 private final Map<UUID, RfcommListenerData> mBluetoothServerSockets = new ConcurrentHashMap<>(); 244 private final ArrayDeque<IBluetoothOobDataCallback> mOobDataCallbackQueue = new ArrayDeque<>(); 245 246 private final RemoteCallbackList<IBluetoothPreferredAudioProfilesCallback> 247 mPreferredAudioProfilesCallbacks = new RemoteCallbackList<>(); 248 private final RemoteCallbackList<IBluetoothQualityReportReadyCallback> 249 mBluetoothQualityReportReadyCallbacks = new RemoteCallbackList<>(); 250 private final RemoteCallbackList<IBluetoothCallback> mRemoteCallbacks = 251 new RemoteCallbackList<>(); 252 253 private final DeviceConfigListener mDeviceConfigListener = new DeviceConfigListener(); 254 255 private final Looper mLooper; 256 private final AdapterServiceHandler mHandler; 257 258 private int mStackReportedState; 259 private long mTxTimeTotalMs; 260 private long mRxTimeTotalMs; 261 private long mIdleTimeTotalMs; 262 private long mEnergyUsedTotalVoltAmpSecMicro; 263 private HashSet<String> mLeAudioAllowDevices = new HashSet<>(); 264 265 private BluetoothAdapter mAdapter; 266 @VisibleForTesting AdapterProperties mAdapterProperties; 267 private AdapterState mAdapterStateMachine; 268 private BondStateMachine mBondStateMachine; 269 private RemoteDevices mRemoteDevices; 270 271 /* TODO: Consider to remove the search API from this class, if changed to use call-back */ 272 private SdpManager mSdpManager = null; 273 274 private boolean mNativeAvailable; 275 private boolean mCleaningUp; 276 private Set<IBluetoothConnectionCallback> mBluetoothConnectionCallbacks = new HashSet<>(); 277 private boolean mQuietmode = false; 278 private Map<String, CallerInfo> mBondAttemptCallerInfo = new HashMap<>(); 279 280 private BatteryStatsManager mBatteryStatsManager; 281 private PowerManager mPowerManager; 282 private PowerManager.WakeLock mWakeLock; 283 private UserManager mUserManager; 284 private CompanionDeviceManager mCompanionDeviceManager; 285 286 // Phone Policy is not used on all devices. Ensure you null check before using it 287 @Nullable private PhonePolicy mPhonePolicy; 288 289 private ActiveDeviceManager mActiveDeviceManager; 290 private final DatabaseManager mDatabaseManager; 291 private final SilenceDeviceManager mSilenceDeviceManager; 292 private CompanionManager mBtCompanionManager; 293 private AppOpsManager mAppOps; 294 295 private BluetoothSocketManagerBinder mBluetoothSocketManagerBinder; 296 297 private BluetoothKeystoreService mBluetoothKeystoreService; 298 private A2dpService mA2dpService; 299 private A2dpSinkService mA2dpSinkService; 300 private HeadsetService mHeadsetService; 301 private HeadsetClientService mHeadsetClientService; 302 private BluetoothMapService mMapService; 303 private MapClientService mMapClientService; 304 private HidDeviceService mHidDeviceService; 305 private HidHostService mHidHostService; 306 private PanService mPanService; 307 private BluetoothPbapService mPbapService; 308 private PbapClientService mPbapClientService; 309 private HearingAidService mHearingAidService; 310 private HapClientService mHapClientService; 311 private SapService mSapService; 312 private VolumeControlService mVolumeControlService; 313 private CsipSetCoordinatorService mCsipSetCoordinatorService; 314 private LeAudioService mLeAudioService; 315 private BassClientService mBassClientService; 316 private BatteryService mBatteryService; 317 private BluetoothQualityReportNativeInterface mBluetoothQualityReportNativeInterface; 318 private GattService mGattService; 319 private ScanController mScanController; 320 321 private volatile boolean mTestModeEnabled = false; 322 323 private MetricsLogger mMetricsLogger; 324 325 /** Handlers for incoming service calls */ 326 private AdapterServiceBinder mBinder; 327 328 // Report ID definition 329 public enum BqrQualityReportId { 330 QUALITY_REPORT_ID_MONITOR_MODE(0x01), 331 QUALITY_REPORT_ID_APPROACH_LSTO(0x02), 332 QUALITY_REPORT_ID_A2DP_AUDIO_CHOPPY(0x03), 333 QUALITY_REPORT_ID_SCO_VOICE_CHOPPY(0x04), 334 QUALITY_REPORT_ID_ROOT_INFLAMMATION(0x05), 335 QUALITY_REPORT_ID_CONNECT_FAIL(0x08), 336 QUALITY_REPORT_ID_LMP_LL_MESSAGE_TRACE(0x11), 337 QUALITY_REPORT_ID_BT_SCHEDULING_TRACE(0x12), 338 QUALITY_REPORT_ID_CONTROLLER_DBG_INFO(0x13); 339 340 private final int mValue; 341 BqrQualityReportId(int value)342 BqrQualityReportId(int value) { 343 mValue = value; 344 } 345 getValue()346 public int getValue() { 347 return mValue; 348 } 349 }; 350 351 static { 352 if (!Flags.avoidStaticLoadingOfNative()) { Log.d(TAG, "Loading JNI Library")353 Log.d(TAG, "Loading JNI Library"); 354 if (Utils.isInstrumentationTestMode()) { Log.w(TAG, "App is instrumented. Skip loading the native")355 Log.w(TAG, "App is instrumented. Skip loading the native"); 356 } else { 357 System.loadLibrary("bluetooth_jni"); 358 } 359 } 360 } 361 362 // Keep a constructor for ActivityThread.handleCreateService AdapterService()363 AdapterService() { 364 this(Looper.getMainLooper()); 365 } 366 367 @VisibleForTesting AdapterService(Looper looper)368 AdapterService(Looper looper) { 369 mLooper = requireNonNull(looper); 370 mHandler = new AdapterServiceHandler(mLooper); 371 mSilenceDeviceManager = new SilenceDeviceManager(this, new ServiceFactory(), mLooper); 372 mDatabaseManager = new DatabaseManager(this); 373 } 374 375 @VisibleForTesting AdapterService(Context ctx)376 public AdapterService(Context ctx) { 377 this(Looper.getMainLooper()); 378 attachBaseContext(ctx); 379 } 380 getAdapterService()381 public static synchronized AdapterService getAdapterService() { 382 return sAdapterService; 383 } 384 getNative()385 AdapterNativeInterface getNative() { 386 return mNativeInterface; 387 } 388 389 /** Allow test to set an AdapterService to be return by AdapterService.getAdapterService() */ 390 @VisibleForTesting setAdapterService(AdapterService instance)391 public static synchronized void setAdapterService(AdapterService instance) { 392 if (instance == null) { 393 Log.e(TAG, "setAdapterService() - instance is null"); 394 return; 395 } 396 Log.d(TAG, "setAdapterService() - set service to " + instance); 397 sAdapterService = instance; 398 } 399 400 /** Clear test Adapter service. See {@code setAdapterService} */ 401 @VisibleForTesting clearAdapterService(AdapterService instance)402 public static synchronized void clearAdapterService(AdapterService instance) { 403 if (sAdapterService == instance) { 404 Log.d(TAG, "clearAdapterService() - This adapter was cleared " + instance); 405 sAdapterService = null; 406 } else { 407 Log.d( 408 TAG, 409 "clearAdapterService() - incorrect cleared adapter." 410 + (" Instance=" + instance) 411 + (" vs sAdapterService=" + sAdapterService)); 412 } 413 } 414 415 /** 416 * Register a {@link ProfileService} with AdapterService. 417 * 418 * @param profile the service being added. 419 */ addProfile(ProfileService profile)420 public void addProfile(ProfileService profile) { 421 mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_REGISTERED, profile).sendToTarget(); 422 } 423 424 /** 425 * Unregister a ProfileService with AdapterService. 426 * 427 * @param profile the service being removed. 428 */ removeProfile(ProfileService profile)429 public void removeProfile(ProfileService profile) { 430 mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_UNREGISTERED, profile).sendToTarget(); 431 } 432 433 /** 434 * Notify AdapterService that a ProfileService has started or stopped. 435 * 436 * @param profile the service being removed. 437 * @param state {@link BluetoothAdapter#STATE_ON} or {@link BluetoothAdapter#STATE_OFF} 438 */ onProfileServiceStateChanged(ProfileService profile, int state)439 public void onProfileServiceStateChanged(ProfileService profile, int state) { 440 if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) { 441 throw new IllegalArgumentException(BluetoothAdapter.nameForState(state)); 442 } 443 Message m = mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_STATE_CHANGED); 444 m.obj = profile; 445 m.arg1 = state; 446 mHandler.sendMessage(m); 447 } 448 449 class AdapterServiceHandler extends Handler { AdapterServiceHandler(Looper looper)450 AdapterServiceHandler(Looper looper) { 451 super(looper); 452 } 453 454 @Override handleMessage(Message msg)455 public void handleMessage(Message msg) { 456 Log.v(TAG, "handleMessage() - Message: " + msg.what); 457 458 switch (msg.what) { 459 case MESSAGE_PROFILE_SERVICE_STATE_CHANGED: 460 Log.v(TAG, "handleMessage() - MESSAGE_PROFILE_SERVICE_STATE_CHANGED"); 461 processProfileServiceStateChanged((ProfileService) msg.obj, msg.arg1); 462 break; 463 case MESSAGE_PROFILE_SERVICE_REGISTERED: 464 Log.v(TAG, "handleMessage() - MESSAGE_PROFILE_SERVICE_REGISTERED"); 465 registerProfileService((ProfileService) msg.obj); 466 break; 467 case MESSAGE_PROFILE_SERVICE_UNREGISTERED: 468 Log.v(TAG, "handleMessage() - MESSAGE_PROFILE_SERVICE_UNREGISTERED"); 469 unregisterProfileService((ProfileService) msg.obj); 470 break; 471 case MESSAGE_PREFERRED_AUDIO_PROFILES_AUDIO_FRAMEWORK_TIMEOUT: 472 Log.e( 473 TAG, 474 "handleMessage() - " 475 + "MESSAGE_PREFERRED_PROFILE_CHANGE_AUDIO_FRAMEWORK_TIMEOUT"); 476 int groupId = (int) msg.obj; 477 478 synchronized (mCsipGroupsPendingAudioProfileChanges) { 479 removeFromPendingAudioProfileChanges(groupId); 480 PendingAudioProfilePreferenceRequest request = 481 mCsipGroupsPendingAudioProfileChanges.remove(groupId); 482 Log.e( 483 TAG, 484 "Preferred audio profiles change audio framework timeout for " 485 + ("device " + request.mDeviceRequested)); 486 sendPreferredAudioProfilesCallbackToApps( 487 request.mDeviceRequested, 488 request.mRequestedPreferences, 489 BluetoothStatusCodes.ERROR_TIMEOUT); 490 } 491 break; 492 } 493 } 494 registerProfileService(ProfileService profile)495 private void registerProfileService(ProfileService profile) { 496 if (mRegisteredProfiles.contains(profile)) { 497 Log.e(TAG, profile.getName() + " already registered."); 498 return; 499 } 500 mRegisteredProfiles.add(profile); 501 } 502 unregisterProfileService(ProfileService profile)503 private void unregisterProfileService(ProfileService profile) { 504 if (!mRegisteredProfiles.contains(profile)) { 505 Log.e(TAG, profile.getName() + " not registered (UNREGISTER)."); 506 return; 507 } 508 mRegisteredProfiles.remove(profile); 509 } 510 processProfileServiceStateChanged(ProfileService profile, int state)511 private void processProfileServiceStateChanged(ProfileService profile, int state) { 512 switch (state) { 513 case BluetoothAdapter.STATE_ON: 514 if (!mRegisteredProfiles.contains(profile)) { 515 Log.e(TAG, profile.getName() + " not registered (STATE_ON)."); 516 return; 517 } 518 if (mRunningProfiles.contains(profile)) { 519 Log.e(TAG, profile.getName() + " already running."); 520 return; 521 } 522 mRunningProfiles.add(profile); 523 // TODO(b/228875190): GATT is assumed supported. GATT starting triggers hardware 524 // initialization. Configuring a device without GATT causes start up failures. 525 if (GattService.class.getSimpleName().equals(profile.getName()) 526 && !Flags.scanManagerRefactor()) { 527 mNativeInterface.enable(); 528 } else if (mRegisteredProfiles.size() == Config.getSupportedProfiles().length 529 && mRegisteredProfiles.size() == mRunningProfiles.size()) { 530 mAdapterProperties.onBluetoothReady(); 531 updateUuids(); 532 initProfileServices(); 533 mNativeInterface.getAdapterProperty( 534 AbstractionLayer.BT_PROPERTY_DYNAMIC_AUDIO_BUFFER); 535 mAdapterStateMachine.sendMessage(AdapterState.BREDR_STARTED); 536 mBtCompanionManager.loadCompanionInfo(); 537 } 538 break; 539 case BluetoothAdapter.STATE_OFF: 540 if (!mRegisteredProfiles.contains(profile)) { 541 Log.e(TAG, profile.getName() + " not registered (STATE_OFF)."); 542 return; 543 } 544 if (!mRunningProfiles.contains(profile)) { 545 Log.e(TAG, profile.getName() + " not running."); 546 return; 547 } 548 mRunningProfiles.remove(profile); 549 550 if (Flags.scanManagerRefactor()) { 551 if (mRunningProfiles.size() == 0) { 552 mAdapterStateMachine.sendMessage(AdapterState.BREDR_STOPPED); 553 } 554 } else { 555 // TODO(b/228875190): GATT is assumed supported. GATT is expected to be the 556 // only profile available in the "BLE ON" state. If only GATT is left, send 557 // BREDR_STOPPED. If GATT is stopped, deinitialize the hardware. 558 if ((mRunningProfiles.size() == 1 559 && (GattService.class 560 .getSimpleName() 561 .equals(mRunningProfiles.get(0).getName())))) { 562 mAdapterStateMachine.sendMessage(AdapterState.BREDR_STOPPED); 563 } else if (mRunningProfiles.size() == 0) { 564 mNativeInterface.disable(); 565 } 566 } 567 break; 568 default: 569 Log.e(TAG, "Unhandled profile state: " + state); 570 } 571 } 572 } 573 574 /** 575 * Stores information about requests made to the audio framework arising from calls to {@link 576 * BluetoothAdapter#setPreferredAudioProfiles(BluetoothDevice, Bundle)}. 577 */ 578 private static class PendingAudioProfilePreferenceRequest { 579 // The newly requested preferences 580 final Bundle mRequestedPreferences; 581 // Reference counter for how many calls are pending completion in the audio framework 582 int mRemainingRequestsToAudioFramework; 583 // The device with which the request was made. Used for sending the callback. 584 final BluetoothDevice mDeviceRequested; 585 586 /** 587 * Constructs an entity to store information about pending preferred audio profile changes. 588 * 589 * @param preferences newly requested preferences 590 * @param numRequestsToAudioFramework how many active device changed requests are sent to 591 * the audio framework 592 * @param device the device with which the request was made 593 */ PendingAudioProfilePreferenceRequest( Bundle preferences, int numRequestsToAudioFramework, BluetoothDevice device)594 PendingAudioProfilePreferenceRequest( 595 Bundle preferences, int numRequestsToAudioFramework, BluetoothDevice device) { 596 mRequestedPreferences = preferences; 597 mRemainingRequestsToAudioFramework = numRequestsToAudioFramework; 598 mDeviceRequested = device; 599 } 600 } 601 getNonNullSystemService(@onNull Class<T> clazz)602 final @NonNull <T> T getNonNullSystemService(@NonNull Class<T> clazz) { 603 return requireNonNull(getSystemService(clazz), clazz.getSimpleName() + " cannot be null"); 604 } 605 606 @Override 607 @RequiresPermission( 608 allOf = { 609 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, 610 android.Manifest.permission.READ_DEVICE_CONFIG, 611 }, 612 anyOf = { 613 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, 614 android.Manifest.permission.INTERACT_ACROSS_USERS, 615 android.Manifest.permission.CREATE_USERS, 616 android.Manifest.permission.MANAGE_USERS, 617 }) onCreate()618 public void onCreate() { 619 super.onCreate(); 620 Log.d(TAG, "onCreate()"); 621 if (!Flags.fastBindToApp()) { 622 init(); 623 return; 624 } 625 // OnCreate must perform the minimum of infaillible and mandatory initialization 626 mRemoteDevices = new RemoteDevices(this, mLooper); 627 mAdapterProperties = new AdapterProperties(this); 628 mAdapterStateMachine = new AdapterState(this, mLooper); 629 mBinder = new AdapterServiceBinder(this); 630 mUserManager = getNonNullSystemService(UserManager.class); 631 mAppOps = getNonNullSystemService(AppOpsManager.class); 632 mPowerManager = getNonNullSystemService(PowerManager.class); 633 mBatteryStatsManager = getNonNullSystemService(BatteryStatsManager.class); 634 mCompanionDeviceManager = getNonNullSystemService(CompanionDeviceManager.class); 635 setAdapterService(this); 636 } 637 init()638 private void init() { 639 Log.d(TAG, "init()"); 640 Config.init(this); 641 initMetricsLogger(); 642 mDeviceConfigListener.start(); 643 644 if (!Flags.fastBindToApp()) { 645 // Moved to OnCreate 646 mUserManager = getNonNullSystemService(UserManager.class); 647 mAppOps = getNonNullSystemService(AppOpsManager.class); 648 mPowerManager = getNonNullSystemService(PowerManager.class); 649 mBatteryStatsManager = getNonNullSystemService(BatteryStatsManager.class); 650 mCompanionDeviceManager = getNonNullSystemService(CompanionDeviceManager.class); 651 mRemoteDevices = new RemoteDevices(this, mLooper); 652 } 653 654 clearDiscoveringPackages(); 655 if (!Flags.fastBindToApp()) { 656 mBinder = new AdapterServiceBinder(this); 657 } 658 mAdapter = BluetoothAdapter.getDefaultAdapter(); 659 if (!Flags.fastBindToApp()) { 660 // Moved to OnCreate 661 mAdapterProperties = new AdapterProperties(this); 662 mAdapterStateMachine = new AdapterState(this, mLooper); 663 } 664 boolean isCommonCriteriaMode = 665 getNonNullSystemService(DevicePolicyManager.class) 666 .isCommonCriteriaModeEnabled(null); 667 mBluetoothKeystoreService = 668 new BluetoothKeystoreService( 669 BluetoothKeystoreNativeInterface.getInstance(), isCommonCriteriaMode); 670 mBluetoothKeystoreService.start(); 671 int configCompareResult = mBluetoothKeystoreService.getCompareResult(); 672 673 // Start tracking Binder latency for the bluetooth process. 674 BluetoothFrameworkInitializer.initializeBinderCallsStats(getApplicationContext()); 675 676 // Android TV doesn't show consent dialogs for just works and encryption only le pairing 677 boolean isAtvDevice = 678 getApplicationContext() 679 .getPackageManager() 680 .hasSystemFeature(PackageManager.FEATURE_LEANBACK_ONLY); 681 if (Flags.avoidStaticLoadingOfNative()) { 682 if (Utils.isInstrumentationTestMode()) { 683 Log.w(TAG, "This Bluetooth App is instrumented. ** Skip loading the native **"); 684 } else { 685 Log.d(TAG, "Loading JNI Library"); 686 System.loadLibrary("bluetooth_jni"); 687 } 688 } 689 mNativeInterface.init( 690 this, 691 mAdapterProperties, 692 mUserManager.isGuestUser(), 693 isCommonCriteriaMode, 694 configCompareResult, 695 getInitFlags(), 696 isAtvDevice, 697 getApplicationInfo().dataDir); 698 mNativeAvailable = true; 699 // Load the name and address 700 mNativeInterface.getAdapterProperty(AbstractionLayer.BT_PROPERTY_BDADDR); 701 mNativeInterface.getAdapterProperty(AbstractionLayer.BT_PROPERTY_BDNAME); 702 mNativeInterface.getAdapterProperty(AbstractionLayer.BT_PROPERTY_CLASS_OF_DEVICE); 703 704 mBluetoothKeystoreService.initJni(); 705 706 mBluetoothQualityReportNativeInterface = 707 requireNonNull( 708 BluetoothQualityReportNativeInterface.getInstance(), 709 "BluetoothQualityReportNativeInterface cannot be null when BQR starts"); 710 mBluetoothQualityReportNativeInterface.init(); 711 712 if (Flags.fastBindToApp()) { 713 mSdpManager = new SdpManager(this, mLooper); 714 } else { 715 mSdpManager = new SdpManager(this); 716 } 717 718 mDatabaseManager.start(MetadataDatabase.createDatabase(this)); 719 720 boolean isAutomotiveDevice = 721 getApplicationContext() 722 .getPackageManager() 723 .hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE); 724 725 /* 726 * Phone policy is specific to phone implementations and hence if a device wants to exclude 727 * it out then it can be disabled by using the flag below. Phone policy is never used on 728 * Android Automotive OS builds, in favor of a policy currently located in 729 * CarBluetoothService. 730 */ 731 if (!isAutomotiveDevice && getResources().getBoolean(R.bool.enable_phone_policy)) { 732 Log.i(TAG, "Phone policy enabled"); 733 mPhonePolicy = new PhonePolicy(this, new ServiceFactory()); 734 mPhonePolicy.start(); 735 } else { 736 Log.i(TAG, "Phone policy disabled"); 737 } 738 739 if (Flags.audioRoutingCentralization()) { 740 mActiveDeviceManager = new AudioRoutingManager(this, new ServiceFactory()); 741 } else { 742 mActiveDeviceManager = new ActiveDeviceManager(this, new ServiceFactory()); 743 } 744 mActiveDeviceManager.start(); 745 746 mSilenceDeviceManager.start(); 747 748 mBtCompanionManager = new CompanionManager(this, new ServiceFactory()); 749 750 mBluetoothSocketManagerBinder = new BluetoothSocketManagerBinder(this); 751 752 if (!Flags.fastBindToApp()) { 753 setAdapterService(this); 754 } 755 756 invalidateBluetoothCaches(); 757 758 // First call to getSharedPreferences will result in a file read into 759 // memory cache. Call it here asynchronously to avoid potential ANR 760 // in the future 761 new AsyncTask<Void, Void, Void>() { 762 @Override 763 protected Void doInBackground(Void... params) { 764 getSharedPreferences( 765 PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE, Context.MODE_PRIVATE); 766 getSharedPreferences( 767 MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE, Context.MODE_PRIVATE); 768 getSharedPreferences(SIM_ACCESS_PERMISSION_PREFERENCE_FILE, Context.MODE_PRIVATE); 769 return null; 770 } 771 }.execute(); 772 773 try { 774 int systemUiUid = 775 getApplicationContext() 776 .createContextAsUser(UserHandle.SYSTEM, /* flags= */ 0) 777 .getPackageManager() 778 .getPackageUid( 779 "com.android.systemui", PackageManager.MATCH_SYSTEM_ONLY); 780 781 Utils.setSystemUiUid(systemUiUid); 782 } catch (PackageManager.NameNotFoundException e) { 783 // Some platforms, such as wearables do not have a system ui. 784 Log.w(TAG, "Unable to resolve SystemUI's UID.", e); 785 } 786 } 787 788 @Override onBind(Intent intent)789 public IBinder onBind(Intent intent) { 790 Log.d(TAG, "onBind()"); 791 return mBinder; 792 } 793 794 @Override 795 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) onUnbind(Intent intent)796 public boolean onUnbind(Intent intent) { 797 if (Flags.explicitKillFromSystemServer()) { 798 Log.d(TAG, "onUnbind()"); 799 return super.onUnbind(intent); 800 } 801 Log.d(TAG, "onUnbind() - calling cleanup"); 802 cleanup(); 803 return super.onUnbind(intent); 804 } 805 806 @Override onDestroy()807 public void onDestroy() { 808 Log.d(TAG, "onDestroy()"); 809 if (Flags.explicitKillFromSystemServer()) { 810 return; 811 } 812 if (!isMock()) { 813 // TODO(b/27859763) 814 Log.i(TAG, "Force exit to cleanup internal state in Bluetooth stack"); 815 System.exit(0); 816 } 817 } 818 getActiveDeviceManager()819 public ActiveDeviceManager getActiveDeviceManager() { 820 return mActiveDeviceManager; 821 } 822 getSilenceDeviceManager()823 public SilenceDeviceManager getSilenceDeviceManager() { 824 return mSilenceDeviceManager; 825 } 826 initMetricsLogger()827 private boolean initMetricsLogger() { 828 if (mMetricsLogger != null) { 829 return false; 830 } 831 mMetricsLogger = MetricsLogger.getInstance(); 832 return mMetricsLogger.init(this); 833 } 834 closeMetricsLogger()835 private boolean closeMetricsLogger() { 836 if (mMetricsLogger == null) { 837 return false; 838 } 839 boolean result = mMetricsLogger.close(); 840 mMetricsLogger = null; 841 return result; 842 } 843 844 /** 845 * Log L2CAP CoC Server Connection Metrics 846 * 847 * @param port port of socket 848 * @param isSecured if secured API is called 849 * @param result transaction result of the connection 850 * @param socketCreationLatencyMillis latency of the connection 851 * @param timeoutMillis timeout set by the app 852 */ logL2capcocServerConnection( BluetoothDevice device, int port, boolean isSecured, int result, long socketCreationTimeMillis, long socketCreationLatencyMillis, long socketConnectionTimeMillis, long timeoutMillis, int appUid)853 public void logL2capcocServerConnection( 854 BluetoothDevice device, 855 int port, 856 boolean isSecured, 857 int result, 858 long socketCreationTimeMillis, 859 long socketCreationLatencyMillis, 860 long socketConnectionTimeMillis, 861 long timeoutMillis, 862 int appUid) { 863 864 int metricId = 0; 865 if (device != null) { 866 metricId = getMetricId(device); 867 } 868 long currentTime = System.currentTimeMillis(); 869 long endToEndLatencyMillis = currentTime - socketCreationTimeMillis; 870 long socketAcceptanceLatencyMillis = currentTime - socketConnectionTimeMillis; 871 Log.i( 872 TAG, 873 "Statslog L2capcoc server connection." 874 + (" metricId " + metricId) 875 + (" port " + port) 876 + (" isSecured " + isSecured) 877 + (" result " + result) 878 + (" endToEndLatencyMillis " + endToEndLatencyMillis) 879 + (" socketCreationLatencyMillis " + socketCreationLatencyMillis) 880 + (" socketAcceptanceLatencyMillis " + socketAcceptanceLatencyMillis) 881 + (" timeout set by app " + timeoutMillis) 882 + (" appUid " + appUid)); 883 BluetoothStatsLog.write( 884 BluetoothStatsLog.BLUETOOTH_L2CAP_COC_SERVER_CONNECTION, 885 metricId, 886 port, 887 isSecured, 888 result, 889 endToEndLatencyMillis, 890 timeoutMillis, 891 appUid, 892 socketCreationLatencyMillis, 893 socketAcceptanceLatencyMillis); 894 } 895 setMetricsLogger(MetricsLogger metricsLogger)896 public void setMetricsLogger(MetricsLogger metricsLogger) { 897 mMetricsLogger = metricsLogger; 898 } 899 900 /** 901 * Log L2CAP CoC Client Connection Metrics 902 * 903 * @param device Bluetooth device 904 * @param port port of socket 905 * @param isSecured if secured API is called 906 * @param result transaction result of the connection 907 * @param socketCreationLatencyNanos latency of the connection 908 */ logL2capcocClientConnection( BluetoothDevice device, int port, boolean isSecured, int result, long socketCreationTimeNanos, long socketCreationLatencyNanos, long socketConnectionTimeNanos, int appUid)909 public void logL2capcocClientConnection( 910 BluetoothDevice device, 911 int port, 912 boolean isSecured, 913 int result, 914 long socketCreationTimeNanos, 915 long socketCreationLatencyNanos, 916 long socketConnectionTimeNanos, 917 int appUid) { 918 919 int metricId = getMetricId(device); 920 long currentTime = System.nanoTime(); 921 long endToEndLatencyMillis = (currentTime - socketCreationTimeNanos) / 1000000; 922 long socketCreationLatencyMillis = socketCreationLatencyNanos / 1000000; 923 long socketConnectionLatencyMillis = (currentTime - socketConnectionTimeNanos) / 1000000; 924 Log.i( 925 TAG, 926 "Statslog L2capcoc client connection." 927 + (" metricId " + metricId) 928 + (" port " + port) 929 + (" isSecured " + isSecured) 930 + (" result " + result) 931 + (" endToEndLatencyMillis " + endToEndLatencyMillis) 932 + (" socketCreationLatencyMillis " + socketCreationLatencyMillis) 933 + (" socketConnectionLatencyMillis " + socketConnectionLatencyMillis) 934 + (" appUid " + appUid)); 935 BluetoothStatsLog.write( 936 BluetoothStatsLog.BLUETOOTH_L2CAP_COC_CLIENT_CONNECTION, 937 metricId, 938 port, 939 isSecured, 940 result, 941 endToEndLatencyMillis, 942 appUid, 943 socketCreationLatencyMillis, 944 socketConnectionLatencyMillis); 945 } 946 947 /** 948 * Log RFCOMM Connection Metrics 949 * 950 * @param device Bluetooth device 951 * @param isSecured if secured API is called 952 * @param resultCode transaction result of the connection 953 * @param isSerialPort true if service class UUID is 0x1101 954 */ logRfcommConnectionAttempt( BluetoothDevice device, boolean isSecured, int resultCode, long socketCreationTimeNanos, boolean isSerialPort, int appUid)955 public void logRfcommConnectionAttempt( 956 BluetoothDevice device, 957 boolean isSecured, 958 int resultCode, 959 long socketCreationTimeNanos, 960 boolean isSerialPort, 961 int appUid) { 962 int metricId = getMetricId(device); 963 long currentTime = System.nanoTime(); 964 long endToEndLatencyNanos = currentTime - socketCreationTimeNanos; 965 byte[] remoteDeviceInfoBytes = MetricsLogger.getInstance().getRemoteDeviceInfoProto(device); 966 BluetoothStatsLog.write( 967 BluetoothStatsLog.BLUETOOTH_RFCOMM_CONNECTION_ATTEMPTED, 968 metricId, 969 endToEndLatencyNanos, 970 isSecured 971 ? BluetoothRfcommProtoEnums.SOCKET_SECURITY_SECURE 972 : BluetoothRfcommProtoEnums.SOCKET_SECURITY_INSECURE, 973 resultCode, 974 isSerialPort, 975 appUid, 976 remoteDeviceInfoBytes); 977 } 978 979 @RequiresPermission( 980 allOf = { 981 android.Manifest.permission.BLUETOOTH_CONNECT, 982 android.Manifest.permission.UPDATE_DEVICE_STATS, 983 }) bringUpBle()984 void bringUpBle() { 985 Log.d(TAG, "bleOnProcessStart()"); 986 987 if (getResources() 988 .getBoolean(R.bool.config_bluetooth_reload_supported_profiles_when_enabled)) { 989 Config.init(getApplicationContext()); 990 } 991 992 // Reset |mRemoteDevices| whenever BLE is turned off then on 993 // This is to replace the fact that |mRemoteDevices| was 994 // reinitialized in previous code. 995 // 996 // TODO(apanicke): The reason is unclear but 997 // I believe it is to clear the variable every time BLE was 998 // turned off then on. The same effect can be achieved by 999 // calling cleanup but this may not be necessary at all 1000 // We should figure out why this is needed later 1001 mRemoteDevices.reset(); 1002 mAdapterProperties.init(mRemoteDevices); 1003 1004 Log.d(TAG, "bleOnProcessStart() - Make Bond State Machine"); 1005 mBondStateMachine = BondStateMachine.make(this, mAdapterProperties, mRemoteDevices); 1006 1007 mNativeInterface.getCallbacks().init(mBondStateMachine, mRemoteDevices); 1008 1009 mBatteryStatsManager.reportBleScanReset(); 1010 BluetoothStatsLog.write_non_chained( 1011 BluetoothStatsLog.BLE_SCAN_STATE_CHANGED, 1012 -1, 1013 null, 1014 BluetoothStatsLog.BLE_SCAN_STATE_CHANGED__STATE__RESET, 1015 false, 1016 false, 1017 false); 1018 1019 // TODO(b/228875190): GATT is assumed supported. As a result, we don't respect the 1020 // configuration sysprop. Configuring a device without GATT, although rare, will cause stack 1021 // start up errors yielding init loops. 1022 if (!GattService.isEnabled()) { 1023 Log.w( 1024 TAG, 1025 "GATT is configured off but the stack assumes it to be enabled. Start anyway."); 1026 } 1027 if (Flags.scanManagerRefactor()) { 1028 startScanController(); 1029 } else { 1030 startGattProfileService(); 1031 } 1032 } 1033 bringDownBle()1034 void bringDownBle() { 1035 if (Flags.scanManagerRefactor()) { 1036 stopScanController(); 1037 } else { 1038 stopGattProfileService(); 1039 } 1040 } 1041 stateChangeCallback(int status)1042 void stateChangeCallback(int status) { 1043 if (status == AbstractionLayer.BT_STATE_OFF) { 1044 Log.d(TAG, "stateChangeCallback: disableNative() completed"); 1045 mAdapterStateMachine.sendMessage(AdapterState.BLE_STOPPED); 1046 } else if (status == AbstractionLayer.BT_STATE_ON) { 1047 mAdapterStateMachine.sendMessage(AdapterState.BLE_STARTED); 1048 } else { 1049 Log.e(TAG, "Incorrect status " + status + " in stateChangeCallback"); 1050 } 1051 } 1052 startProfileServices()1053 void startProfileServices() { 1054 Log.d(TAG, "startCoreServices()"); 1055 int[] supportedProfileServices = Config.getSupportedProfiles(); 1056 if (Flags.scanManagerRefactor()) { 1057 // Scanning is always supported, started separately, and is not a profile service. 1058 // This will check other profile services. 1059 if (supportedProfileServices.length == 0) { 1060 mAdapterProperties.onBluetoothReady(); 1061 updateUuids(); 1062 mAdapterStateMachine.sendMessage(AdapterState.BREDR_STARTED); 1063 } else { 1064 setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_ON); 1065 } 1066 } else { 1067 // TODO(b/228875190): GATT is assumed supported. If we support no other profiles then 1068 // just move on to BREDR_STARTED. Note that configuring GATT to NOT supported will cause 1069 // adapter initialization failures 1070 if (supportedProfileServices.length == 1 1071 && supportedProfileServices[0] == BluetoothProfile.GATT) { 1072 mAdapterProperties.onBluetoothReady(); 1073 updateUuids(); 1074 mAdapterStateMachine.sendMessage(AdapterState.BREDR_STARTED); 1075 } else { 1076 setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_ON); 1077 } 1078 } 1079 } 1080 stopProfileServices()1081 void stopProfileServices() { 1082 // Make sure to stop classic background tasks now 1083 mNativeInterface.cancelDiscovery(); 1084 mAdapterProperties.setScanMode(BluetoothAdapter.SCAN_MODE_NONE); 1085 1086 int[] supportedProfileServices = Config.getSupportedProfiles(); 1087 if (Flags.scanManagerRefactor()) { 1088 // Scanning is always supported, started separately, and is not a profile service. 1089 // This will check other profile services. 1090 if (supportedProfileServices.length == 0) { 1091 mAdapterStateMachine.sendMessage(AdapterState.BREDR_STOPPED); 1092 } else { 1093 setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_OFF); 1094 } 1095 } else { 1096 // TODO(b/228875190): GATT is assumed supported. If we support no profiles then just 1097 // move on to BREDR_STOPPED 1098 if (supportedProfileServices.length == 1 1099 && (mRunningProfiles.size() == 1 1100 && GattService.class 1101 .getSimpleName() 1102 .equals(mRunningProfiles.get(0).getName()))) { 1103 Log.d( 1104 TAG, 1105 "stopProfileServices() - No profiles services to stop or already stopped."); 1106 mAdapterStateMachine.sendMessage(AdapterState.BREDR_STOPPED); 1107 } else { 1108 setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_OFF); 1109 } 1110 } 1111 } 1112 startGattProfileService()1113 private void startGattProfileService() { 1114 mGattService = new GattService(this); 1115 1116 mStartedProfiles.put(BluetoothProfile.GATT, mGattService); 1117 addProfile(mGattService); 1118 mGattService.start(); 1119 mGattService.setAvailable(true); 1120 onProfileServiceStateChanged(mGattService, BluetoothAdapter.STATE_ON); 1121 } 1122 startScanController()1123 private void startScanController() { 1124 mScanController = new ScanController(this); 1125 mNativeInterface.enable(); 1126 } 1127 stopGattProfileService()1128 private void stopGattProfileService() { 1129 mAdapterProperties.onBleDisable(); 1130 if (mRunningProfiles.size() == 0) { 1131 Log.d(TAG, "stopGattProfileService() - No profiles services to stop."); 1132 mAdapterStateMachine.sendMessage(AdapterState.BLE_STOPPED); 1133 } 1134 1135 mStartedProfiles.remove(BluetoothProfile.GATT); 1136 if (mGattService != null) { 1137 mGattService.setAvailable(false); 1138 onProfileServiceStateChanged(mGattService, BluetoothAdapter.STATE_OFF); 1139 mGattService.stop(); 1140 removeProfile(mGattService); 1141 mGattService.cleanup(); 1142 mGattService.getBinder().cleanup(); 1143 mGattService = null; 1144 } 1145 } 1146 stopScanController()1147 private void stopScanController() { 1148 mAdapterProperties.onBleDisable(); 1149 1150 if (mScanController == null) { 1151 mAdapterStateMachine.sendMessage(AdapterState.BLE_STOPPED); 1152 } else { 1153 mScanController.stop(); 1154 mScanController = null; 1155 mNativeInterface.disable(); 1156 } 1157 } 1158 invalidateBluetoothGetStateCache()1159 private void invalidateBluetoothGetStateCache() { 1160 BluetoothAdapter.invalidateBluetoothGetStateCache(); 1161 } 1162 updateLeAudioProfileServiceState()1163 void updateLeAudioProfileServiceState() { 1164 Set<Integer> nonSupportedProfiles = new HashSet<>(); 1165 1166 if (!isLeConnectedIsochronousStreamCentralSupported()) { 1167 for (int profileId : Config.getLeAudioUnicastProfiles()) { 1168 nonSupportedProfiles.add(profileId); 1169 } 1170 } 1171 1172 if (!isLeAudioBroadcastAssistantSupported()) { 1173 nonSupportedProfiles.add(BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT); 1174 } 1175 1176 if (!isLeAudioBroadcastSourceSupported()) { 1177 Config.setProfileEnabled(BluetoothProfile.LE_AUDIO_BROADCAST, false); 1178 } 1179 1180 // Disable the non-supported profiles service 1181 for (int profileId : nonSupportedProfiles) { 1182 Config.setProfileEnabled(profileId, false); 1183 if (mStartedProfiles.containsKey(profileId)) { 1184 setProfileServiceState(profileId, BluetoothAdapter.STATE_OFF); 1185 } 1186 } 1187 } 1188 updateAdapterState(int prevState, int newState)1189 void updateAdapterState(int prevState, int newState) { 1190 mAdapterProperties.setState(newState); 1191 invalidateBluetoothGetStateCache(); 1192 1193 // Only BluetoothManagerService should be registered 1194 int n = mRemoteCallbacks.beginBroadcast(); 1195 Log.d( 1196 TAG, 1197 "updateAdapterState() - Broadcasting state " 1198 + BluetoothAdapter.nameForState(newState) 1199 + " to " 1200 + n 1201 + " receivers."); 1202 for (int i = 0; i < n; i++) { 1203 try { 1204 mRemoteCallbacks.getBroadcastItem(i).onBluetoothStateChange(prevState, newState); 1205 } catch (RemoteException e) { 1206 Log.d(TAG, "updateAdapterState() - Callback #" + i + " failed (" + e + ")"); 1207 } 1208 } 1209 mRemoteCallbacks.finishBroadcast(); 1210 1211 for (Map.Entry<BluetoothStateCallback, Executor> e : mLocalCallbacks.entrySet()) { 1212 e.getValue().execute(() -> e.getKey().onBluetoothStateChange(prevState, newState)); 1213 } 1214 1215 // Turn the Adapter all the way off if we are disabling and the snoop log setting changed. 1216 if (newState == BluetoothAdapter.STATE_BLE_TURNING_ON) { 1217 sSnoopLogSettingAtEnable = 1218 BluetoothProperties.snoop_log_mode() 1219 .orElse(BluetoothProperties.snoop_log_mode_values.EMPTY); 1220 sDefaultSnoopLogSettingAtEnable = 1221 Settings.Global.getString( 1222 getContentResolver(), Settings.Global.BLUETOOTH_BTSNOOP_DEFAULT_MODE); 1223 1224 sSnoopLogFilterHeadersSettingAtEnable = 1225 BluetoothProperties.snoop_log_filter_snoop_headers_enabled().orElse(false); 1226 sSnoopLogFilterProfileA2dpSettingAtEnable = 1227 BluetoothProperties.snoop_log_filter_profile_a2dp_enabled().orElse(false); 1228 sSnoopLogFilterProfileRfcommSettingAtEnable = 1229 BluetoothProperties.snoop_log_filter_profile_rfcomm_enabled().orElse(false); 1230 sSnoopLogFilterProfilePbapModeSettingAtEnable = 1231 BluetoothProperties.snoop_log_filter_profile_pbap() 1232 .orElse(BluetoothProperties.snoop_log_filter_profile_pbap_values.EMPTY); 1233 sSnoopLogFilterProfileMapModeSettingAtEnable = 1234 BluetoothProperties.snoop_log_filter_profile_map() 1235 .orElse(BluetoothProperties.snoop_log_filter_profile_map_values.EMPTY); 1236 1237 BluetoothProperties.snoop_default_mode( 1238 BluetoothProperties.snoop_default_mode_values.DISABLED); 1239 for (BluetoothProperties.snoop_default_mode_values value : 1240 BluetoothProperties.snoop_default_mode_values.values()) { 1241 if (value.getPropValue().equals(sDefaultSnoopLogSettingAtEnable)) { 1242 BluetoothProperties.snoop_default_mode(value); 1243 } 1244 } 1245 } else if (newState == BluetoothAdapter.STATE_BLE_ON 1246 && prevState != BluetoothAdapter.STATE_OFF) { 1247 var snoopLogSetting = 1248 BluetoothProperties.snoop_log_mode() 1249 .orElse(BluetoothProperties.snoop_log_mode_values.EMPTY); 1250 var snoopDefaultModeSetting = 1251 Settings.Global.getString( 1252 getContentResolver(), Settings.Global.BLUETOOTH_BTSNOOP_DEFAULT_MODE); 1253 1254 var snoopLogFilterHeadersSettingAtEnable = 1255 BluetoothProperties.snoop_log_filter_snoop_headers_enabled().orElse(false); 1256 var snoopLogFilterProfileA2dpSettingAtEnable = 1257 BluetoothProperties.snoop_log_filter_profile_a2dp_enabled().orElse(false); 1258 var snoopLogFilterProfileRfcommSettingAtEnable = 1259 BluetoothProperties.snoop_log_filter_profile_rfcomm_enabled().orElse(false); 1260 1261 var snoopLogFilterProfilePbapModeSetting = 1262 BluetoothProperties.snoop_log_filter_profile_pbap() 1263 .orElse(BluetoothProperties.snoop_log_filter_profile_pbap_values.EMPTY); 1264 var snoopLogFilterProfileMapModeSetting = 1265 BluetoothProperties.snoop_log_filter_profile_map() 1266 .orElse(BluetoothProperties.snoop_log_filter_profile_map_values.EMPTY); 1267 1268 if (!(sSnoopLogSettingAtEnable == snoopLogSetting) 1269 || !(sDefaultSnoopLogSettingAtEnable == snoopDefaultModeSetting) 1270 || !(sSnoopLogFilterHeadersSettingAtEnable 1271 == snoopLogFilterHeadersSettingAtEnable) 1272 || !(sSnoopLogFilterProfileA2dpSettingAtEnable 1273 == snoopLogFilterProfileA2dpSettingAtEnable) 1274 || !(sSnoopLogFilterProfileRfcommSettingAtEnable 1275 == snoopLogFilterProfileRfcommSettingAtEnable) 1276 || !(sSnoopLogFilterProfilePbapModeSettingAtEnable 1277 == snoopLogFilterProfilePbapModeSetting) 1278 || !(sSnoopLogFilterProfileMapModeSettingAtEnable 1279 == snoopLogFilterProfileMapModeSetting)) { 1280 mAdapterStateMachine.sendMessage(AdapterState.BLE_TURN_OFF); 1281 } 1282 } 1283 } 1284 linkQualityReportCallback( long timestamp, int reportId, int rssi, int snr, int retransmissionCount, int packetsNotReceiveCount, int negativeAcknowledgementCount)1285 void linkQualityReportCallback( 1286 long timestamp, 1287 int reportId, 1288 int rssi, 1289 int snr, 1290 int retransmissionCount, 1291 int packetsNotReceiveCount, 1292 int negativeAcknowledgementCount) { 1293 BluetoothInCallService bluetoothInCallService = BluetoothInCallService.getInstance(); 1294 1295 if (reportId == BqrQualityReportId.QUALITY_REPORT_ID_SCO_VOICE_CHOPPY.getValue()) { 1296 if (bluetoothInCallService == null) { 1297 Log.w( 1298 TAG, 1299 "No BluetoothInCallService while trying to send BQR." 1300 + (" timestamp: " + timestamp) 1301 + (" reportId: " + reportId) 1302 + (" rssi: " + rssi) 1303 + (" snr: " + snr) 1304 + (" retransmissionCount: " + retransmissionCount) 1305 + (" packetsNotReceiveCount: " + packetsNotReceiveCount) 1306 + (" negativeAcknowledgementCount: " 1307 + negativeAcknowledgementCount)); 1308 return; 1309 } 1310 bluetoothInCallService.sendBluetoothCallQualityReport( 1311 timestamp, 1312 rssi, 1313 snr, 1314 retransmissionCount, 1315 packetsNotReceiveCount, 1316 negativeAcknowledgementCount); 1317 } 1318 } 1319 1320 /** 1321 * Callback from Bluetooth Quality Report Native Interface to inform the listeners about 1322 * Bluetooth Quality. 1323 * 1324 * @param device is the BluetoothDevice which connection quality is being reported 1325 * @param bluetoothQualityReport a Parcel that contains information about Bluetooth Quality 1326 * @return whether the Bluetooth stack acknowledged the change successfully 1327 */ bluetoothQualityReportReadyCallback( BluetoothDevice device, BluetoothQualityReport bluetoothQualityReport)1328 public int bluetoothQualityReportReadyCallback( 1329 BluetoothDevice device, BluetoothQualityReport bluetoothQualityReport) { 1330 synchronized (mBluetoothQualityReportReadyCallbacks) { 1331 int n = mBluetoothQualityReportReadyCallbacks.beginBroadcast(); 1332 Log.d( 1333 TAG, 1334 "bluetoothQualityReportReadyCallback() - " 1335 + "Broadcasting Bluetooth Quality Report to " 1336 + n 1337 + " receivers."); 1338 for (int i = 0; i < n; i++) { 1339 try { 1340 mBluetoothQualityReportReadyCallbacks 1341 .getBroadcastItem(i) 1342 .onBluetoothQualityReportReady( 1343 device, bluetoothQualityReport, BluetoothStatusCodes.SUCCESS); 1344 } catch (RemoteException e) { 1345 Log.d( 1346 TAG, 1347 "bluetoothQualityReportReadyCallback() - Callback #" 1348 + i 1349 + " failed (" 1350 + e 1351 + ")"); 1352 } 1353 } 1354 mBluetoothQualityReportReadyCallbacks.finishBroadcast(); 1355 } 1356 1357 return BluetoothStatusCodes.SUCCESS; 1358 } 1359 switchBufferSizeCallback(boolean isLowLatencyBufferSize)1360 void switchBufferSizeCallback(boolean isLowLatencyBufferSize) { 1361 List<BluetoothDevice> activeDevices = getActiveDevices(BluetoothProfile.A2DP); 1362 if (activeDevices.size() != 1) { 1363 Log.e( 1364 TAG, 1365 "Cannot switch buffer size. The number of A2DP active devices is " 1366 + activeDevices.size()); 1367 return; 1368 } 1369 1370 // Send intent to fastpair 1371 Intent switchBufferSizeIntent = new Intent(BluetoothDevice.ACTION_SWITCH_BUFFER_SIZE); 1372 switchBufferSizeIntent.setClassName( 1373 getString(com.android.bluetooth.R.string.peripheral_link_package), 1374 getString(com.android.bluetooth.R.string.peripheral_link_package) 1375 + getString(com.android.bluetooth.R.string.peripheral_link_service)); 1376 switchBufferSizeIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, activeDevices.get(0)); 1377 switchBufferSizeIntent.putExtra( 1378 BluetoothDevice.EXTRA_LOW_LATENCY_BUFFER_SIZE, isLowLatencyBufferSize); 1379 sendBroadcastMultiplePermissions( 1380 switchBufferSizeIntent, 1381 new String[] { 1382 android.Manifest.permission.BLUETOOTH_CONNECT, 1383 android.Manifest.permission.BLUETOOTH_PRIVILEGED 1384 }, 1385 null); 1386 } 1387 switchCodecCallback(boolean isLowLatencyBufferSize)1388 void switchCodecCallback(boolean isLowLatencyBufferSize) { 1389 List<BluetoothDevice> activeDevices = getActiveDevices(BluetoothProfile.A2DP); 1390 if (activeDevices.size() != 1) { 1391 Log.e( 1392 TAG, 1393 "Cannot switch buffer size. The number of A2DP active devices is " 1394 + activeDevices.size()); 1395 return; 1396 } 1397 mA2dpService.switchCodecByBufferSize(activeDevices.get(0), isLowLatencyBufferSize); 1398 } 1399 1400 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) cleanup()1401 void cleanup() { 1402 Log.d(TAG, "cleanup()"); 1403 if (mCleaningUp) { 1404 Log.e(TAG, "cleanup() - Service already starting to cleanup, ignoring request..."); 1405 return; 1406 } 1407 1408 closeMetricsLogger(); 1409 1410 clearAdapterService(this); 1411 1412 mCleaningUp = true; 1413 invalidateBluetoothCaches(); 1414 1415 stopRfcommServerSockets(); 1416 1417 // This wake lock release may also be called concurrently by 1418 // {@link #releaseWakeLock(String lockName)}, so a synchronization is needed here. 1419 synchronized (this) { 1420 if (mWakeLock != null) { 1421 if (mWakeLock.isHeld()) { 1422 mWakeLock.release(); 1423 } 1424 mWakeLock = null; 1425 } 1426 } 1427 1428 mDatabaseManager.cleanup(); 1429 1430 if (mAdapterStateMachine != null) { 1431 mAdapterStateMachine.doQuit(); 1432 } 1433 1434 if (mBondStateMachine != null) { 1435 mBondStateMachine.doQuit(); 1436 } 1437 1438 if (mRemoteDevices != null) { 1439 mRemoteDevices.reset(); 1440 } 1441 1442 if (mSdpManager != null) { 1443 mSdpManager.cleanup(); 1444 mSdpManager = null; 1445 } 1446 1447 if (mNativeAvailable) { 1448 Log.d(TAG, "cleanup() - Cleaning up adapter native"); 1449 mNativeInterface.cleanup(); 1450 mNativeAvailable = false; 1451 } 1452 1453 if (mAdapterProperties != null) { 1454 mAdapterProperties.cleanup(); 1455 } 1456 1457 if (mNativeInterface.getCallbacks() != null) { 1458 mNativeInterface.getCallbacks().cleanup(); 1459 } 1460 1461 if (mBluetoothKeystoreService != null) { 1462 Log.d(TAG, "cleanup(): mBluetoothKeystoreService.cleanup()"); 1463 mBluetoothKeystoreService.cleanup(); 1464 } 1465 1466 if (mPhonePolicy != null) { 1467 mPhonePolicy.cleanup(); 1468 } 1469 1470 mSilenceDeviceManager.cleanup(); 1471 1472 if (mActiveDeviceManager != null) { 1473 mActiveDeviceManager.cleanup(); 1474 } 1475 1476 if (mBluetoothSocketManagerBinder != null) { 1477 mBluetoothSocketManagerBinder.cleanUp(); 1478 mBluetoothSocketManagerBinder = null; 1479 } 1480 1481 if (!Flags.explicitKillFromSystemServer()) { 1482 // Bluetooth will be killed, no need to cleanup binder 1483 if (mBinder != null) { 1484 mBinder.cleanup(); 1485 mBinder = null; // Do not remove. Otherwise Binder leak! 1486 } 1487 } 1488 1489 mPreferredAudioProfilesCallbacks.kill(); 1490 1491 mBluetoothQualityReportReadyCallbacks.kill(); 1492 1493 mRemoteCallbacks.kill(); 1494 } 1495 invalidateBluetoothCaches()1496 private void invalidateBluetoothCaches() { 1497 BluetoothAdapter.invalidateGetProfileConnectionStateCache(); 1498 BluetoothAdapter.invalidateIsOffloadedFilteringSupportedCache(); 1499 BluetoothDevice.invalidateBluetoothGetBondStateCache(); 1500 BluetoothAdapter.invalidateBluetoothGetStateCache(); 1501 BluetoothAdapter.invalidateGetAdapterConnectionStateCache(); 1502 BluetoothMap.invalidateBluetoothGetConnectionStateCache(); 1503 BluetoothSap.invalidateBluetoothGetConnectionStateCache(); 1504 } 1505 1506 private static final Map<Integer, Function<AdapterService, ProfileService>> 1507 PROFILE_CONSTRUCTORS = 1508 Map.ofEntries( 1509 Map.entry(BluetoothProfile.A2DP, A2dpService::new), 1510 Map.entry(BluetoothProfile.A2DP_SINK, A2dpSinkService::new), 1511 Map.entry(BluetoothProfile.AVRCP, AvrcpTargetService::new), 1512 Map.entry( 1513 BluetoothProfile.AVRCP_CONTROLLER, AvrcpControllerService::new), 1514 Map.entry( 1515 BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT, 1516 BassClientService::new), 1517 Map.entry(BluetoothProfile.BATTERY, BatteryService::new), 1518 Map.entry( 1519 BluetoothProfile.CSIP_SET_COORDINATOR, 1520 CsipSetCoordinatorService::new), 1521 Map.entry(BluetoothProfile.HAP_CLIENT, HapClientService::new), 1522 Map.entry(BluetoothProfile.HEADSET, HeadsetService::new), 1523 Map.entry(BluetoothProfile.HEADSET_CLIENT, HeadsetClientService::new), 1524 Map.entry(BluetoothProfile.HEARING_AID, HearingAidService::new), 1525 Map.entry(BluetoothProfile.HID_DEVICE, HidDeviceService::new), 1526 Map.entry(BluetoothProfile.HID_HOST, HidHostService::new), 1527 Map.entry(BluetoothProfile.GATT, GattService::new), 1528 Map.entry(BluetoothProfile.LE_AUDIO, LeAudioService::new), 1529 Map.entry(BluetoothProfile.LE_CALL_CONTROL, TbsService::new), 1530 Map.entry(BluetoothProfile.MAP, BluetoothMapService::new), 1531 Map.entry(BluetoothProfile.MAP_CLIENT, MapClientService::new), 1532 Map.entry(BluetoothProfile.MCP_SERVER, McpService::new), 1533 Map.entry(BluetoothProfile.OPP, BluetoothOppService::new), 1534 Map.entry(BluetoothProfile.PAN, PanService::new), 1535 Map.entry(BluetoothProfile.PBAP, BluetoothPbapService::new), 1536 Map.entry(BluetoothProfile.PBAP_CLIENT, PbapClientService::new), 1537 Map.entry(BluetoothProfile.SAP, SapService::new), 1538 Map.entry(BluetoothProfile.VOLUME_CONTROL, VolumeControlService::new)); 1539 1540 @VisibleForTesting setProfileServiceState(int profileId, int state)1541 void setProfileServiceState(int profileId, int state) { 1542 if (state == BluetoothAdapter.STATE_ON) { 1543 if (!mStartedProfiles.containsKey(profileId)) { 1544 ProfileService profileService = PROFILE_CONSTRUCTORS.get(profileId).apply(this); 1545 mStartedProfiles.put(profileId, profileService); 1546 addProfile(profileService); 1547 profileService.start(); 1548 profileService.setAvailable(true); 1549 onProfileServiceStateChanged(profileService, BluetoothAdapter.STATE_ON); 1550 } else { 1551 Log.e( 1552 TAG, 1553 "setProfileServiceState(" 1554 + BluetoothProfile.getProfileName(profileId) 1555 + ", STATE_ON): profile is already started"); 1556 } 1557 } else if (state == BluetoothAdapter.STATE_OFF) { 1558 ProfileService profileService = mStartedProfiles.remove(profileId); 1559 if (profileService != null) { 1560 profileService.setAvailable(false); 1561 onProfileServiceStateChanged(profileService, BluetoothAdapter.STATE_OFF); 1562 profileService.stop(); 1563 removeProfile(profileService); 1564 profileService.cleanup(); 1565 profileService.getBinder().cleanup(); 1566 } else { 1567 Log.e( 1568 TAG, 1569 "setProfileServiceState(" 1570 + BluetoothProfile.getProfileName(profileId) 1571 + ", STATE_OFF): profile is already stopped"); 1572 } 1573 } 1574 } 1575 setAllProfileServiceStates(int[] profileIds, int state)1576 private void setAllProfileServiceStates(int[] profileIds, int state) { 1577 for (int profileId : profileIds) { 1578 if (!Flags.scanManagerRefactor()) { 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 1661 @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) isProfileSupported(BluetoothDevice device, int profile)1662 boolean isProfileSupported(BluetoothDevice device, int profile) { 1663 ParcelUuid[] remoteDeviceUuids = getRemoteUuids(device); 1664 ParcelUuid[] localDeviceUuids = mAdapterProperties.getUuids(); 1665 if (remoteDeviceUuids == null || remoteDeviceUuids.length == 0) { 1666 Log.e( 1667 TAG, 1668 "isProfileSupported(" 1669 + ("device=" + device) 1670 + (", profile=" + BluetoothProfile.getProfileName(profile) + "):") 1671 + " remote device Uuids Empty"); 1672 } 1673 1674 Log.v( 1675 TAG, 1676 "isProfileSupported(" 1677 + ("device=" + device) 1678 + (", profile=" + BluetoothProfile.getProfileName(profile) + "):") 1679 + (" local_uuids=" + Arrays.toString(localDeviceUuids)) 1680 + (", remote_uuids=" + Arrays.toString(remoteDeviceUuids))); 1681 1682 if (profile == BluetoothProfile.HEADSET) { 1683 return (Utils.arrayContains(localDeviceUuids, BluetoothUuid.HSP_AG) 1684 && Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HSP)) 1685 || (Utils.arrayContains(localDeviceUuids, BluetoothUuid.HFP_AG) 1686 && Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HFP)); 1687 } 1688 if (profile == BluetoothProfile.HEADSET_CLIENT) { 1689 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HFP_AG) 1690 && Utils.arrayContains(localDeviceUuids, BluetoothUuid.HFP); 1691 } 1692 if (profile == BluetoothProfile.A2DP) { 1693 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.ADV_AUDIO_DIST) 1694 || Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.A2DP_SINK); 1695 } 1696 if (profile == BluetoothProfile.A2DP_SINK) { 1697 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.ADV_AUDIO_DIST) 1698 || Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.A2DP_SOURCE); 1699 } 1700 if (profile == BluetoothProfile.OPP) { 1701 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.OBEX_OBJECT_PUSH); 1702 } 1703 if (profile == BluetoothProfile.HID_HOST) { 1704 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HID) 1705 || Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HOGP) 1706 || (Flags.androidHeadtrackerService() 1707 && Utils.arrayContains( 1708 remoteDeviceUuids, HidHostService.ANDROID_HEADTRACKER_UUID)); 1709 } 1710 if (profile == BluetoothProfile.HID_DEVICE) { 1711 return mHidDeviceService.getConnectionState(device) 1712 == BluetoothProfile.STATE_DISCONNECTED; 1713 } 1714 if (profile == BluetoothProfile.PAN) { 1715 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.NAP); 1716 } 1717 if (profile == BluetoothProfile.MAP) { 1718 return mMapService.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED; 1719 } 1720 if (profile == BluetoothProfile.PBAP) { 1721 return mPbapService.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED; 1722 } 1723 if (profile == BluetoothProfile.MAP_CLIENT) { 1724 return Utils.arrayContains(localDeviceUuids, BluetoothUuid.MNS) 1725 && Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.MAS); 1726 } 1727 if (profile == BluetoothProfile.PBAP_CLIENT) { 1728 return Utils.arrayContains(localDeviceUuids, BluetoothUuid.PBAP_PCE) 1729 && Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.PBAP_PSE); 1730 } 1731 if (profile == BluetoothProfile.HEARING_AID) { 1732 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HEARING_AID); 1733 } 1734 if (profile == BluetoothProfile.SAP) { 1735 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.SAP); 1736 } 1737 if (profile == BluetoothProfile.VOLUME_CONTROL) { 1738 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.VOLUME_CONTROL); 1739 } 1740 if (profile == BluetoothProfile.CSIP_SET_COORDINATOR) { 1741 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.COORDINATED_SET); 1742 } 1743 if (profile == BluetoothProfile.LE_AUDIO) { 1744 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.LE_AUDIO); 1745 } 1746 if (profile == BluetoothProfile.HAP_CLIENT) { 1747 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HAS); 1748 } 1749 if (profile == BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT) { 1750 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.BASS); 1751 } 1752 if (profile == BluetoothProfile.BATTERY) { 1753 return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.BATTERY); 1754 } 1755 1756 Log.e(TAG, "isSupported: Unexpected profile passed in to function: " + profile); 1757 return false; 1758 } 1759 1760 /** 1761 * Checks if the connection policy of all profiles are unknown for the given device 1762 * 1763 * @param device is the device for which we are checking if the connection policy of all 1764 * profiles are unknown 1765 * @return false if one of profile is enabled or disabled, true otherwise 1766 */ 1767 @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) isAllProfilesUnknown(BluetoothDevice device)1768 boolean isAllProfilesUnknown(BluetoothDevice device) { 1769 if (mA2dpService != null 1770 && mA2dpService.getConnectionPolicy(device) 1771 != BluetoothProfile.CONNECTION_POLICY_UNKNOWN) { 1772 return false; 1773 } 1774 if (mA2dpSinkService != null 1775 && mA2dpSinkService.getConnectionPolicy(device) 1776 != BluetoothProfile.CONNECTION_POLICY_UNKNOWN) { 1777 return false; 1778 } 1779 if (mHeadsetService != null 1780 && mHeadsetService.getConnectionPolicy(device) 1781 != BluetoothProfile.CONNECTION_POLICY_UNKNOWN) { 1782 return false; 1783 } 1784 if (mHeadsetClientService != null 1785 && mHeadsetClientService.getConnectionPolicy(device) 1786 != BluetoothProfile.CONNECTION_POLICY_UNKNOWN) { 1787 return false; 1788 } 1789 if (mMapClientService != null 1790 && mMapClientService.getConnectionPolicy(device) 1791 != BluetoothProfile.CONNECTION_POLICY_UNKNOWN) { 1792 return false; 1793 } 1794 if (mHidHostService != null 1795 && mHidHostService.getConnectionPolicy(device) 1796 != BluetoothProfile.CONNECTION_POLICY_UNKNOWN) { 1797 return false; 1798 } 1799 if (mPanService != null 1800 && mPanService.getConnectionPolicy(device) 1801 != BluetoothProfile.CONNECTION_POLICY_UNKNOWN) { 1802 return false; 1803 } 1804 if (mPbapClientService != null 1805 && mPbapClientService.getConnectionPolicy(device) 1806 != BluetoothProfile.CONNECTION_POLICY_UNKNOWN) { 1807 return false; 1808 } 1809 if (mHearingAidService != null 1810 && mHearingAidService.getConnectionPolicy(device) 1811 != BluetoothProfile.CONNECTION_POLICY_UNKNOWN) { 1812 return false; 1813 } 1814 if (mHapClientService != null 1815 && mHapClientService.getConnectionPolicy(device) 1816 != BluetoothProfile.CONNECTION_POLICY_UNKNOWN) { 1817 return false; 1818 } 1819 if (mVolumeControlService != null 1820 && mVolumeControlService.getConnectionPolicy(device) 1821 != BluetoothProfile.CONNECTION_POLICY_UNKNOWN) { 1822 return false; 1823 } 1824 if (mCsipSetCoordinatorService != null 1825 && mCsipSetCoordinatorService.getConnectionPolicy(device) 1826 != BluetoothProfile.CONNECTION_POLICY_UNKNOWN) { 1827 return false; 1828 } 1829 if (mLeAudioService != null 1830 && mLeAudioService.getConnectionPolicy(device) 1831 != BluetoothProfile.CONNECTION_POLICY_UNKNOWN) { 1832 return false; 1833 } 1834 if (mBassClientService != null 1835 && mBassClientService.getConnectionPolicy(device) 1836 != BluetoothProfile.CONNECTION_POLICY_UNKNOWN) { 1837 return false; 1838 } 1839 return true; 1840 } 1841 1842 /** 1843 * Connects only available profiles (those with {@link 1844 * BluetoothProfile#CONNECTION_POLICY_ALLOWED}) 1845 * 1846 * @param device is the device with which we are connecting the profiles 1847 * @return {@link BluetoothStatusCodes#SUCCESS} 1848 */ 1849 @RequiresPermission( 1850 allOf = { 1851 android.Manifest.permission.BLUETOOTH_PRIVILEGED, 1852 android.Manifest.permission.MODIFY_PHONE_STATE, 1853 }) connectEnabledProfiles(BluetoothDevice device)1854 private int connectEnabledProfiles(BluetoothDevice device) { 1855 if (mCsipSetCoordinatorService != null 1856 && isProfileSupported(device, BluetoothProfile.CSIP_SET_COORDINATOR) 1857 && mCsipSetCoordinatorService.getConnectionPolicy(device) 1858 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1859 Log.i(TAG, "connectEnabledProfiles: Connecting Coordinated Set Profile"); 1860 mCsipSetCoordinatorService.connect(device); 1861 } 1862 if (mA2dpService != null 1863 && isProfileSupported(device, BluetoothProfile.A2DP) 1864 && mA2dpService.getConnectionPolicy(device) 1865 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1866 Log.i(TAG, "connectEnabledProfiles: Connecting A2dp"); 1867 mA2dpService.connect(device); 1868 } 1869 if (mA2dpSinkService != null 1870 && isProfileSupported(device, BluetoothProfile.A2DP_SINK) 1871 && mA2dpSinkService.getConnectionPolicy(device) 1872 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1873 Log.i(TAG, "connectEnabledProfiles: Connecting A2dp Sink"); 1874 mA2dpSinkService.connect(device); 1875 } 1876 if (mHeadsetService != null 1877 && isProfileSupported(device, BluetoothProfile.HEADSET) 1878 && mHeadsetService.getConnectionPolicy(device) 1879 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1880 Log.i(TAG, "connectEnabledProfiles: Connecting Headset Profile"); 1881 mHeadsetService.connect(device); 1882 } 1883 if (mHeadsetClientService != null 1884 && isProfileSupported(device, BluetoothProfile.HEADSET_CLIENT) 1885 && mHeadsetClientService.getConnectionPolicy(device) 1886 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1887 Log.i(TAG, "connectEnabledProfiles: Connecting HFP"); 1888 mHeadsetClientService.connect(device); 1889 } 1890 if (mMapClientService != null 1891 && isProfileSupported(device, BluetoothProfile.MAP_CLIENT) 1892 && mMapClientService.getConnectionPolicy(device) 1893 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1894 Log.i(TAG, "connectEnabledProfiles: Connecting MAP"); 1895 mMapClientService.connect(device); 1896 } 1897 if (mHidHostService != null 1898 && isProfileSupported(device, BluetoothProfile.HID_HOST) 1899 && mHidHostService.getConnectionPolicy(device) 1900 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1901 Log.i(TAG, "connectEnabledProfiles: Connecting Hid Host Profile"); 1902 mHidHostService.connect(device); 1903 } 1904 if (mPanService != null 1905 && isProfileSupported(device, BluetoothProfile.PAN) 1906 && mPanService.getConnectionPolicy(device) 1907 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1908 Log.i(TAG, "connectEnabledProfiles: Connecting Pan Profile"); 1909 mPanService.connect(device); 1910 } 1911 if (mPbapClientService != null 1912 && isProfileSupported(device, BluetoothProfile.PBAP_CLIENT) 1913 && mPbapClientService.getConnectionPolicy(device) 1914 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1915 Log.i(TAG, "connectEnabledProfiles: Connecting Pbap"); 1916 mPbapClientService.connect(device); 1917 } 1918 if (mHearingAidService != null 1919 && isProfileSupported(device, BluetoothProfile.HEARING_AID) 1920 && mHearingAidService.getConnectionPolicy(device) 1921 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1922 Log.i(TAG, "connectEnabledProfiles: Connecting Hearing Aid Profile"); 1923 mHearingAidService.connect(device); 1924 } 1925 if (mHapClientService != null 1926 && isProfileSupported(device, BluetoothProfile.HAP_CLIENT) 1927 && mHapClientService.getConnectionPolicy(device) 1928 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1929 Log.i(TAG, "connectEnabledProfiles: Connecting HAS Profile"); 1930 mHapClientService.connect(device); 1931 } 1932 if (mVolumeControlService != null 1933 && isProfileSupported(device, BluetoothProfile.VOLUME_CONTROL) 1934 && mVolumeControlService.getConnectionPolicy(device) 1935 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1936 Log.i(TAG, "connectEnabledProfiles: Connecting Volume Control Profile"); 1937 mVolumeControlService.connect(device); 1938 } 1939 if (mLeAudioService != null 1940 && isProfileSupported(device, BluetoothProfile.LE_AUDIO) 1941 && mLeAudioService.getConnectionPolicy(device) 1942 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1943 Log.i(TAG, "connectEnabledProfiles: Connecting LeAudio profile (BAP)"); 1944 mLeAudioService.connect(device); 1945 } 1946 if (mBassClientService != null 1947 && isProfileSupported(device, BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT) 1948 && mBassClientService.getConnectionPolicy(device) 1949 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1950 Log.i(TAG, "connectEnabledProfiles: Connecting LE Broadcast Assistant Profile"); 1951 mBassClientService.connect(device); 1952 } 1953 if (mBatteryService != null 1954 && isProfileSupported(device, BluetoothProfile.BATTERY) 1955 && mBatteryService.getConnectionPolicy(device) 1956 > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { 1957 Log.i(TAG, "connectEnabledProfiles: Connecting Battery Service"); 1958 mBatteryService.connect(device); 1959 } 1960 return BluetoothStatusCodes.SUCCESS; 1961 } 1962 1963 /** 1964 * Verifies that all bluetooth profile services are running 1965 * 1966 * @return true if all bluetooth profile services running, false otherwise 1967 */ profileServicesRunning()1968 private boolean profileServicesRunning() { 1969 if (mRegisteredProfiles.size() == Config.getSupportedProfiles().length 1970 && mRegisteredProfiles.size() == mRunningProfiles.size()) { 1971 return true; 1972 } 1973 1974 Log.e(TAG, "profileServicesRunning: One or more supported services not running"); 1975 return false; 1976 } 1977 1978 /** Initializes all the profile services fields */ initProfileServices()1979 private void initProfileServices() { 1980 Log.i(TAG, "initProfileServices: Initializing all bluetooth profile services"); 1981 mA2dpService = A2dpService.getA2dpService(); 1982 mA2dpSinkService = A2dpSinkService.getA2dpSinkService(); 1983 mHeadsetService = HeadsetService.getHeadsetService(); 1984 mHeadsetClientService = HeadsetClientService.getHeadsetClientService(); 1985 mMapService = BluetoothMapService.getBluetoothMapService(); 1986 mMapClientService = MapClientService.getMapClientService(); 1987 mHidDeviceService = HidDeviceService.getHidDeviceService(); 1988 mHidHostService = HidHostService.getHidHostService(); 1989 mPanService = PanService.getPanService(); 1990 mPbapService = BluetoothPbapService.getBluetoothPbapService(); 1991 mPbapClientService = PbapClientService.getPbapClientService(); 1992 mHearingAidService = HearingAidService.getHearingAidService(); 1993 mHapClientService = HapClientService.getHapClientService(); 1994 mSapService = SapService.getSapService(); 1995 mVolumeControlService = VolumeControlService.getVolumeControlService(); 1996 mCsipSetCoordinatorService = CsipSetCoordinatorService.getCsipSetCoordinatorService(); 1997 mLeAudioService = LeAudioService.getLeAudioService(); 1998 mBassClientService = BassClientService.getBassClientService(); 1999 mBatteryService = BatteryService.getBatteryService(); 2000 if (Flags.scanManagerRefactor()) { 2001 mGattService = GattService.getGattService(); 2002 } 2003 } 2004 2005 @BluetoothAdapter.RfcommListenerResult 2006 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) startRfcommListener( String name, ParcelUuid uuid, PendingIntent pendingIntent, AttributionSource attributionSource)2007 private int startRfcommListener( 2008 String name, 2009 ParcelUuid uuid, 2010 PendingIntent pendingIntent, 2011 AttributionSource attributionSource) { 2012 if (mBluetoothServerSockets.containsKey(uuid.getUuid())) { 2013 Log.d( 2014 TAG, 2015 String.format( 2016 "Cannot start RFCOMM listener: UUID %s already in use.", 2017 uuid.getUuid())); 2018 return BluetoothStatusCodes.RFCOMM_LISTENER_START_FAILED_UUID_IN_USE; 2019 } 2020 2021 try { 2022 startRfcommListenerInternal(name, uuid.getUuid(), pendingIntent, attributionSource); 2023 } catch (IOException e) { 2024 return BluetoothStatusCodes.RFCOMM_LISTENER_FAILED_TO_CREATE_SERVER_SOCKET; 2025 } 2026 2027 return BluetoothStatusCodes.SUCCESS; 2028 } 2029 2030 @BluetoothAdapter.RfcommListenerResult 2031 @VisibleForTesting stopRfcommListener(ParcelUuid uuid, AttributionSource attributionSource)2032 int stopRfcommListener(ParcelUuid uuid, AttributionSource attributionSource) { 2033 RfcommListenerData listenerData = mBluetoothServerSockets.get(uuid.getUuid()); 2034 2035 if (listenerData == null) { 2036 Log.d( 2037 TAG, 2038 String.format( 2039 "Cannot stop RFCOMM listener: UUID %s is not registered.", 2040 uuid.getUuid())); 2041 return BluetoothStatusCodes.RFCOMM_LISTENER_OPERATION_FAILED_NO_MATCHING_SERVICE_RECORD; 2042 } 2043 2044 if (attributionSource.getUid() != listenerData.mAttributionSource.getUid()) { 2045 return BluetoothStatusCodes.RFCOMM_LISTENER_OPERATION_FAILED_DIFFERENT_APP; 2046 } 2047 2048 // Remove the entry so that it does not try and restart the server socket. 2049 mBluetoothServerSockets.remove(uuid.getUuid()); 2050 2051 return listenerData.closeServerAndPendingSockets(mHandler); 2052 } 2053 2054 @VisibleForTesting retrievePendingSocketForServiceRecord( ParcelUuid uuid, AttributionSource attributionSource)2055 IncomingRfcommSocketInfo retrievePendingSocketForServiceRecord( 2056 ParcelUuid uuid, AttributionSource attributionSource) { 2057 IncomingRfcommSocketInfo socketInfo = new IncomingRfcommSocketInfo(); 2058 2059 RfcommListenerData listenerData = mBluetoothServerSockets.get(uuid.getUuid()); 2060 2061 if (listenerData == null) { 2062 socketInfo.status = 2063 BluetoothStatusCodes 2064 .RFCOMM_LISTENER_OPERATION_FAILED_NO_MATCHING_SERVICE_RECORD; 2065 return socketInfo; 2066 } 2067 2068 if (attributionSource.getUid() != listenerData.mAttributionSource.getUid()) { 2069 socketInfo.status = BluetoothStatusCodes.RFCOMM_LISTENER_OPERATION_FAILED_DIFFERENT_APP; 2070 return socketInfo; 2071 } 2072 2073 BluetoothSocket socket = listenerData.mPendingSockets.poll(); 2074 2075 if (socket == null) { 2076 socketInfo.status = BluetoothStatusCodes.RFCOMM_LISTENER_NO_SOCKET_AVAILABLE; 2077 return socketInfo; 2078 } 2079 2080 mHandler.removeCallbacksAndMessages(socket); 2081 2082 socketInfo.bluetoothDevice = socket.getRemoteDevice(); 2083 socketInfo.pfd = socket.getParcelFileDescriptor(); 2084 socketInfo.status = BluetoothStatusCodes.SUCCESS; 2085 2086 return socketInfo; 2087 } 2088 2089 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) handleIncomingRfcommConnections(UUID uuid)2090 private void handleIncomingRfcommConnections(UUID uuid) { 2091 RfcommListenerData listenerData = mBluetoothServerSockets.get(uuid); 2092 while (true) { 2093 BluetoothSocket socket; 2094 try { 2095 socket = listenerData.mServerSocket.accept(); 2096 } catch (IOException e) { 2097 if (mBluetoothServerSockets.containsKey(uuid)) { 2098 // The uuid still being in the map indicates that the accept failure is 2099 // unexpected. Try and restart the listener. 2100 Log.e(TAG, "Failed to accept socket on " + listenerData.mServerSocket, e); 2101 restartRfcommListener(listenerData, uuid); 2102 } 2103 return; 2104 } 2105 2106 listenerData.mPendingSockets.add(socket); 2107 try { 2108 listenerData.mPendingIntent.send(); 2109 } catch (PendingIntent.CanceledException e) { 2110 Log.e(TAG, "PendingIntent for RFCOMM socket notifications cancelled.", e); 2111 // The pending intent was cancelled, close the server as there is no longer any way 2112 // to notify the app that registered the listener. 2113 listenerData.closeServerAndPendingSockets(mHandler); 2114 mBluetoothServerSockets.remove(uuid); 2115 return; 2116 } 2117 mHandler.postDelayed( 2118 () -> pendingSocketTimeoutRunnable(listenerData, socket), 2119 socket, 2120 PENDING_SOCKET_HANDOFF_TIMEOUT.toMillis()); 2121 } 2122 } 2123 2124 // Tries to restart the rfcomm listener for the given UUID 2125 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) restartRfcommListener(RfcommListenerData listenerData, UUID uuid)2126 private void restartRfcommListener(RfcommListenerData listenerData, UUID uuid) { 2127 listenerData.closeServerAndPendingSockets(mHandler); 2128 try { 2129 startRfcommListenerInternal( 2130 listenerData.mName, 2131 uuid, 2132 listenerData.mPendingIntent, 2133 listenerData.mAttributionSource); 2134 } catch (IOException e) { 2135 Log.e(TAG, "Failed to recreate rfcomm server socket", e); 2136 2137 mBluetoothServerSockets.remove(uuid); 2138 } 2139 } 2140 pendingSocketTimeoutRunnable( RfcommListenerData listenerData, BluetoothSocket socket)2141 private void pendingSocketTimeoutRunnable( 2142 RfcommListenerData listenerData, BluetoothSocket socket) { 2143 boolean socketFound = listenerData.mPendingSockets.remove(socket); 2144 if (socketFound) { 2145 try { 2146 socket.close(); 2147 } catch (IOException e) { 2148 Log.e(TAG, "Failed to close bt socket", e); 2149 // We don't care if closing the socket failed, just continue on. 2150 } 2151 } 2152 } 2153 2154 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) startRfcommListenerInternal( String name, UUID uuid, PendingIntent intent, AttributionSource attributionSource)2155 private void startRfcommListenerInternal( 2156 String name, UUID uuid, PendingIntent intent, AttributionSource attributionSource) 2157 throws IOException { 2158 BluetoothServerSocket bluetoothServerSocket = 2159 mAdapter.listenUsingRfcommWithServiceRecord(name, uuid); 2160 2161 RfcommListenerData listenerData = 2162 new RfcommListenerData(bluetoothServerSocket, name, intent, attributionSource); 2163 2164 mBluetoothServerSockets.put(uuid, listenerData); 2165 2166 new Thread(() -> handleIncomingRfcommConnections(uuid)).start(); 2167 } 2168 stopRfcommServerSockets()2169 private void stopRfcommServerSockets() { 2170 Iterator<Map.Entry<UUID, RfcommListenerData>> socketsIterator = 2171 mBluetoothServerSockets.entrySet().iterator(); 2172 while (socketsIterator.hasNext()) { 2173 socketsIterator.next().getValue().closeServerAndPendingSockets(mHandler); 2174 socketsIterator.remove(); 2175 } 2176 } 2177 2178 private static class RfcommListenerData { 2179 final BluetoothServerSocket mServerSocket; 2180 // Service record name 2181 final String mName; 2182 // The Intent which contains the Service info to which the incoming socket connections are 2183 // handed off to. 2184 final PendingIntent mPendingIntent; 2185 // AttributionSource for the requester of the RFCOMM listener 2186 final AttributionSource mAttributionSource; 2187 // Contains the connected sockets which are pending transfer to the app which requested the 2188 // listener. 2189 final ConcurrentLinkedQueue<BluetoothSocket> mPendingSockets = 2190 new ConcurrentLinkedQueue<>(); 2191 RfcommListenerData( BluetoothServerSocket serverSocket, String name, PendingIntent pendingIntent, AttributionSource attributionSource)2192 RfcommListenerData( 2193 BluetoothServerSocket serverSocket, 2194 String name, 2195 PendingIntent pendingIntent, 2196 AttributionSource attributionSource) { 2197 mServerSocket = serverSocket; 2198 mName = name; 2199 mPendingIntent = pendingIntent; 2200 mAttributionSource = attributionSource; 2201 } 2202 closeServerAndPendingSockets(Handler handler)2203 int closeServerAndPendingSockets(Handler handler) { 2204 int result = BluetoothStatusCodes.SUCCESS; 2205 try { 2206 mServerSocket.close(); 2207 } catch (IOException e) { 2208 Log.e(TAG, "Failed to call close on rfcomm server socket", e); 2209 result = BluetoothStatusCodes.RFCOMM_LISTENER_FAILED_TO_CLOSE_SERVER_SOCKET; 2210 } 2211 mPendingSockets.forEach( 2212 pendingSocket -> { 2213 handler.removeCallbacksAndMessages(pendingSocket); 2214 try { 2215 pendingSocket.close(); 2216 } catch (IOException e) { 2217 Log.e(TAG, "Failed to close socket", e); 2218 } 2219 }); 2220 mPendingSockets.clear(); 2221 2222 return result; 2223 } 2224 } 2225 2226 @VisibleForTesting isAvailable()2227 boolean isAvailable() { 2228 return !mCleaningUp; 2229 } 2230 2231 /** 2232 * Get an metadata of given device and key 2233 * 2234 * @param device Bluetooth device 2235 * @param key Metadata key 2236 * @param value Metadata value 2237 * @return if metadata is set successfully 2238 */ setMetadata(BluetoothDevice device, int key, byte[] value)2239 public boolean setMetadata(BluetoothDevice device, int key, byte[] value) { 2240 if (value == null || value.length > BluetoothDevice.METADATA_MAX_LENGTH) { 2241 return false; 2242 } 2243 return mDatabaseManager.setCustomMeta(device, key, value); 2244 } 2245 2246 /** 2247 * Get an metadata of given device and key 2248 * 2249 * @param device Bluetooth device 2250 * @param key Metadata key 2251 * @return value of given device and key combination 2252 */ getMetadata(BluetoothDevice device, int key)2253 public byte[] getMetadata(BluetoothDevice device, int key) { 2254 return mDatabaseManager.getCustomMeta(device, key); 2255 } 2256 2257 /** Update Adapter Properties when BT profiles connection state changes. */ updateProfileConnectionAdapterProperties( BluetoothDevice device, int profile, int state, int prevState)2258 public void updateProfileConnectionAdapterProperties( 2259 BluetoothDevice device, int profile, int state, int prevState) { 2260 mHandler.post( 2261 () -> 2262 mAdapterProperties.updateOnProfileConnectionChanged( 2263 device, profile, state, prevState)); 2264 } 2265 2266 /** 2267 * The Binder implementation must be declared to be a static class, with the AdapterService 2268 * instance passed in the constructor. Furthermore, when the AdapterService shuts down, the 2269 * reference to the AdapterService must be explicitly removed. 2270 * 2271 * <p>Otherwise, a memory leak can occur from repeated starting/stopping the service...Please 2272 * refer to android.os.Binder for further details on why an inner instance class should be 2273 * avoided. 2274 * 2275 * <p>TODO: b/339548431 -- Delete this comment as it does not apply when we get killed 2276 */ 2277 @VisibleForTesting 2278 public static class AdapterServiceBinder extends IBluetooth.Stub { 2279 // TODO: b/339548431 move variable to final 2280 private AdapterService mService; 2281 AdapterServiceBinder(AdapterService svc)2282 AdapterServiceBinder(AdapterService svc) { 2283 mService = svc; 2284 mService.invalidateBluetoothGetStateCache(); 2285 BluetoothAdapter.getDefaultAdapter().disableBluetoothGetStateCache(); 2286 } 2287 cleanup()2288 public void cleanup() { 2289 mService = null; 2290 } 2291 getService()2292 public AdapterService getService() { 2293 if (mService != null && mService.isAvailable()) { 2294 return mService; 2295 } 2296 return null; 2297 } 2298 2299 @Override getState()2300 public int getState() { 2301 AdapterService service = getService(); 2302 if (service == null) { 2303 return BluetoothAdapter.STATE_OFF; 2304 } 2305 2306 return service.getState(); 2307 } 2308 2309 @Override killBluetoothProcess()2310 public void killBluetoothProcess() { 2311 mService.enforceCallingPermission( 2312 android.Manifest.permission.BLUETOOTH_PRIVILEGED, null); 2313 2314 Runnable killAction = 2315 () -> { 2316 if (Flags.killInsteadOfExit()) { 2317 Log.i(TAG, "killBluetoothProcess: Calling killProcess(myPid())"); 2318 Process.killProcess(Process.myPid()); 2319 } else { 2320 Log.i(TAG, "killBluetoothProcess: Calling System.exit"); 2321 System.exit(0); 2322 } 2323 }; 2324 2325 // Post on the main handler to let the cleanup complete before calling exit 2326 mService.mHandler.post(killAction); 2327 2328 try { 2329 // Wait for Bluetooth to be killed from its main thread 2330 Thread.sleep(950); // SystemServer is waiting 1000 ms, we need to wait less here 2331 } catch (InterruptedException e) { 2332 Log.e(TAG, "killBluetoothProcess: Interrupted while waiting for kill"); 2333 } 2334 2335 // Bluetooth cannot be killed on the main thread; it is in a deadLock. 2336 // Trying to recover by killing the Bluetooth from the binder thread. 2337 // This is bad :( 2338 Counter.logIncrement("bluetooth.value_kill_from_binder_thread"); 2339 Log.wtf(TAG, "Failed to kill Bluetooth using its main thread. Trying from binder"); 2340 killAction.run(); 2341 } 2342 2343 @Override enable(boolean quietMode, AttributionSource attributionSource)2344 public void enable(boolean quietMode, AttributionSource attributionSource) { 2345 AdapterService service = getService(); 2346 if (service == null 2347 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "enable") 2348 || !Utils.checkConnectPermissionForDataDelivery( 2349 service, attributionSource, "AdapterService enable")) { 2350 return; 2351 } 2352 2353 service.enable(quietMode); 2354 } 2355 2356 @Override disable(AttributionSource attributionSource)2357 public void disable(AttributionSource attributionSource) { 2358 AdapterService service = getService(); 2359 if (service == null 2360 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "disable") 2361 || !Utils.checkConnectPermissionForDataDelivery( 2362 service, attributionSource, "AdapterService disable")) { 2363 return; 2364 } 2365 2366 service.disable(); 2367 } 2368 2369 @Override getAddress(AttributionSource attributionSource)2370 public String getAddress(AttributionSource attributionSource) { 2371 AdapterService service = getService(); 2372 if (service == null 2373 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getAddress") 2374 || !Utils.checkConnectPermissionForDataDelivery( 2375 service, attributionSource, "AdapterService getAddress")) { 2376 return null; 2377 } 2378 2379 enforceLocalMacAddressPermission(service); 2380 2381 return Utils.getAddressStringFromByte(service.mAdapterProperties.getAddress()); 2382 } 2383 2384 @Override isLogRedactionEnabled()2385 public boolean isLogRedactionEnabled() { 2386 AdapterService service = getService(); 2387 if (service == null) { 2388 return true; 2389 } 2390 return service.mNativeInterface.isLogRedactionEnabled(); 2391 } 2392 2393 @Override getUuids(AttributionSource attributionSource)2394 public List<ParcelUuid> getUuids(AttributionSource attributionSource) { 2395 AdapterService service = getService(); 2396 if (service == null 2397 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getUuids") 2398 || !Utils.checkConnectPermissionForDataDelivery( 2399 service, attributionSource, "AdapterService getUuids")) { 2400 return Collections.emptyList(); 2401 } 2402 2403 ParcelUuid[] parcels = service.mAdapterProperties.getUuids(); 2404 if (parcels == null) { 2405 parcels = new ParcelUuid[0]; 2406 } 2407 return Arrays.asList(parcels); 2408 } 2409 2410 @Override getIdentityAddress(String address)2411 public String getIdentityAddress(String address) { 2412 AdapterService service = getService(); 2413 if (service == null 2414 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getIdentityAddress") 2415 || !Utils.checkConnectPermissionForDataDelivery( 2416 service, 2417 Utils.getCallingAttributionSource(mService), 2418 "AdapterService getIdentityAddress")) { 2419 return null; 2420 } 2421 enforceBluetoothPrivilegedPermission(service); 2422 return service.getIdentityAddress(address); 2423 } 2424 2425 @Override getName(AttributionSource attributionSource)2426 public String getName(AttributionSource attributionSource) { 2427 AdapterService service = getService(); 2428 if (service == null 2429 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getName") 2430 || !Utils.checkConnectPermissionForDataDelivery( 2431 service, attributionSource, "AdapterService getName")) { 2432 return null; 2433 } 2434 2435 return service.getName(); 2436 } 2437 2438 @Override getNameLengthForAdvertise(AttributionSource attributionSource)2439 public int getNameLengthForAdvertise(AttributionSource attributionSource) { 2440 AdapterService service = getService(); 2441 if (service == null 2442 || !callerIsSystemOrActiveOrManagedUser( 2443 service, TAG, "getNameLengthForAdvertise") 2444 || !Utils.checkAdvertisePermissionForDataDelivery( 2445 service, attributionSource, TAG)) { 2446 return -1; 2447 } 2448 2449 return service.getNameLengthForAdvertise(); 2450 } 2451 2452 @Override setName(String name, AttributionSource attributionSource)2453 public boolean setName(String name, AttributionSource attributionSource) { 2454 AdapterService service = getService(); 2455 if (service == null 2456 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setName") 2457 || !Utils.checkConnectPermissionForDataDelivery( 2458 service, attributionSource, "AdapterService setName")) { 2459 return false; 2460 } 2461 2462 Log.d(TAG, "AdapterServiceBinder.setName(" + name + ")"); 2463 return service.mAdapterProperties.setName(name); 2464 } 2465 2466 @Override getScanMode(AttributionSource attributionSource)2467 public int getScanMode(AttributionSource attributionSource) { 2468 AdapterService service = getService(); 2469 if (service == null 2470 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getScanMode") 2471 || !Utils.checkScanPermissionForDataDelivery( 2472 service, attributionSource, "AdapterService getScanMode")) { 2473 return BluetoothAdapter.SCAN_MODE_NONE; 2474 } 2475 2476 return service.getScanMode(); 2477 } 2478 2479 @Override setScanMode(int mode, AttributionSource attributionSource)2480 public int setScanMode(int mode, AttributionSource attributionSource) { 2481 AdapterService service = getService(); 2482 if (service == null 2483 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setScanMode") 2484 || !Utils.checkScanPermissionForDataDelivery( 2485 service, attributionSource, "AdapterService setScanMode")) { 2486 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_SCAN_PERMISSION; 2487 } 2488 enforceBluetoothPrivilegedPermission(service); 2489 2490 return service.mAdapterProperties.setScanMode(mode) 2491 ? BluetoothStatusCodes.SUCCESS 2492 : BluetoothStatusCodes.ERROR_UNKNOWN; 2493 } 2494 2495 @Override getDiscoverableTimeout(AttributionSource attributionSource)2496 public long getDiscoverableTimeout(AttributionSource attributionSource) { 2497 AdapterService service = getService(); 2498 if (service == null 2499 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getDiscoverableTimeout") 2500 || !Utils.checkScanPermissionForDataDelivery( 2501 service, attributionSource, "AdapterService getDiscoverableTimeout")) { 2502 return -1; 2503 } 2504 2505 return service.mAdapterProperties.getDiscoverableTimeout(); 2506 } 2507 2508 @Override setDiscoverableTimeout(long timeout, AttributionSource attributionSource)2509 public int setDiscoverableTimeout(long timeout, AttributionSource attributionSource) { 2510 AdapterService service = getService(); 2511 if (service == null 2512 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setDiscoverableTimeout") 2513 || !Utils.checkScanPermissionForDataDelivery( 2514 service, attributionSource, "AdapterService setDiscoverableTimeout")) { 2515 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_SCAN_PERMISSION; 2516 } 2517 enforceBluetoothPrivilegedPermission(service); 2518 2519 return service.mAdapterProperties.setDiscoverableTimeout((int) timeout) 2520 ? BluetoothStatusCodes.SUCCESS 2521 : BluetoothStatusCodes.ERROR_UNKNOWN; 2522 } 2523 2524 @Override startDiscovery(AttributionSource attributionSource)2525 public boolean startDiscovery(AttributionSource attributionSource) { 2526 AdapterService service = getService(); 2527 if (service == null 2528 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "startDiscovery")) { 2529 return false; 2530 } 2531 2532 if (!Utils.checkScanPermissionForDataDelivery( 2533 service, attributionSource, "Starting discovery.")) { 2534 return false; 2535 } 2536 2537 Log.i(TAG, "startDiscovery: from " + Utils.getUidPidString()); 2538 return service.startDiscovery(attributionSource); 2539 } 2540 2541 @Override cancelDiscovery(AttributionSource attributionSource)2542 public boolean cancelDiscovery(AttributionSource attributionSource) { 2543 AdapterService service = getService(); 2544 if (service == null 2545 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "cancelDiscovery") 2546 || !Utils.checkScanPermissionForDataDelivery( 2547 service, attributionSource, "AdapterService cancelDiscovery")) { 2548 return false; 2549 } 2550 2551 Log.i(TAG, "cancelDiscovery: from " + Utils.getUidPidString()); 2552 return service.mNativeInterface.cancelDiscovery(); 2553 } 2554 2555 @Override isDiscovering(AttributionSource attributionSource)2556 public boolean isDiscovering(AttributionSource attributionSource) { 2557 AdapterService service = getService(); 2558 if (service == null 2559 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "isDiscovering") 2560 || !Utils.checkScanPermissionForDataDelivery( 2561 service, attributionSource, "AdapterService isDiscovering")) { 2562 return false; 2563 } 2564 2565 return service.mAdapterProperties.isDiscovering(); 2566 } 2567 2568 @Override getDiscoveryEndMillis(AttributionSource source)2569 public long getDiscoveryEndMillis(AttributionSource source) { 2570 AdapterService service = getService(); 2571 if (service == null 2572 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getDiscoveryEndMillis") 2573 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 2574 return -1; 2575 } 2576 2577 enforceBluetoothPrivilegedPermission(service); 2578 2579 return service.mAdapterProperties.discoveryEndMillis(); 2580 } 2581 2582 @Override getMostRecentlyConnectedDevices( AttributionSource attributionSource)2583 public List<BluetoothDevice> getMostRecentlyConnectedDevices( 2584 AttributionSource attributionSource) { 2585 // don't check caller, may be called from system UI 2586 AdapterService service = getService(); 2587 if (service == null 2588 || !Utils.checkConnectPermissionForDataDelivery( 2589 service, 2590 attributionSource, 2591 "AdapterService getMostRecentlyConnectedDevices")) { 2592 return Collections.emptyList(); 2593 } 2594 2595 enforceBluetoothPrivilegedPermission(service); 2596 2597 return service.mDatabaseManager.getMostRecentlyConnectedDevices(); 2598 } 2599 2600 @Override getBondedDevices(AttributionSource attributionSource)2601 public List<BluetoothDevice> getBondedDevices(AttributionSource attributionSource) { 2602 // don't check caller, may be called from system UI 2603 AdapterService service = getService(); 2604 if (service == null 2605 || !Utils.checkConnectPermissionForDataDelivery( 2606 service, attributionSource, "AdapterService getBondedDevices")) { 2607 return Collections.emptyList(); 2608 } 2609 2610 return Arrays.asList(service.getBondedDevices()); 2611 } 2612 2613 @Override getAdapterConnectionState()2614 public int getAdapterConnectionState() { 2615 // don't check caller, may be called from system UI 2616 AdapterService service = getService(); 2617 if (service == null) { 2618 return BluetoothAdapter.STATE_DISCONNECTED; 2619 } 2620 2621 return service.mAdapterProperties.getConnectionState(); 2622 } 2623 2624 /** 2625 * This method has an associated binder cache. The invalidation methods must be changed if 2626 * the logic behind this method changes. 2627 */ 2628 @Override getProfileConnectionState(int profile, AttributionSource source)2629 public int getProfileConnectionState(int profile, AttributionSource source) { 2630 AdapterService service = getService(); 2631 boolean checkConnect = false; 2632 final int callingUid = Binder.getCallingUid(); 2633 final long token = Binder.clearCallingIdentity(); 2634 try { 2635 checkConnect = CompatChanges.isChangeEnabled(ENFORCE_CONNECT, callingUid); 2636 } finally { 2637 Binder.restoreCallingIdentity(token); 2638 } 2639 if (service == null 2640 || !callerIsSystemOrActiveOrManagedUser( 2641 service, TAG, "getProfileConnectionState") 2642 || (checkConnect 2643 && !Utils.checkConnectPermissionForDataDelivery( 2644 service, source, "AdapterService getProfileConnectionState"))) { 2645 return BluetoothProfile.STATE_DISCONNECTED; 2646 } 2647 2648 return service.mAdapterProperties.getProfileConnectionState(profile); 2649 } 2650 2651 @Override createBond( BluetoothDevice device, int transport, OobData remoteP192Data, OobData remoteP256Data, AttributionSource attributionSource)2652 public boolean createBond( 2653 BluetoothDevice device, 2654 int transport, 2655 OobData remoteP192Data, 2656 OobData remoteP256Data, 2657 AttributionSource attributionSource) { 2658 AdapterService service = getService(); 2659 if (service == null 2660 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "createBond") 2661 || !Utils.checkConnectPermissionForDataDelivery( 2662 service, attributionSource, "AdapterService createBond")) { 2663 return false; 2664 } 2665 2666 // This conditional is required to satisfy permission dependencies 2667 // since createBond calls createBondOutOfBand with null value passed as data. 2668 // BluetoothDevice#createBond requires BLUETOOTH_ADMIN only. 2669 service.enforceBluetoothPrivilegedPermissionIfNeeded(remoteP192Data, remoteP256Data); 2670 2671 Log.i( 2672 TAG, 2673 "createBond: device=" 2674 + device 2675 + ", transport=" 2676 + transport 2677 + ", from " 2678 + Utils.getUidPidString()); 2679 return service.createBond( 2680 device, 2681 transport, 2682 remoteP192Data, 2683 remoteP256Data, 2684 attributionSource.getPackageName()); 2685 } 2686 2687 @Override cancelBondProcess( BluetoothDevice device, AttributionSource attributionSource)2688 public boolean cancelBondProcess( 2689 BluetoothDevice device, AttributionSource attributionSource) { 2690 AdapterService service = getService(); 2691 if (service == null 2692 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "cancelBondProcess") 2693 || !Utils.checkConnectPermissionForDataDelivery( 2694 service, attributionSource, "AdapterService cancelBondProcess")) { 2695 return false; 2696 } 2697 2698 enforceBluetoothPrivilegedPermission(service); 2699 2700 Log.i(TAG, "cancelBondProcess: device=" + device + ", from " + Utils.getUidPidString()); 2701 2702 DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device); 2703 if (deviceProp != null) { 2704 deviceProp.setBondingInitiatedLocally(false); 2705 } 2706 2707 return service.mNativeInterface.cancelBond(getBytesFromAddress(device.getAddress())); 2708 } 2709 2710 @Override removeBond(BluetoothDevice device, AttributionSource attributionSource)2711 public boolean removeBond(BluetoothDevice device, AttributionSource attributionSource) { 2712 AdapterService service = getService(); 2713 if (service == null 2714 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "removeBond") 2715 || !Utils.checkConnectPermissionForDataDelivery( 2716 service, attributionSource, "AdapterService removeBond")) { 2717 return false; 2718 } 2719 2720 Log.i(TAG, "removeBond: device=" + device + ", from " + Utils.getUidPidString()); 2721 2722 DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device); 2723 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDED) { 2724 Log.w( 2725 TAG, 2726 device.getAddressForLogging() 2727 + " cannot be removed since " 2728 + ((deviceProp == null) 2729 ? "properties are empty" 2730 : "bond state is " + deviceProp.getBondState())); 2731 return false; 2732 } 2733 service.mBondAttemptCallerInfo.remove(device.getAddress()); 2734 deviceProp.setBondingInitiatedLocally(false); 2735 2736 Message msg = service.mBondStateMachine.obtainMessage(BondStateMachine.REMOVE_BOND); 2737 msg.obj = device; 2738 service.mBondStateMachine.sendMessage(msg); 2739 return true; 2740 } 2741 2742 @Override getBondState(BluetoothDevice device, AttributionSource attributionSource)2743 public int getBondState(BluetoothDevice device, AttributionSource attributionSource) { 2744 // don't check caller, may be called from system UI 2745 AdapterService service = getService(); 2746 if (service == null 2747 || !Utils.checkConnectPermissionForDataDelivery( 2748 service, attributionSource, "AdapterService getBondState")) { 2749 return BluetoothDevice.BOND_NONE; 2750 } 2751 2752 return service.getBondState(device); 2753 } 2754 2755 @Override isBondingInitiatedLocally( BluetoothDevice device, AttributionSource attributionSource)2756 public boolean isBondingInitiatedLocally( 2757 BluetoothDevice device, AttributionSource attributionSource) { 2758 // don't check caller, may be called from system UI 2759 AdapterService service = getService(); 2760 if (service == null 2761 || !Utils.checkConnectPermissionForDataDelivery( 2762 service, 2763 attributionSource, 2764 "AdapterService isBondingInitiatedLocally")) { 2765 return false; 2766 } 2767 2768 DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device); 2769 return deviceProp != null && deviceProp.isBondingInitiatedLocally(); 2770 } 2771 2772 @Override generateLocalOobData( int transport, IBluetoothOobDataCallback callback, AttributionSource source)2773 public void generateLocalOobData( 2774 int transport, IBluetoothOobDataCallback callback, AttributionSource source) { 2775 AdapterService service = getService(); 2776 if (service == null 2777 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "generateLocalOobData") 2778 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 2779 return; 2780 } 2781 enforceBluetoothPrivilegedPermission(service); 2782 service.generateLocalOobData(transport, callback); 2783 } 2784 2785 @Override getSupportedProfiles(AttributionSource source)2786 public long getSupportedProfiles(AttributionSource source) { 2787 AdapterService service = getService(); 2788 if (service == null 2789 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 2790 return 0; 2791 } 2792 enforceBluetoothPrivilegedPermission(service); 2793 2794 return Config.getSupportedProfilesBitMask(); 2795 } 2796 2797 @Override getConnectionState(BluetoothDevice device, AttributionSource attributionSource)2798 public int getConnectionState(BluetoothDevice device, AttributionSource attributionSource) { 2799 AdapterService service = getService(); 2800 if (service == null 2801 || !Utils.checkConnectPermissionForDataDelivery( 2802 service, attributionSource, "AdapterService getConnectionState")) { 2803 return BluetoothDevice.CONNECTION_STATE_DISCONNECTED; 2804 } 2805 2806 return service.getConnectionState(device); 2807 } 2808 2809 @Override getConnectionHandle( BluetoothDevice device, int transport, AttributionSource attributionSource)2810 public int getConnectionHandle( 2811 BluetoothDevice device, int transport, AttributionSource attributionSource) { 2812 AdapterService service = getService(); 2813 if (service == null 2814 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getConnectionHandle") 2815 || !Utils.checkConnectPermissionForDataDelivery( 2816 service, attributionSource, TAG)) { 2817 return BluetoothDevice.ERROR; 2818 } 2819 2820 enforceBluetoothPrivilegedPermission(service); 2821 2822 return service.getConnectionHandle(device, transport); 2823 } 2824 2825 @Override canBondWithoutDialog(BluetoothDevice device, AttributionSource source)2826 public boolean canBondWithoutDialog(BluetoothDevice device, AttributionSource source) { 2827 AdapterService service = getService(); 2828 if (service == null 2829 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 2830 return false; 2831 } 2832 2833 enforceBluetoothPrivilegedPermission(service); 2834 2835 return service.canBondWithoutDialog(device); 2836 } 2837 2838 @Override getPackageNameOfBondingApplication(BluetoothDevice device)2839 public String getPackageNameOfBondingApplication(BluetoothDevice device) { 2840 AdapterService service = getService(); 2841 2842 if (service == null) { 2843 return null; 2844 } 2845 2846 enforceBluetoothPrivilegedPermission(service); 2847 2848 return service.getPackageNameOfBondingApplication(device); 2849 } 2850 2851 @Override removeActiveDevice(@ctiveDeviceUse int profiles, AttributionSource source)2852 public boolean removeActiveDevice(@ActiveDeviceUse int profiles, AttributionSource source) { 2853 AdapterService service = getService(); 2854 if (service == null 2855 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "removeActiveDevice") 2856 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 2857 return false; 2858 } 2859 Log.i( 2860 TAG, 2861 "removeActiveDevice: profiles=" 2862 + profiles 2863 + ", from " 2864 + Utils.getUidPidString()); 2865 return service.setActiveDevice(null, profiles); 2866 } 2867 2868 @Override setActiveDevice( BluetoothDevice device, @ActiveDeviceUse int profiles, AttributionSource source)2869 public boolean setActiveDevice( 2870 BluetoothDevice device, @ActiveDeviceUse int profiles, AttributionSource source) { 2871 AdapterService service = getService(); 2872 if (service == null 2873 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setActiveDevice") 2874 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 2875 return false; 2876 } 2877 2878 enforceBluetoothPrivilegedPermission(service); 2879 2880 Log.i( 2881 TAG, 2882 "setActiveDevice: device=" 2883 + device 2884 + ", profiles=" 2885 + profiles 2886 + ", from " 2887 + Utils.getUidPidString()); 2888 2889 return service.setActiveDevice(device, profiles); 2890 } 2891 2892 @Override getActiveDevices( @ctiveDeviceProfile int profile, AttributionSource source)2893 public List<BluetoothDevice> getActiveDevices( 2894 @ActiveDeviceProfile int profile, AttributionSource source) { 2895 AdapterService service = getService(); 2896 if (service == null 2897 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getActiveDevices") 2898 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 2899 return Collections.emptyList(); 2900 } 2901 2902 enforceBluetoothPrivilegedPermission(service); 2903 2904 return service.getActiveDevices(profile); 2905 } 2906 2907 @Override connectAllEnabledProfiles(BluetoothDevice device, AttributionSource source)2908 public int connectAllEnabledProfiles(BluetoothDevice device, AttributionSource source) { 2909 AdapterService service = getService(); 2910 if (service == null) { 2911 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; 2912 } 2913 if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "connectAllEnabledProfiles")) { 2914 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; 2915 } 2916 if (device == null) { 2917 throw new IllegalArgumentException("device cannot be null"); 2918 } 2919 if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { 2920 throw new IllegalArgumentException("device cannot have an invalid address"); 2921 } 2922 if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 2923 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; 2924 } 2925 2926 enforceBluetoothPrivilegedPermission(service); 2927 2928 Log.i( 2929 TAG, 2930 "connectAllEnabledProfiles: device=" 2931 + device 2932 + ", from " 2933 + Utils.getUidPidString()); 2934 2935 try { 2936 return service.connectAllEnabledProfiles(device); 2937 } catch (Exception e) { 2938 Log.v(TAG, "connectAllEnabledProfiles() failed", e); 2939 SneakyThrow.sneakyThrow(e); 2940 throw new RuntimeException(e); 2941 } 2942 } 2943 2944 @Override disconnectAllEnabledProfiles(BluetoothDevice device, AttributionSource source)2945 public int disconnectAllEnabledProfiles(BluetoothDevice device, AttributionSource source) { 2946 AdapterService service = getService(); 2947 if (service == null) { 2948 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; 2949 } 2950 if (!callerIsSystemOrActiveOrManagedUser( 2951 service, TAG, "disconnectAllEnabledProfiles")) { 2952 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; 2953 } 2954 if (device == null) { 2955 throw new IllegalArgumentException("device cannot be null"); 2956 } 2957 if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { 2958 throw new IllegalArgumentException("device cannot have an invalid address"); 2959 } 2960 if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 2961 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; 2962 } 2963 2964 enforceBluetoothPrivilegedPermission(service); 2965 2966 Log.i( 2967 TAG, 2968 "disconnectAllEnabledProfiles: device=" 2969 + device 2970 + ", from " 2971 + Utils.getUidPidString()); 2972 2973 try { 2974 return service.disconnectAllEnabledProfiles(device); 2975 } catch (Exception e) { 2976 Log.v(TAG, "disconnectAllEnabledProfiles() failed", e); 2977 SneakyThrow.sneakyThrow(e); 2978 throw new RuntimeException(e); 2979 } 2980 } 2981 2982 @Override getRemoteName(BluetoothDevice device, AttributionSource attributionSource)2983 public String getRemoteName(BluetoothDevice device, AttributionSource attributionSource) { 2984 AdapterService service = getService(); 2985 if (service == null 2986 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getRemoteName") 2987 || !Utils.checkConnectPermissionForDataDelivery( 2988 service, attributionSource, "AdapterService getRemoteName")) { 2989 return null; 2990 } 2991 2992 return service.getRemoteName(device); 2993 } 2994 2995 @Override getRemoteType(BluetoothDevice device, AttributionSource attributionSource)2996 public int getRemoteType(BluetoothDevice device, AttributionSource attributionSource) { 2997 AdapterService service = getService(); 2998 if (service == null 2999 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getRemoteType") 3000 || !Utils.checkConnectPermissionForDataDelivery( 3001 service, attributionSource, "AdapterService getRemoteType")) { 3002 return BluetoothDevice.DEVICE_TYPE_UNKNOWN; 3003 } 3004 3005 return service.getRemoteType(device); 3006 } 3007 3008 @Override getRemoteAlias(BluetoothDevice device, AttributionSource attributionSource)3009 public String getRemoteAlias(BluetoothDevice device, AttributionSource attributionSource) { 3010 AdapterService service = getService(); 3011 if (service == null 3012 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getRemoteAlias") 3013 || !Utils.checkConnectPermissionForDataDelivery( 3014 service, attributionSource, "AdapterService getRemoteAlias")) { 3015 return null; 3016 } 3017 3018 DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device); 3019 return deviceProp != null ? deviceProp.getAlias() : null; 3020 } 3021 3022 @Override setRemoteAlias( BluetoothDevice device, String name, AttributionSource attributionSource)3023 public int setRemoteAlias( 3024 BluetoothDevice device, String name, AttributionSource attributionSource) { 3025 AdapterService service = getService(); 3026 if (service == null) { 3027 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; 3028 } 3029 if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "setRemoteAlias")) { 3030 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; 3031 } 3032 if (name != null && name.isEmpty()) { 3033 throw new IllegalArgumentException("alias cannot be the empty string"); 3034 } 3035 3036 if (!hasBluetoothPrivilegedPermission(service)) { 3037 if (!Utils.checkConnectPermissionForDataDelivery( 3038 service, attributionSource, "AdapterService setRemoteAlias")) { 3039 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; 3040 } 3041 enforceCdmAssociation( 3042 service.mCompanionDeviceManager, 3043 service, 3044 attributionSource.getPackageName(), 3045 Binder.getCallingUid(), 3046 device); 3047 } 3048 3049 DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device); 3050 if (deviceProp == null) { 3051 return BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED; 3052 } 3053 deviceProp.setAlias(device, name); 3054 return BluetoothStatusCodes.SUCCESS; 3055 } 3056 3057 @Override getRemoteClass(BluetoothDevice device, AttributionSource attributionSource)3058 public int getRemoteClass(BluetoothDevice device, AttributionSource attributionSource) { 3059 AdapterService service = getService(); 3060 if (service == null 3061 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getRemoteClass") 3062 || !Utils.checkConnectPermissionForDataDelivery( 3063 service, attributionSource, "AdapterService getRemoteClass")) { 3064 return 0; 3065 } 3066 3067 DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device); 3068 return deviceProp != null ? deviceProp.getBluetoothClass() : 0; 3069 } 3070 3071 @Override getRemoteUuids( BluetoothDevice device, AttributionSource attributionSource)3072 public List<ParcelUuid> getRemoteUuids( 3073 BluetoothDevice device, AttributionSource attributionSource) { 3074 AdapterService service = getService(); 3075 if (service == null 3076 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getRemoteUuids") 3077 || !Utils.checkConnectPermissionForDataDelivery( 3078 service, attributionSource, "AdapterService getRemoteUuids")) { 3079 return Collections.emptyList(); 3080 } 3081 3082 ParcelUuid[] parcels = service.getRemoteUuids(device); 3083 if (parcels == null) { 3084 return null; 3085 } 3086 return Arrays.asList(parcels); 3087 } 3088 3089 @Override fetchRemoteUuids( BluetoothDevice device, int transport, AttributionSource attributionSource)3090 public boolean fetchRemoteUuids( 3091 BluetoothDevice device, int transport, AttributionSource attributionSource) { 3092 AdapterService service = getService(); 3093 if (service == null 3094 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "fetchRemoteUuids") 3095 || !Utils.checkConnectPermissionForDataDelivery( 3096 service, attributionSource, "AdapterService fetchRemoteUuids")) { 3097 return false; 3098 } 3099 if (transport != TRANSPORT_AUTO) { 3100 enforceBluetoothPrivilegedPermission(service); 3101 } 3102 3103 Log.i( 3104 TAG, 3105 "fetchRemoteUuids: device=" 3106 + device 3107 + ", transport=" 3108 + transport 3109 + ", from " 3110 + Utils.getUidPidString()); 3111 3112 service.mRemoteDevices.fetchUuids(device, transport); 3113 MetricsLogger.getInstance().cacheCount(BluetoothProtoEnums.SDP_FETCH_UUID_REQUEST, 1); 3114 return true; 3115 } 3116 3117 @Override setPin( BluetoothDevice device, boolean accept, int len, byte[] pinCode, AttributionSource attributionSource)3118 public boolean setPin( 3119 BluetoothDevice device, 3120 boolean accept, 3121 int len, 3122 byte[] pinCode, 3123 AttributionSource attributionSource) { 3124 AdapterService service = getService(); 3125 if (service == null 3126 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setPin") 3127 || !Utils.checkConnectPermissionForDataDelivery( 3128 service, attributionSource, "AdapterService setPin")) { 3129 return false; 3130 } 3131 3132 DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device); 3133 // Only allow setting a pin in bonding state, or bonded state in case of security 3134 // upgrade. 3135 if (deviceProp == null || !deviceProp.isBondingOrBonded()) { 3136 Log.e(TAG, "setPin: device=" + device + ", not bonding"); 3137 return false; 3138 } 3139 if (pinCode.length != len) { 3140 android.util.EventLog.writeEvent( 3141 0x534e4554, "139287605", -1, "PIN code length mismatch"); 3142 return false; 3143 } 3144 service.logUserBondResponse( 3145 device, accept, BluetoothProtoEnums.BOND_SUB_STATE_LOCAL_PIN_REPLIED); 3146 Log.i( 3147 TAG, 3148 "setPin: device=" 3149 + device 3150 + ", accept=" 3151 + accept 3152 + ", from " 3153 + Utils.getUidPidString()); 3154 return service.mNativeInterface.pinReply( 3155 getBytesFromAddress(device.getAddress()), accept, len, pinCode); 3156 } 3157 3158 @Override setPasskey( BluetoothDevice device, boolean accept, int len, byte[] passkey, AttributionSource attributionSource)3159 public boolean setPasskey( 3160 BluetoothDevice device, 3161 boolean accept, 3162 int len, 3163 byte[] passkey, 3164 AttributionSource attributionSource) { 3165 AdapterService service = getService(); 3166 if (service == null 3167 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setPasskey") 3168 || !Utils.checkConnectPermissionForDataDelivery( 3169 service, attributionSource, "AdapterService setPasskey")) { 3170 return false; 3171 } 3172 3173 DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device); 3174 if (deviceProp == null || !deviceProp.isBonding()) { 3175 Log.e(TAG, "setPasskey: device=" + device + ", not bonding"); 3176 return false; 3177 } 3178 if (passkey.length != len) { 3179 android.util.EventLog.writeEvent( 3180 0x534e4554, "139287605", -1, "Passkey length mismatch"); 3181 return false; 3182 } 3183 service.logUserBondResponse( 3184 device, accept, BluetoothProtoEnums.BOND_SUB_STATE_LOCAL_SSP_REPLIED); 3185 Log.i( 3186 TAG, 3187 "setPasskey: device=" 3188 + device 3189 + ", accept=" 3190 + accept 3191 + ", from " 3192 + Utils.getUidPidString()); 3193 3194 return service.mNativeInterface.sspReply( 3195 getBytesFromAddress(device.getAddress()), 3196 AbstractionLayer.BT_SSP_VARIANT_PASSKEY_ENTRY, 3197 accept, 3198 Utils.byteArrayToInt(passkey)); 3199 } 3200 3201 @Override setPairingConfirmation( BluetoothDevice device, boolean accept, AttributionSource source)3202 public boolean setPairingConfirmation( 3203 BluetoothDevice device, boolean accept, AttributionSource source) { 3204 AdapterService service = getService(); 3205 if (service == null 3206 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setPairingConfirmation") 3207 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3208 return false; 3209 } 3210 3211 enforceBluetoothPrivilegedPermission(service); 3212 3213 DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device); 3214 if (deviceProp == null || !deviceProp.isBonding()) { 3215 Log.e(TAG, "setPairingConfirmation: device=" + device + ", not bonding"); 3216 return false; 3217 } 3218 service.logUserBondResponse( 3219 device, accept, BluetoothProtoEnums.BOND_SUB_STATE_LOCAL_SSP_REPLIED); 3220 Log.i( 3221 TAG, 3222 "setPairingConfirmation: device=" 3223 + device 3224 + ", accept=" 3225 + accept 3226 + ", from " 3227 + Utils.getUidPidString()); 3228 3229 return service.mNativeInterface.sspReply( 3230 getBytesFromAddress(device.getAddress()), 3231 AbstractionLayer.BT_SSP_VARIANT_PASSKEY_CONFIRMATION, 3232 accept, 3233 0); 3234 } 3235 3236 @Override getSilenceMode(BluetoothDevice device, AttributionSource source)3237 public boolean getSilenceMode(BluetoothDevice device, AttributionSource source) { 3238 AdapterService service = getService(); 3239 if (service == null 3240 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getSilenceMode") 3241 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3242 return false; 3243 } 3244 3245 enforceBluetoothPrivilegedPermission(service); 3246 3247 return service.mSilenceDeviceManager.getSilenceMode(device); 3248 } 3249 3250 @Override setSilenceMode( BluetoothDevice device, boolean silence, AttributionSource source)3251 public boolean setSilenceMode( 3252 BluetoothDevice device, boolean silence, AttributionSource source) { 3253 AdapterService service = getService(); 3254 if (service == null 3255 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setSilenceMode") 3256 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3257 return false; 3258 } 3259 3260 enforceBluetoothPrivilegedPermission(service); 3261 3262 service.mSilenceDeviceManager.setSilenceMode(device, silence); 3263 return true; 3264 } 3265 3266 @Override getPhonebookAccessPermission( BluetoothDevice device, AttributionSource attributionSource)3267 public int getPhonebookAccessPermission( 3268 BluetoothDevice device, AttributionSource attributionSource) { 3269 AdapterService service = getService(); 3270 if (service == null 3271 || !callerIsSystemOrActiveOrManagedUser( 3272 service, TAG, "getPhonebookAccessPermission") 3273 || !Utils.checkConnectPermissionForDataDelivery( 3274 service, 3275 attributionSource, 3276 "AdapterService getPhonebookAccessPermission")) { 3277 return BluetoothDevice.ACCESS_UNKNOWN; 3278 } 3279 3280 return service.getDeviceAccessFromPrefs( 3281 device, PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE); 3282 } 3283 3284 @Override setPhonebookAccessPermission( BluetoothDevice device, int value, AttributionSource source)3285 public boolean setPhonebookAccessPermission( 3286 BluetoothDevice device, int value, AttributionSource source) { 3287 AdapterService service = getService(); 3288 if (service == null 3289 || !callerIsSystemOrActiveOrManagedUser( 3290 service, TAG, "setPhonebookAccessPermission") 3291 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3292 return false; 3293 } 3294 3295 enforceBluetoothPrivilegedPermission(service); 3296 3297 service.setPhonebookAccessPermission(device, value); 3298 return true; 3299 } 3300 3301 @Override getMessageAccessPermission( BluetoothDevice device, AttributionSource attributionSource)3302 public int getMessageAccessPermission( 3303 BluetoothDevice device, AttributionSource attributionSource) { 3304 AdapterService service = getService(); 3305 if (service == null 3306 || !callerIsSystemOrActiveOrManagedUser( 3307 service, TAG, "getMessageAccessPermission") 3308 || !Utils.checkConnectPermissionForDataDelivery( 3309 service, 3310 attributionSource, 3311 "AdapterService getMessageAccessPermission")) { 3312 return BluetoothDevice.ACCESS_UNKNOWN; 3313 } 3314 3315 return service.getDeviceAccessFromPrefs( 3316 device, MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE); 3317 } 3318 3319 @Override setMessageAccessPermission( BluetoothDevice device, int value, AttributionSource source)3320 public boolean setMessageAccessPermission( 3321 BluetoothDevice device, int value, AttributionSource source) { 3322 AdapterService service = getService(); 3323 if (service == null 3324 || !callerIsSystemOrActiveOrManagedUser( 3325 service, TAG, "setMessageAccessPermission") 3326 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3327 return false; 3328 } 3329 3330 enforceBluetoothPrivilegedPermission(service); 3331 3332 service.setMessageAccessPermission(device, value); 3333 return true; 3334 } 3335 3336 @Override getSimAccessPermission( BluetoothDevice device, AttributionSource attributionSource)3337 public int getSimAccessPermission( 3338 BluetoothDevice device, AttributionSource attributionSource) { 3339 AdapterService service = getService(); 3340 if (service == null 3341 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getSimAccessPermission") 3342 || !Utils.checkConnectPermissionForDataDelivery( 3343 service, attributionSource, "AdapterService getSimAccessPermission")) { 3344 return BluetoothDevice.ACCESS_UNKNOWN; 3345 } 3346 3347 return service.getDeviceAccessFromPrefs(device, SIM_ACCESS_PERMISSION_PREFERENCE_FILE); 3348 } 3349 3350 @Override setSimAccessPermission( BluetoothDevice device, int value, AttributionSource source)3351 public boolean setSimAccessPermission( 3352 BluetoothDevice device, int value, AttributionSource source) { 3353 AdapterService service = getService(); 3354 if (service == null 3355 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setSimAccessPermission") 3356 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3357 return false; 3358 } 3359 3360 enforceBluetoothPrivilegedPermission(service); 3361 3362 service.setSimAccessPermission(device, value); 3363 return true; 3364 } 3365 3366 @Override logL2capcocServerConnection( BluetoothDevice device, int port, boolean isSecured, int result, long socketCreationTimeMillis, long socketCreationLatencyMillis, long socketConnectionTimeMillis, long timeoutMillis)3367 public void logL2capcocServerConnection( 3368 BluetoothDevice device, 3369 int port, 3370 boolean isSecured, 3371 int result, 3372 long socketCreationTimeMillis, 3373 long socketCreationLatencyMillis, 3374 long socketConnectionTimeMillis, 3375 long timeoutMillis) { 3376 AdapterService service = getService(); 3377 if (service == null) { 3378 return; 3379 } 3380 service.logL2capcocServerConnection( 3381 device, 3382 port, 3383 isSecured, 3384 result, 3385 socketCreationTimeMillis, 3386 socketCreationLatencyMillis, 3387 socketConnectionTimeMillis, 3388 timeoutMillis, 3389 Binder.getCallingUid()); 3390 } 3391 3392 @Override getSocketManager()3393 public IBluetoothSocketManager getSocketManager() { 3394 AdapterService service = getService(); 3395 if (service == null) { 3396 return null; 3397 } 3398 3399 return IBluetoothSocketManager.Stub.asInterface(service.mBluetoothSocketManagerBinder); 3400 } 3401 3402 @Override logL2capcocClientConnection( BluetoothDevice device, int port, boolean isSecured, int result, long socketCreationTimeNanos, long socketCreationLatencyNanos, long socketConnectionTimeNanos)3403 public void logL2capcocClientConnection( 3404 BluetoothDevice device, 3405 int port, 3406 boolean isSecured, 3407 int result, 3408 long socketCreationTimeNanos, 3409 long socketCreationLatencyNanos, 3410 long socketConnectionTimeNanos) { 3411 AdapterService service = getService(); 3412 if (service == null) { 3413 return; 3414 } 3415 service.logL2capcocClientConnection( 3416 device, 3417 port, 3418 isSecured, 3419 result, 3420 socketCreationTimeNanos, 3421 socketCreationLatencyNanos, 3422 socketConnectionTimeNanos, 3423 Binder.getCallingUid()); 3424 } 3425 3426 @Override logRfcommConnectionAttempt( BluetoothDevice device, boolean isSecured, int resultCode, long socketCreationTimeNanos, boolean isSerialPort)3427 public void logRfcommConnectionAttempt( 3428 BluetoothDevice device, 3429 boolean isSecured, 3430 int resultCode, 3431 long socketCreationTimeNanos, 3432 boolean isSerialPort) { 3433 AdapterService service = getService(); 3434 if (service == null) { 3435 return; 3436 } 3437 service.logRfcommConnectionAttempt( 3438 device, 3439 isSecured, 3440 resultCode, 3441 socketCreationTimeNanos, 3442 isSerialPort, 3443 Binder.getCallingUid()); 3444 } 3445 3446 @Override sdpSearch( BluetoothDevice device, ParcelUuid uuid, AttributionSource attributionSource)3447 public boolean sdpSearch( 3448 BluetoothDevice device, ParcelUuid uuid, AttributionSource attributionSource) { 3449 AdapterService service = getService(); 3450 if (service == null 3451 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "sdpSearch") 3452 || !Utils.checkConnectPermissionForDataDelivery( 3453 service, attributionSource, "AdapterService sdpSearch")) { 3454 return false; 3455 } 3456 3457 if (service.mSdpManager == null) { 3458 return false; 3459 } 3460 service.mSdpManager.sdpSearch(device, uuid); 3461 return true; 3462 } 3463 3464 @Override getBatteryLevel(BluetoothDevice device, AttributionSource attributionSource)3465 public int getBatteryLevel(BluetoothDevice device, AttributionSource attributionSource) { 3466 AdapterService service = getService(); 3467 if (service == null 3468 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getBatteryLevel") 3469 || !Utils.checkConnectPermissionForDataDelivery( 3470 service, attributionSource, "AdapterService getBatteryLevel")) { 3471 return BluetoothDevice.BATTERY_LEVEL_UNKNOWN; 3472 } 3473 3474 DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device); 3475 if (deviceProp == null) { 3476 return BluetoothDevice.BATTERY_LEVEL_UNKNOWN; 3477 } 3478 return deviceProp.getBatteryLevel(); 3479 } 3480 3481 @Override getMaxConnectedAudioDevices(AttributionSource attributionSource)3482 public int getMaxConnectedAudioDevices(AttributionSource attributionSource) { 3483 // don't check caller, may be called from system UI 3484 AdapterService service = getService(); 3485 if (service == null 3486 || !Utils.checkConnectPermissionForDataDelivery( 3487 service, 3488 attributionSource, 3489 "AdapterService getMaxConnectedAudioDevices")) { 3490 return -1; 3491 } 3492 3493 return service.getMaxConnectedAudioDevices(); 3494 } 3495 3496 @Override factoryReset(AttributionSource source)3497 public boolean factoryReset(AttributionSource source) { 3498 AdapterService service = getService(); 3499 if (service == null 3500 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3501 return false; 3502 } 3503 3504 enforceBluetoothPrivilegedPermission(service); 3505 return service.factoryReset(); 3506 } 3507 3508 @Override registerBluetoothConnectionCallback( IBluetoothConnectionCallback callback, AttributionSource source)3509 public void registerBluetoothConnectionCallback( 3510 IBluetoothConnectionCallback callback, AttributionSource source) { 3511 AdapterService service = getService(); 3512 if (service == null 3513 || !callerIsSystemOrActiveOrManagedUser( 3514 service, TAG, "registerBluetoothConnectionCallback") 3515 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3516 return; 3517 } 3518 enforceBluetoothPrivilegedPermission(service); 3519 service.mBluetoothConnectionCallbacks.add(callback); 3520 } 3521 3522 @Override unregisterBluetoothConnectionCallback( IBluetoothConnectionCallback callback, AttributionSource source)3523 public void unregisterBluetoothConnectionCallback( 3524 IBluetoothConnectionCallback callback, AttributionSource source) { 3525 AdapterService service = getService(); 3526 if (service == null 3527 || !callerIsSystemOrActiveOrManagedUser( 3528 service, TAG, "unregisterBluetoothConnectionCallback") 3529 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3530 return; 3531 } 3532 enforceBluetoothPrivilegedPermission(service); 3533 service.mBluetoothConnectionCallbacks.remove(callback); 3534 } 3535 3536 @Override registerCallback(IBluetoothCallback callback, AttributionSource source)3537 public void registerCallback(IBluetoothCallback callback, AttributionSource source) { 3538 AdapterService service = getService(); 3539 if (service == null 3540 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "registerCallback") 3541 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3542 return; 3543 } 3544 3545 enforceBluetoothPrivilegedPermission(service); 3546 3547 service.registerRemoteCallback(callback); 3548 } 3549 3550 @Override unregisterCallback(IBluetoothCallback callback, AttributionSource source)3551 public void unregisterCallback(IBluetoothCallback callback, AttributionSource source) { 3552 AdapterService service = getService(); 3553 if (service == null 3554 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "unregisterCallback") 3555 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3556 return; 3557 } 3558 3559 enforceBluetoothPrivilegedPermission(service); 3560 3561 service.unregisterRemoteCallback(callback); 3562 } 3563 3564 @Override isMultiAdvertisementSupported()3565 public boolean isMultiAdvertisementSupported() { 3566 AdapterService service = getService(); 3567 if (service == null) { 3568 return false; 3569 } 3570 3571 int val = service.mAdapterProperties.getNumOfAdvertisementInstancesSupported(); 3572 return val >= MIN_ADVT_INSTANCES_FOR_MA; 3573 } 3574 3575 /** 3576 * This method has an associated binder cache. The invalidation methods must be changed if 3577 * the logic behind this method changes. 3578 */ 3579 @Override isOffloadedFilteringSupported()3580 public boolean isOffloadedFilteringSupported() { 3581 AdapterService service = getService(); 3582 if (service == null) { 3583 return false; 3584 } 3585 3586 int val = service.getNumOfOffloadedScanFilterSupported(); 3587 return val >= MIN_OFFLOADED_FILTERS; 3588 } 3589 3590 @Override isOffloadedScanBatchingSupported()3591 public boolean isOffloadedScanBatchingSupported() { 3592 AdapterService service = getService(); 3593 if (service == null) { 3594 return false; 3595 } 3596 3597 int val = service.getOffloadedScanResultStorage(); 3598 return val >= MIN_OFFLOADED_SCAN_STORAGE_BYTES; 3599 } 3600 3601 @Override isLe2MPhySupported()3602 public boolean isLe2MPhySupported() { 3603 AdapterService service = getService(); 3604 if (service == null) { 3605 return false; 3606 } 3607 3608 return service.isLe2MPhySupported(); 3609 } 3610 3611 @Override isLeCodedPhySupported()3612 public boolean isLeCodedPhySupported() { 3613 AdapterService service = getService(); 3614 if (service == null) { 3615 return false; 3616 } 3617 3618 return service.isLeCodedPhySupported(); 3619 } 3620 3621 @Override isLeExtendedAdvertisingSupported()3622 public boolean isLeExtendedAdvertisingSupported() { 3623 AdapterService service = getService(); 3624 if (service == null) { 3625 return false; 3626 } 3627 3628 return service.isLeExtendedAdvertisingSupported(); 3629 } 3630 3631 @Override isLePeriodicAdvertisingSupported()3632 public boolean isLePeriodicAdvertisingSupported() { 3633 AdapterService service = getService(); 3634 if (service == null) { 3635 return false; 3636 } 3637 3638 return service.isLePeriodicAdvertisingSupported(); 3639 } 3640 3641 @Override isLeAudioSupported()3642 public int isLeAudioSupported() { 3643 AdapterService service = getService(); 3644 if (service == null) { 3645 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; 3646 } 3647 3648 Set<Integer> supportedProfileServices = 3649 Arrays.stream(Config.getSupportedProfiles()) 3650 .boxed() 3651 .collect(Collectors.toSet()); 3652 int[] leAudioUnicastProfiles = Config.getLeAudioUnicastProfiles(); 3653 3654 if (Arrays.stream(leAudioUnicastProfiles) 3655 .allMatch(supportedProfileServices::contains)) { 3656 return BluetoothStatusCodes.FEATURE_SUPPORTED; 3657 } 3658 3659 return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED; 3660 } 3661 3662 @Override isLeAudioBroadcastSourceSupported()3663 public int isLeAudioBroadcastSourceSupported() { 3664 AdapterService service = getService(); 3665 if (service == null) { 3666 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; 3667 } 3668 3669 long supportBitMask = Config.getSupportedProfilesBitMask(); 3670 if ((supportBitMask & (1 << BluetoothProfile.LE_AUDIO_BROADCAST)) != 0) { 3671 return BluetoothStatusCodes.FEATURE_SUPPORTED; 3672 } 3673 3674 return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED; 3675 } 3676 3677 @Override isLeAudioBroadcastAssistantSupported()3678 public int isLeAudioBroadcastAssistantSupported() { 3679 AdapterService service = getService(); 3680 if (service == null) { 3681 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; 3682 } 3683 3684 int[] supportedProfileServices = Config.getSupportedProfiles(); 3685 3686 if (Arrays.stream(supportedProfileServices) 3687 .anyMatch( 3688 profileId -> 3689 profileId == BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT)) { 3690 return BluetoothStatusCodes.FEATURE_SUPPORTED; 3691 } 3692 3693 return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED; 3694 } 3695 3696 @Override isDistanceMeasurementSupported(AttributionSource source)3697 public int isDistanceMeasurementSupported(AttributionSource source) { 3698 AdapterService service = getService(); 3699 if (service == null) { 3700 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; 3701 } else if (!callerIsSystemOrActiveOrManagedUser( 3702 service, TAG, "isDistanceMeasurementSupported")) { 3703 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; 3704 } else if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3705 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; 3706 } 3707 enforceBluetoothPrivilegedPermission(service); 3708 return BluetoothStatusCodes.FEATURE_SUPPORTED; 3709 } 3710 3711 @Override getLeMaximumAdvertisingDataLength()3712 public int getLeMaximumAdvertisingDataLength() { 3713 AdapterService service = getService(); 3714 if (service == null) { 3715 return 0; 3716 } 3717 3718 return service.getLeMaximumAdvertisingDataLength(); 3719 } 3720 3721 @Override isActivityAndEnergyReportingSupported()3722 public boolean isActivityAndEnergyReportingSupported() { 3723 AdapterService service = getService(); 3724 if (service == null) { 3725 return false; 3726 } 3727 3728 return service.mAdapterProperties.isActivityAndEnergyReportingSupported(); 3729 } 3730 3731 @Override reportActivityInfo(AttributionSource source)3732 public BluetoothActivityEnergyInfo reportActivityInfo(AttributionSource source) { 3733 AdapterService service = getService(); 3734 if (service == null 3735 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3736 return null; 3737 } 3738 3739 enforceBluetoothPrivilegedPermission(service); 3740 3741 return service.reportActivityInfo(); 3742 } 3743 3744 @Override registerMetadataListener( IBluetoothMetadataListener listener, BluetoothDevice device, AttributionSource source)3745 public boolean registerMetadataListener( 3746 IBluetoothMetadataListener listener, 3747 BluetoothDevice device, 3748 AttributionSource source) { 3749 AdapterService service = getService(); 3750 if (service == null 3751 || !callerIsSystemOrActiveOrManagedUser( 3752 service, TAG, "registerMetadataListener") 3753 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3754 return false; 3755 } 3756 3757 enforceBluetoothPrivilegedPermission(service); 3758 3759 List<IBluetoothMetadataListener> list = service.mMetadataListeners.get(device); 3760 if (list == null) { 3761 list = new ArrayList<>(); 3762 } else if (list.contains(listener)) { 3763 // The device is already registered with this listener 3764 return true; 3765 } 3766 list.add(listener); 3767 service.mMetadataListeners.put(device, list); 3768 return true; 3769 } 3770 3771 @Override unregisterMetadataListener( BluetoothDevice device, AttributionSource source)3772 public boolean unregisterMetadataListener( 3773 BluetoothDevice device, AttributionSource source) { 3774 AdapterService service = getService(); 3775 if (service == null 3776 || !callerIsSystemOrActiveOrManagedUser( 3777 service, TAG, "unregisterMetadataListener") 3778 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3779 return false; 3780 } 3781 3782 enforceBluetoothPrivilegedPermission(service); 3783 3784 service.mMetadataListeners.remove(device); 3785 return true; 3786 } 3787 3788 @Override setMetadata( BluetoothDevice device, int key, byte[] value, AttributionSource source)3789 public boolean setMetadata( 3790 BluetoothDevice device, int key, byte[] value, AttributionSource source) { 3791 AdapterService service = getService(); 3792 if (service == null 3793 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setMetadata") 3794 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3795 return false; 3796 } 3797 3798 enforceBluetoothPrivilegedPermission(service); 3799 3800 if (value.length > BluetoothDevice.METADATA_MAX_LENGTH) { 3801 return false; 3802 } 3803 return service.mDatabaseManager.setCustomMeta(device, key, value); 3804 } 3805 3806 @Override getMetadata(BluetoothDevice device, int key, AttributionSource source)3807 public byte[] getMetadata(BluetoothDevice device, int key, AttributionSource source) { 3808 AdapterService service = getService(); 3809 if (service == null 3810 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getMetadata") 3811 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3812 return null; 3813 } 3814 3815 enforceBluetoothPrivilegedPermission(service); 3816 3817 return service.mDatabaseManager.getCustomMeta(device, key); 3818 } 3819 3820 @Override isRequestAudioPolicyAsSinkSupported( BluetoothDevice device, AttributionSource source)3821 public int isRequestAudioPolicyAsSinkSupported( 3822 BluetoothDevice device, AttributionSource source) { 3823 AdapterService service = getService(); 3824 if (service == null 3825 || !callerIsSystemOrActiveOrManagedUser( 3826 service, TAG, "isRequestAudioPolicyAsSinkSupported") 3827 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3828 return BluetoothStatusCodes.FEATURE_NOT_CONFIGURED; 3829 } 3830 enforceBluetoothPrivilegedPermission(service); 3831 return service.isRequestAudioPolicyAsSinkSupported(device); 3832 } 3833 3834 @Override requestAudioPolicyAsSink( BluetoothDevice device, BluetoothSinkAudioPolicy policies, AttributionSource source)3835 public int requestAudioPolicyAsSink( 3836 BluetoothDevice device, 3837 BluetoothSinkAudioPolicy policies, 3838 AttributionSource source) { 3839 AdapterService service = getService(); 3840 if (service == null) { 3841 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; 3842 } else if (!callerIsSystemOrActiveOrManagedUser( 3843 service, TAG, "requestAudioPolicyAsSink")) { 3844 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; 3845 } else if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3846 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; 3847 } 3848 enforceBluetoothPrivilegedPermission(service); 3849 return service.requestAudioPolicyAsSink(device, policies); 3850 } 3851 3852 @Override getRequestedAudioPolicyAsSink( BluetoothDevice device, AttributionSource source)3853 public BluetoothSinkAudioPolicy getRequestedAudioPolicyAsSink( 3854 BluetoothDevice device, AttributionSource source) { 3855 AdapterService service = getService(); 3856 if (service == null 3857 || !callerIsSystemOrActiveOrManagedUser( 3858 service, TAG, "getRequestedAudioPolicyAsSink") 3859 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3860 return null; 3861 } 3862 enforceBluetoothPrivilegedPermission(service); 3863 return service.getRequestedAudioPolicyAsSink(device); 3864 } 3865 3866 @Override requestActivityInfo( IBluetoothActivityEnergyInfoListener listener, AttributionSource source)3867 public void requestActivityInfo( 3868 IBluetoothActivityEnergyInfoListener listener, AttributionSource source) { 3869 BluetoothActivityEnergyInfo info = reportActivityInfo(source); 3870 try { 3871 listener.onBluetoothActivityEnergyInfoAvailable(info); 3872 } catch (RemoteException e) { 3873 Log.e(TAG, "onBluetoothActivityEnergyInfo: RemoteException", e); 3874 } 3875 } 3876 3877 @Override startBrEdr(AttributionSource source)3878 public void startBrEdr(AttributionSource source) { 3879 AdapterService service = getService(); 3880 if (service == null 3881 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "startBrEdr") 3882 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3883 return; 3884 } 3885 3886 enforceBluetoothPrivilegedPermission(service); 3887 3888 service.startBrEdr(); 3889 } 3890 3891 @Override stopBle(AttributionSource source)3892 public void stopBle(AttributionSource source) { 3893 AdapterService service = getService(); 3894 if (service == null 3895 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "stopBle") 3896 || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 3897 return; 3898 } 3899 3900 enforceBluetoothPrivilegedPermission(service); 3901 3902 service.stopBle(); 3903 } 3904 3905 @Override dump(FileDescriptor fd, String[] args)3906 public void dump(FileDescriptor fd, String[] args) { 3907 PrintWriter writer = new PrintWriter(new FileOutputStream(fd)); 3908 AdapterService service = getService(); 3909 if (service == null) { 3910 return; 3911 } 3912 3913 enforceDumpPermission(service); 3914 3915 service.dump(fd, writer, args); 3916 writer.close(); 3917 } 3918 3919 @Override allowLowLatencyAudio(boolean allowed, BluetoothDevice device)3920 public boolean allowLowLatencyAudio(boolean allowed, BluetoothDevice device) { 3921 AdapterService service = getService(); 3922 if (service == null 3923 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "allowLowLatencyAudio") 3924 || !Utils.checkConnectPermissionForDataDelivery( 3925 service, 3926 Utils.getCallingAttributionSource(service), 3927 "AdapterService allowLowLatencyAudio")) { 3928 return false; 3929 } 3930 enforceBluetoothPrivilegedPermission(service); 3931 return service.allowLowLatencyAudio(allowed, device); 3932 } 3933 3934 @Override startRfcommListener( String name, ParcelUuid uuid, PendingIntent pendingIntent, AttributionSource attributionSource)3935 public int startRfcommListener( 3936 String name, 3937 ParcelUuid uuid, 3938 PendingIntent pendingIntent, 3939 AttributionSource attributionSource) { 3940 AdapterService service = getService(); 3941 if (service == null 3942 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "startRfcommListener") 3943 || !Utils.checkConnectPermissionForDataDelivery( 3944 service, attributionSource, "AdapterService startRfcommListener")) { 3945 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; 3946 } 3947 enforceBluetoothPrivilegedPermission(service); 3948 return service.startRfcommListener(name, uuid, pendingIntent, attributionSource); 3949 } 3950 3951 @Override stopRfcommListener(ParcelUuid uuid, AttributionSource attributionSource)3952 public int stopRfcommListener(ParcelUuid uuid, AttributionSource attributionSource) { 3953 AdapterService service = getService(); 3954 if (service == null 3955 || !callerIsSystemOrActiveOrManagedUser(service, TAG, "stopRfcommListener") 3956 || !Utils.checkConnectPermissionForDataDelivery( 3957 service, attributionSource, "AdapterService stopRfcommListener")) { 3958 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; 3959 } 3960 enforceBluetoothPrivilegedPermission(service); 3961 return service.stopRfcommListener(uuid, attributionSource); 3962 } 3963 3964 @Override retrievePendingSocketForServiceRecord( ParcelUuid uuid, AttributionSource attributionSource)3965 public IncomingRfcommSocketInfo retrievePendingSocketForServiceRecord( 3966 ParcelUuid uuid, AttributionSource attributionSource) { 3967 AdapterService service = getService(); 3968 if (service == null 3969 || !callerIsSystemOrActiveOrManagedUser( 3970 service, TAG, "retrievePendingSocketForServiceRecord") 3971 || !Utils.checkConnectPermissionForDataDelivery( 3972 service, 3973 attributionSource, 3974 "AdapterService retrievePendingSocketForServiceRecord")) { 3975 return null; 3976 } 3977 enforceBluetoothPrivilegedPermission(service); 3978 return service.retrievePendingSocketForServiceRecord(uuid, attributionSource); 3979 } 3980 3981 @Override setForegroundUserId(int userId, AttributionSource attributionSource)3982 public void setForegroundUserId(int userId, AttributionSource attributionSource) { 3983 AdapterService service = getService(); 3984 if (service == null 3985 || !Utils.checkConnectPermissionForDataDelivery( 3986 service, 3987 Utils.getCallingAttributionSource(mService), 3988 "AdapterService setForegroundUserId")) { 3989 return; 3990 } 3991 enforceBluetoothPrivilegedPermission(service); 3992 Utils.setForegroundUserId(userId); 3993 } 3994 3995 @Override setPreferredAudioProfiles( BluetoothDevice device, Bundle modeToProfileBundle, AttributionSource source)3996 public int setPreferredAudioProfiles( 3997 BluetoothDevice device, Bundle modeToProfileBundle, AttributionSource source) { 3998 AdapterService service = getService(); 3999 if (service == null) { 4000 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; 4001 } 4002 if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "setPreferredAudioProfiles")) { 4003 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; 4004 } 4005 requireNonNull(device); 4006 requireNonNull(modeToProfileBundle); 4007 if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { 4008 throw new IllegalArgumentException("device cannot have an invalid address"); 4009 } 4010 if (service.getBondState(device) != BluetoothDevice.BOND_BONDED) { 4011 return BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED; 4012 } 4013 if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 4014 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; 4015 } 4016 enforceBluetoothPrivilegedPermission(service); 4017 4018 return service.setPreferredAudioProfiles(device, modeToProfileBundle); 4019 } 4020 4021 @Override getPreferredAudioProfiles(BluetoothDevice device, AttributionSource source)4022 public Bundle getPreferredAudioProfiles(BluetoothDevice device, AttributionSource source) { 4023 AdapterService service = getService(); 4024 if (service == null) { 4025 return Bundle.EMPTY; 4026 } 4027 if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "getPreferredAudioProfiles")) { 4028 return Bundle.EMPTY; 4029 } 4030 requireNonNull(device); 4031 if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { 4032 throw new IllegalArgumentException("device cannot have an invalid address"); 4033 } 4034 if (service.getBondState(device) != BluetoothDevice.BOND_BONDED) { 4035 return Bundle.EMPTY; 4036 } 4037 if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 4038 return Bundle.EMPTY; 4039 } 4040 enforceBluetoothPrivilegedPermission(service); 4041 4042 return service.getPreferredAudioProfiles(device); 4043 } 4044 4045 @Override notifyActiveDeviceChangeApplied( BluetoothDevice device, AttributionSource source)4046 public int notifyActiveDeviceChangeApplied( 4047 BluetoothDevice device, AttributionSource source) { 4048 AdapterService service = getService(); 4049 if (service == null) { 4050 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; 4051 } 4052 if (!callerIsSystem(TAG, "notifyActiveDeviceChangeApplied")) { 4053 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; 4054 } 4055 requireNonNull(device); 4056 if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { 4057 throw new IllegalArgumentException("device cannot have an invalid address"); 4058 } 4059 if (service.getBondState(device) != BluetoothDevice.BOND_BONDED) { 4060 return BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED; 4061 } 4062 if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 4063 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; 4064 } 4065 enforceBluetoothPrivilegedPermission(service); 4066 4067 return service.notifyActiveDeviceChangeApplied(device); 4068 } 4069 4070 @Override registerPreferredAudioProfilesChangedCallback( IBluetoothPreferredAudioProfilesCallback callback, AttributionSource source)4071 public int registerPreferredAudioProfilesChangedCallback( 4072 IBluetoothPreferredAudioProfilesCallback callback, AttributionSource source) { 4073 AdapterService service = getService(); 4074 if (service == null) { 4075 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; 4076 } 4077 if (!callerIsSystemOrActiveOrManagedUser( 4078 service, TAG, "registerPreferredAudioProfilesChangedCallback")) { 4079 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; 4080 } 4081 requireNonNull(callback); 4082 if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 4083 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; 4084 } 4085 enforceBluetoothPrivilegedPermission(service); 4086 4087 // If LE only mode is enabled, the dual mode audio feature is disabled 4088 if (!isDualModeAudioEnabled()) { 4089 return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED; 4090 } 4091 4092 service.mPreferredAudioProfilesCallbacks.register(callback); 4093 return BluetoothStatusCodes.SUCCESS; 4094 } 4095 4096 @Override unregisterPreferredAudioProfilesChangedCallback( IBluetoothPreferredAudioProfilesCallback callback, AttributionSource source)4097 public int unregisterPreferredAudioProfilesChangedCallback( 4098 IBluetoothPreferredAudioProfilesCallback callback, AttributionSource source) { 4099 AdapterService service = getService(); 4100 if (service == null) { 4101 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; 4102 } 4103 if (!callerIsSystemOrActiveOrManagedUser( 4104 service, TAG, "unregisterPreferredAudioProfilesChangedCallback")) { 4105 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; 4106 } 4107 requireNonNull(callback); 4108 if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 4109 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; 4110 } 4111 enforceBluetoothPrivilegedPermission(service); 4112 4113 if (!service.mPreferredAudioProfilesCallbacks.unregister(callback)) { 4114 Log.e( 4115 TAG, 4116 "unregisterPreferredAudioProfilesChangedCallback: callback was never " 4117 + "registered"); 4118 return BluetoothStatusCodes.ERROR_CALLBACK_NOT_REGISTERED; 4119 } 4120 return BluetoothStatusCodes.SUCCESS; 4121 } 4122 4123 @Override registerBluetoothQualityReportReadyCallback( IBluetoothQualityReportReadyCallback callback, AttributionSource source)4124 public int registerBluetoothQualityReportReadyCallback( 4125 IBluetoothQualityReportReadyCallback callback, AttributionSource source) { 4126 AdapterService service = getService(); 4127 if (service == null) { 4128 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; 4129 } 4130 if (!callerIsSystemOrActiveOrManagedUser( 4131 service, TAG, "registerBluetoothQualityReportReadyCallback")) { 4132 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; 4133 } 4134 requireNonNull(callback); 4135 if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 4136 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; 4137 } 4138 enforceBluetoothPrivilegedPermission(service); 4139 4140 service.mBluetoothQualityReportReadyCallbacks.register(callback); 4141 return BluetoothStatusCodes.SUCCESS; 4142 } 4143 4144 @Override unregisterBluetoothQualityReportReadyCallback( IBluetoothQualityReportReadyCallback callback, AttributionSource source)4145 public int unregisterBluetoothQualityReportReadyCallback( 4146 IBluetoothQualityReportReadyCallback callback, AttributionSource source) { 4147 AdapterService service = getService(); 4148 if (service == null) { 4149 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; 4150 } 4151 if (!callerIsSystemOrActiveOrManagedUser( 4152 service, TAG, "unregisterBluetoothQualityReportReadyCallback")) { 4153 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; 4154 } 4155 requireNonNull(callback); 4156 if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 4157 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; 4158 } 4159 enforceBluetoothPrivilegedPermission(service); 4160 4161 if (!service.mBluetoothQualityReportReadyCallbacks.unregister(callback)) { 4162 Log.e( 4163 TAG, 4164 "unregisterBluetoothQualityReportReadyCallback: callback was never " 4165 + "registered"); 4166 return BluetoothStatusCodes.ERROR_CALLBACK_NOT_REGISTERED; 4167 } 4168 return BluetoothStatusCodes.SUCCESS; 4169 } 4170 4171 @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) 4172 @Override getOffloadedTransportDiscoveryDataScanSupported( AttributionSource attributionSource)4173 public int getOffloadedTransportDiscoveryDataScanSupported( 4174 AttributionSource attributionSource) { 4175 AdapterService service = getService(); 4176 if (service == null 4177 || !callerIsSystemOrActiveOrManagedUser( 4178 service, TAG, "getOffloadedTransportDiscoveryDataScanSupported") 4179 || !Utils.checkScanPermissionForDataDelivery( 4180 service, 4181 attributionSource, 4182 "getOffloadedTransportDiscoveryDataScanSupported")) { 4183 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_SCAN_PERMISSION; 4184 } 4185 enforceBluetoothPrivilegedPermission(service); 4186 4187 return service.getOffloadedTransportDiscoveryDataScanSupported(); 4188 } 4189 4190 @Override isMediaProfileConnected(AttributionSource source)4191 public boolean isMediaProfileConnected(AttributionSource source) { 4192 AdapterService service = getService(); 4193 if (service == null 4194 || !Utils.checkConnectPermissionForDataDelivery( 4195 service, source, "AdapterService.isMediaProfileConnected")) { 4196 return false; 4197 } 4198 enforceBluetoothPrivilegedPermission(service); 4199 4200 return service.isMediaProfileConnected(); 4201 } 4202 4203 @Override getBluetoothGatt()4204 public IBinder getBluetoothGatt() { 4205 AdapterService service = getService(); 4206 return service == null ? null : service.getBluetoothGatt(); 4207 } 4208 4209 @Override getBluetoothScan()4210 public IBinder getBluetoothScan() { 4211 AdapterService service = getService(); 4212 return service == null ? null : service.getBluetoothScan(); 4213 } 4214 4215 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) 4216 @Override unregAllGattClient(AttributionSource source)4217 public void unregAllGattClient(AttributionSource source) { 4218 AdapterService service = getService(); 4219 if (service == null) { 4220 return; 4221 } 4222 enforceBluetoothPrivilegedPermission(service); 4223 service.unregAllGattClient(source); 4224 } 4225 4226 @Override getProfile(int profileId)4227 public IBinder getProfile(int profileId) { 4228 AdapterService service = getService(); 4229 if (service == null) { 4230 return null; 4231 } 4232 4233 return service.getProfile(profileId); 4234 } 4235 4236 @Override setActiveAudioDevicePolicy( BluetoothDevice device, int activeAudioDevicePolicy, AttributionSource source)4237 public int setActiveAudioDevicePolicy( 4238 BluetoothDevice device, int activeAudioDevicePolicy, AttributionSource source) { 4239 AdapterService service = getService(); 4240 if (service == null) { 4241 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; 4242 } 4243 if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "setActiveAudioDevicePolicy")) { 4244 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; 4245 } 4246 if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { 4247 throw new IllegalArgumentException("device cannot have an invalid address"); 4248 } 4249 if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 4250 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; 4251 } 4252 4253 enforceBluetoothPrivilegedPermission(service); 4254 return service.mDatabaseManager.setActiveAudioDevicePolicy( 4255 device, activeAudioDevicePolicy); 4256 } 4257 4258 @Override getActiveAudioDevicePolicy(BluetoothDevice device, AttributionSource source)4259 public int getActiveAudioDevicePolicy(BluetoothDevice device, AttributionSource source) { 4260 AdapterService service = getService(); 4261 if (service == null) { 4262 return BluetoothDevice.ACTIVE_AUDIO_DEVICE_POLICY_DEFAULT; 4263 } 4264 if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "getActiveAudioDevicePolicy")) { 4265 throw new IllegalStateException( 4266 "Caller is not the system or part of the active/managed user"); 4267 } 4268 if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { 4269 throw new IllegalArgumentException("device cannot have an invalid address"); 4270 } 4271 if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { 4272 return BluetoothDevice.ACTIVE_AUDIO_DEVICE_POLICY_DEFAULT; 4273 } 4274 4275 enforceBluetoothPrivilegedPermission(service); 4276 return service.mDatabaseManager.getActiveAudioDevicePolicy(device); 4277 } 4278 } 4279 4280 /** 4281 * Gets the preferred audio profiles for the device. See {@link 4282 * BluetoothAdapter#getPreferredAudioProfiles(BluetoothDevice)} for more details. 4283 * 4284 * @param device is the remote device whose preferences we want to fetch 4285 * @return a Bundle containing the preferred audio profiles for the device 4286 */ getPreferredAudioProfiles(BluetoothDevice device)4287 public Bundle getPreferredAudioProfiles(BluetoothDevice device) { 4288 if (!isDualModeAudioEnabled() 4289 || mLeAudioService == null 4290 || !isDualModeAudioSinkDevice(device)) { 4291 return Bundle.EMPTY; 4292 } 4293 // Checks if the device is part of an LE Audio group 4294 List<BluetoothDevice> groupDevices = mLeAudioService.getGroupDevices(device); 4295 if (groupDevices.isEmpty()) { 4296 return Bundle.EMPTY; 4297 } 4298 4299 // If there are no preferences stored, return the defaults 4300 Bundle storedBundle = Bundle.EMPTY; 4301 for (BluetoothDevice groupDevice : groupDevices) { 4302 Bundle groupDevicePreferences = mDatabaseManager.getPreferredAudioProfiles(groupDevice); 4303 if (!groupDevicePreferences.isEmpty()) { 4304 storedBundle = groupDevicePreferences; 4305 break; 4306 } 4307 } 4308 4309 if (storedBundle.isEmpty()) { 4310 Bundle defaultPreferencesBundle = new Bundle(); 4311 boolean useDefaultPreferences = false; 4312 if (isOutputOnlyAudioSupported(groupDevices)) { 4313 // Gets the default output only audio profile or defaults to LE_AUDIO if not present 4314 int outputOnlyDefault = 4315 BluetoothProperties.getDefaultOutputOnlyAudioProfile() 4316 .orElse(BluetoothProfile.LE_AUDIO); 4317 if (outputOnlyDefault != BluetoothProfile.A2DP 4318 && outputOnlyDefault != BluetoothProfile.LE_AUDIO) { 4319 outputOnlyDefault = BluetoothProfile.LE_AUDIO; 4320 } 4321 defaultPreferencesBundle.putInt( 4322 BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY, outputOnlyDefault); 4323 useDefaultPreferences = true; 4324 } 4325 if (isDuplexAudioSupported(groupDevices)) { 4326 // Gets the default duplex audio profile or defaults to LE_AUDIO if not present 4327 int duplexDefault = 4328 BluetoothProperties.getDefaultDuplexAudioProfile() 4329 .orElse(BluetoothProfile.LE_AUDIO); 4330 if (duplexDefault != BluetoothProfile.HEADSET 4331 && duplexDefault != BluetoothProfile.LE_AUDIO) { 4332 duplexDefault = BluetoothProfile.LE_AUDIO; 4333 } 4334 defaultPreferencesBundle.putInt(BluetoothAdapter.AUDIO_MODE_DUPLEX, duplexDefault); 4335 useDefaultPreferences = true; 4336 } 4337 4338 if (useDefaultPreferences) { 4339 return defaultPreferencesBundle; 4340 } 4341 } 4342 return storedBundle; 4343 } 4344 4345 /** 4346 * Sets the preferred audio profiles for the device. See {@link 4347 * BluetoothAdapter#setPreferredAudioProfiles(BluetoothDevice, Bundle)} for more details. 4348 * 4349 * @param device is the remote device whose preferences we want to fetch 4350 * @param modeToProfileBundle is the preferences we want to set for the device 4351 * @return whether the preferences were successfully requested 4352 */ setPreferredAudioProfiles(BluetoothDevice device, Bundle modeToProfileBundle)4353 private int setPreferredAudioProfiles(BluetoothDevice device, Bundle modeToProfileBundle) { 4354 Log.i(TAG, "setPreferredAudioProfiles for device=" + device.getAddressForLogging()); 4355 if (!isDualModeAudioEnabled()) { 4356 Log.e(TAG, "setPreferredAudioProfiles called while sysprop is disabled"); 4357 return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED; 4358 } 4359 if (mLeAudioService == null) { 4360 Log.e(TAG, "setPreferredAudioProfiles: LEA service is not up"); 4361 return BluetoothStatusCodes.ERROR_PROFILE_NOT_CONNECTED; 4362 } 4363 if (!isDualModeAudioSinkDevice(device)) { 4364 Log.e(TAG, "setPreferredAudioProfiles: Not a dual mode audio device"); 4365 return BluetoothStatusCodes.ERROR_NOT_DUAL_MODE_AUDIO_DEVICE; 4366 } 4367 // Checks if the device is part of an LE Audio group 4368 int groupId = mLeAudioService.getGroupId(device); 4369 List<BluetoothDevice> groupDevices = mLeAudioService.getGroupDevices(groupId); 4370 if (groupDevices.isEmpty()) { 4371 return BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED; 4372 } 4373 4374 // Copies relevant keys & values from modeToProfile bundle 4375 Bundle strippedPreferences = new Bundle(); 4376 if (modeToProfileBundle.containsKey(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY) 4377 && isOutputOnlyAudioSupported(groupDevices)) { 4378 int outputOnlyProfile = 4379 modeToProfileBundle.getInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY); 4380 if (outputOnlyProfile != BluetoothProfile.A2DP 4381 && outputOnlyProfile != BluetoothProfile.LE_AUDIO) { 4382 throw new IllegalArgumentException( 4383 "AUDIO_MODE_OUTPUT_ONLY has invalid value: " + outputOnlyProfile); 4384 } 4385 strippedPreferences.putInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY, outputOnlyProfile); 4386 } 4387 if (modeToProfileBundle.containsKey(BluetoothAdapter.AUDIO_MODE_DUPLEX) 4388 && isDuplexAudioSupported(groupDevices)) { 4389 int duplexProfile = modeToProfileBundle.getInt(BluetoothAdapter.AUDIO_MODE_DUPLEX); 4390 if (duplexProfile != BluetoothProfile.HEADSET 4391 && duplexProfile != BluetoothProfile.LE_AUDIO) { 4392 throw new IllegalArgumentException( 4393 "AUDIO_MODE_DUPLEX has invalid value: " + duplexProfile); 4394 } 4395 strippedPreferences.putInt(BluetoothAdapter.AUDIO_MODE_DUPLEX, duplexProfile); 4396 } 4397 4398 synchronized (mCsipGroupsPendingAudioProfileChanges) { 4399 if (mCsipGroupsPendingAudioProfileChanges.containsKey(groupId)) { 4400 return BluetoothStatusCodes.ERROR_ANOTHER_ACTIVE_REQUEST; 4401 } 4402 4403 Bundle previousPreferences = getPreferredAudioProfiles(device); 4404 4405 int dbResult = 4406 mDatabaseManager.setPreferredAudioProfiles(groupDevices, strippedPreferences); 4407 if (dbResult != BluetoothStatusCodes.SUCCESS) { 4408 return dbResult; 4409 } 4410 4411 int outputOnlyPreference = 4412 strippedPreferences.getInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY); 4413 if (outputOnlyPreference == 0) { 4414 outputOnlyPreference = 4415 previousPreferences.getInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY); 4416 } 4417 int duplexPreference = strippedPreferences.getInt(BluetoothAdapter.AUDIO_MODE_DUPLEX); 4418 if (duplexPreference == 0) { 4419 duplexPreference = previousPreferences.getInt(BluetoothAdapter.AUDIO_MODE_DUPLEX); 4420 } 4421 4422 mLeAudioService.sendAudioProfilePreferencesToNative( 4423 groupId, 4424 outputOnlyPreference == BluetoothProfile.LE_AUDIO, 4425 duplexPreference == BluetoothProfile.LE_AUDIO); 4426 4427 /* Populates the HashMap to hold requests on the groupId. We will update 4428 numRequestsToAudioFramework after we make requests to the audio framework */ 4429 PendingAudioProfilePreferenceRequest holdRequest = 4430 new PendingAudioProfilePreferenceRequest(strippedPreferences, 0, device); 4431 mCsipGroupsPendingAudioProfileChanges.put(groupId, holdRequest); 4432 4433 // Notifies audio framework via the handler thread to avoid this blocking calls 4434 mHandler.post( 4435 () -> 4436 sendPreferredAudioProfileChangeToAudioFramework( 4437 device, strippedPreferences, previousPreferences)); 4438 return BluetoothStatusCodes.SUCCESS; 4439 } 4440 } 4441 4442 /** 4443 * Sends the updated preferred audio profiles to the audio framework. 4444 * 4445 * @param device is the device with updated audio preferences 4446 * @param strippedPreferences is a {@link Bundle} containing the preferences 4447 */ sendPreferredAudioProfileChangeToAudioFramework( BluetoothDevice device, Bundle strippedPreferences, Bundle previousPreferences)4448 private void sendPreferredAudioProfileChangeToAudioFramework( 4449 BluetoothDevice device, Bundle strippedPreferences, Bundle previousPreferences) { 4450 int newOutput = strippedPreferences.getInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY); 4451 int newDuplex = strippedPreferences.getInt(BluetoothAdapter.AUDIO_MODE_DUPLEX); 4452 int previousOutput = previousPreferences.getInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY); 4453 int previousDuplex = previousPreferences.getInt(BluetoothAdapter.AUDIO_MODE_DUPLEX); 4454 4455 Log.i( 4456 TAG, 4457 "sendPreferredAudioProfileChangeToAudioFramework: changing output from " 4458 + BluetoothProfile.getProfileName(previousOutput) 4459 + " to " 4460 + BluetoothProfile.getProfileName(newOutput) 4461 + " and duplex from " 4462 + BluetoothProfile.getProfileName(previousDuplex) 4463 + " to " 4464 + BluetoothProfile.getProfileName(newDuplex)); 4465 4466 // If no change from existing preferences, do not inform audio framework 4467 if (previousOutput == newOutput && previousDuplex == newDuplex) { 4468 Log.i(TAG, "No change to preferred audio profiles, no requests to Audio FW"); 4469 sendPreferredAudioProfilesCallbackToApps( 4470 device, strippedPreferences, BluetoothStatusCodes.SUCCESS); 4471 return; 4472 } 4473 4474 int numRequestsToAudioFw = 0; 4475 4476 // Checks if the device is part of an LE Audio group 4477 int groupId = mLeAudioService.getGroupId(device); 4478 List<BluetoothDevice> groupDevices = mLeAudioService.getGroupDevices(groupId); 4479 if (groupDevices.isEmpty()) { 4480 Log.i( 4481 TAG, 4482 "sendPreferredAudioProfileChangeToAudioFramework: Empty LEA group for " 4483 + "device - " 4484 + device); 4485 sendPreferredAudioProfilesCallbackToApps( 4486 device, strippedPreferences, BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED); 4487 return; 4488 } 4489 4490 synchronized (mCsipGroupsPendingAudioProfileChanges) { 4491 if (previousOutput != newOutput) { 4492 if (newOutput == BluetoothProfile.A2DP 4493 && mA2dpService.getActiveDevice() != null 4494 && groupDevices.contains(mA2dpService.getActiveDevice())) { 4495 Log.i(TAG, "Sent change for AUDIO_MODE_OUTPUT_ONLY to A2DP to Audio FW"); 4496 numRequestsToAudioFw += 4497 mA2dpService.sendPreferredAudioProfileChangeToAudioFramework(); 4498 } else if (newOutput == BluetoothProfile.LE_AUDIO 4499 && mLeAudioService.getActiveGroupId() == groupId) { 4500 Log.i(TAG, "Sent change for AUDIO_MODE_OUTPUT_ONLY to LE_AUDIO to Audio FW"); 4501 numRequestsToAudioFw += 4502 mLeAudioService.sendPreferredAudioProfileChangeToAudioFramework(); 4503 } 4504 } 4505 4506 if (previousDuplex != newDuplex) { 4507 if (newDuplex == BluetoothProfile.HEADSET 4508 && mHeadsetService.getActiveDevice() != null 4509 && groupDevices.contains(mHeadsetService.getActiveDevice())) { 4510 Log.i(TAG, "Sent change for AUDIO_MODE_DUPLEX to HFP to Audio FW"); 4511 // TODO(b/275426145): Add similar HFP method in BluetoothProfileConnectionInfo 4512 numRequestsToAudioFw += 4513 mA2dpService.sendPreferredAudioProfileChangeToAudioFramework(); 4514 } else if (newDuplex == BluetoothProfile.LE_AUDIO 4515 && mLeAudioService.getActiveGroupId() == groupId) { 4516 Log.i(TAG, "Sent change for AUDIO_MODE_DUPLEX to LE_AUDIO to Audio FW"); 4517 numRequestsToAudioFw += 4518 mLeAudioService.sendPreferredAudioProfileChangeToAudioFramework(); 4519 } 4520 } 4521 4522 Log.i( 4523 TAG, 4524 "sendPreferredAudioProfileChangeToAudioFramework: sent " 4525 + numRequestsToAudioFw 4526 + " request(s) to the Audio Framework for device: " 4527 + device); 4528 4529 if (numRequestsToAudioFw > 0) { 4530 mCsipGroupsPendingAudioProfileChanges.put( 4531 groupId, 4532 new PendingAudioProfilePreferenceRequest( 4533 strippedPreferences, numRequestsToAudioFw, device)); 4534 4535 Message m = 4536 mHandler.obtainMessage( 4537 MESSAGE_PREFERRED_AUDIO_PROFILES_AUDIO_FRAMEWORK_TIMEOUT); 4538 m.obj = groupId; 4539 mHandler.sendMessageDelayed(m, PREFERRED_AUDIO_PROFILE_CHANGE_TIMEOUT.toMillis()); 4540 return; 4541 } 4542 } 4543 sendPreferredAudioProfilesCallbackToApps( 4544 device, strippedPreferences, BluetoothStatusCodes.SUCCESS); 4545 } 4546 removeFromPendingAudioProfileChanges(int groupId)4547 private void removeFromPendingAudioProfileChanges(int groupId) { 4548 synchronized (mCsipGroupsPendingAudioProfileChanges) { 4549 Log.i( 4550 TAG, 4551 "removeFromPendingAudioProfileChanges: Timeout on change for groupId=" 4552 + groupId); 4553 if (!mCsipGroupsPendingAudioProfileChanges.containsKey(groupId)) { 4554 Log.e( 4555 TAG, 4556 "removeFromPendingAudioProfileChanges( " 4557 + groupId 4558 + ", " 4559 + groupId 4560 + ") is not pending"); 4561 return; 4562 } 4563 } 4564 } 4565 4566 /** 4567 * Notification from the audio framework that an active device change has taken effect. See 4568 * {@link BluetoothAdapter#notifyActiveDeviceChangeApplied(BluetoothDevice)} for more details. 4569 * 4570 * @param device the remote device whose preferred audio profiles have been changed 4571 * @return whether the Bluetooth stack acknowledged the change successfully 4572 */ notifyActiveDeviceChangeApplied(BluetoothDevice device)4573 private int notifyActiveDeviceChangeApplied(BluetoothDevice device) { 4574 if (mLeAudioService == null) { 4575 Log.e(TAG, "LE Audio profile not enabled"); 4576 return BluetoothStatusCodes.ERROR_PROFILE_NOT_CONNECTED; 4577 } 4578 4579 int groupId = mLeAudioService.getGroupId(device); 4580 if (groupId == LE_AUDIO_GROUP_ID_INVALID) { 4581 return BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED; 4582 } 4583 4584 synchronized (mCsipGroupsPendingAudioProfileChanges) { 4585 if (!mCsipGroupsPendingAudioProfileChanges.containsKey(groupId)) { 4586 Log.e( 4587 TAG, 4588 "notifyActiveDeviceChangeApplied, but no pending request for " 4589 + "groupId: " 4590 + groupId); 4591 return BluetoothStatusCodes.ERROR_UNKNOWN; 4592 } 4593 4594 PendingAudioProfilePreferenceRequest pendingRequest = 4595 mCsipGroupsPendingAudioProfileChanges.get(groupId); 4596 4597 // If this is the final audio framework request, send callback to apps 4598 if (pendingRequest.mRemainingRequestsToAudioFramework == 1) { 4599 Log.i( 4600 TAG, 4601 "notifyActiveDeviceChangeApplied: Complete for device " 4602 + pendingRequest.mDeviceRequested); 4603 sendPreferredAudioProfilesCallbackToApps( 4604 pendingRequest.mDeviceRequested, 4605 pendingRequest.mRequestedPreferences, 4606 BluetoothStatusCodes.SUCCESS); 4607 // Removes the timeout from the handler 4608 mHandler.removeMessages( 4609 MESSAGE_PREFERRED_AUDIO_PROFILES_AUDIO_FRAMEWORK_TIMEOUT, groupId); 4610 } else if (pendingRequest.mRemainingRequestsToAudioFramework > 1) { 4611 PendingAudioProfilePreferenceRequest updatedPendingRequest = 4612 new PendingAudioProfilePreferenceRequest( 4613 pendingRequest.mRequestedPreferences, 4614 pendingRequest.mRemainingRequestsToAudioFramework - 1, 4615 pendingRequest.mDeviceRequested); 4616 Log.i( 4617 TAG, 4618 "notifyActiveDeviceChangeApplied: Updating device " 4619 + updatedPendingRequest.mDeviceRequested 4620 + " with new remaining requests count=" 4621 + updatedPendingRequest.mRemainingRequestsToAudioFramework); 4622 mCsipGroupsPendingAudioProfileChanges.put(groupId, updatedPendingRequest); 4623 } else { 4624 Log.i( 4625 TAG, 4626 "notifyActiveDeviceChangeApplied: " 4627 + pendingRequest.mDeviceRequested 4628 + " has no remaining requests to audio framework, but is still" 4629 + " present in mCsipGroupsPendingAudioProfileChanges"); 4630 } 4631 } 4632 4633 return BluetoothStatusCodes.SUCCESS; 4634 } 4635 sendPreferredAudioProfilesCallbackToApps( BluetoothDevice device, Bundle preferredAudioProfiles, int status)4636 private void sendPreferredAudioProfilesCallbackToApps( 4637 BluetoothDevice device, Bundle preferredAudioProfiles, int status) { 4638 int n = mPreferredAudioProfilesCallbacks.beginBroadcast(); 4639 Log.d( 4640 TAG, 4641 "sendPreferredAudioProfilesCallbackToApps() - Broadcasting audio profile " 4642 + ("change callback to device: " + device) 4643 + (" and status=" + status) 4644 + (" to " + n + " receivers.")); 4645 for (int i = 0; i < n; i++) { 4646 try { 4647 mPreferredAudioProfilesCallbacks 4648 .getBroadcastItem(i) 4649 .onPreferredAudioProfilesChanged(device, preferredAudioProfiles, status); 4650 } catch (RemoteException e) { 4651 Log.d( 4652 TAG, 4653 "sendPreferredAudioProfilesCallbackToApps() - Callback #" 4654 + i 4655 + " failed (" 4656 + e 4657 + ")"); 4658 } 4659 } 4660 mPreferredAudioProfilesCallbacks.finishBroadcast(); 4661 } 4662 4663 // ----API Methods-------- 4664 isEnabled()4665 public boolean isEnabled() { 4666 return getState() == BluetoothAdapter.STATE_ON; 4667 } 4668 getState()4669 public int getState() { 4670 if (mAdapterProperties != null) { 4671 return mAdapterProperties.getState(); 4672 } 4673 return BluetoothAdapter.STATE_OFF; 4674 } 4675 4676 @RequiresPermission( 4677 anyOf = { 4678 android.Manifest.permission.INTERACT_ACROSS_USERS, 4679 android.Manifest.permission.MANAGE_USERS, 4680 }) enable(boolean quietMode)4681 public synchronized void enable(boolean quietMode) { 4682 // Enforce the user restriction for disallowing Bluetooth if it was set. 4683 if (mUserManager.hasUserRestrictionForUser( 4684 UserManager.DISALLOW_BLUETOOTH, UserHandle.SYSTEM)) { 4685 Log.d(TAG, "enable() called when Bluetooth was disallowed"); 4686 return; 4687 } 4688 if (Flags.fastBindToApp()) { 4689 // The call to init must be done on the main thread 4690 mHandler.post(() -> init()); 4691 } 4692 4693 Log.i(TAG, "enable() - Enable called with quiet mode status = " + quietMode); 4694 mQuietmode = quietMode; 4695 mAdapterStateMachine.sendMessage(AdapterState.BLE_TURN_ON); 4696 } 4697 disable()4698 void disable() { 4699 Log.d(TAG, "disable() called with mRunningProfiles.size() = " + mRunningProfiles.size()); 4700 mAdapterStateMachine.sendMessage(AdapterState.USER_TURN_OFF); 4701 } 4702 getName()4703 public String getName() { 4704 return mAdapterProperties.getName(); 4705 } 4706 getNameLengthForAdvertise()4707 public int getNameLengthForAdvertise() { 4708 return mAdapterProperties.getName().length(); 4709 } 4710 getDiscoveringPackages()4711 List<DiscoveringPackage> getDiscoveringPackages() { 4712 return mDiscoveringPackages; 4713 } 4714 clearDiscoveringPackages()4715 void clearDiscoveringPackages() { 4716 synchronized (mDiscoveringPackages) { 4717 mDiscoveringPackages.clear(); 4718 } 4719 } 4720 startDiscovery(AttributionSource attributionSource)4721 boolean startDiscovery(AttributionSource attributionSource) { 4722 UserHandle callingUser = Binder.getCallingUserHandle(); 4723 Log.d(TAG, "startDiscovery"); 4724 String callingPackage = attributionSource.getPackageName(); 4725 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); 4726 boolean isQApp = Utils.checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.Q); 4727 boolean hasDisavowedLocation = 4728 Utils.hasDisavowedLocationForScan(this, attributionSource, mTestModeEnabled); 4729 String permission = null; 4730 if (Utils.checkCallerHasNetworkSettingsPermission(this)) { 4731 permission = android.Manifest.permission.NETWORK_SETTINGS; 4732 } else if (Utils.checkCallerHasNetworkSetupWizardPermission(this)) { 4733 permission = android.Manifest.permission.NETWORK_SETUP_WIZARD; 4734 } else if (!hasDisavowedLocation) { 4735 if (isQApp) { 4736 if (!Utils.checkCallerHasFineLocation(this, attributionSource, callingUser)) { 4737 return false; 4738 } 4739 permission = android.Manifest.permission.ACCESS_FINE_LOCATION; 4740 } else { 4741 if (!Utils.checkCallerHasCoarseLocation(this, attributionSource, callingUser)) { 4742 return false; 4743 } 4744 permission = android.Manifest.permission.ACCESS_COARSE_LOCATION; 4745 } 4746 } 4747 4748 synchronized (mDiscoveringPackages) { 4749 mDiscoveringPackages.add( 4750 new DiscoveringPackage(callingPackage, permission, hasDisavowedLocation)); 4751 } 4752 return mNativeInterface.startDiscovery(); 4753 } 4754 4755 /** 4756 * Same as API method {@link BluetoothAdapter#getBondedDevices()} 4757 * 4758 * @return array of bonded {@link BluetoothDevice} or null on error 4759 */ getBondedDevices()4760 public BluetoothDevice[] getBondedDevices() { 4761 return mAdapterProperties.getBondedDevices(); 4762 } 4763 4764 /** 4765 * Get the database manager to access Bluetooth storage 4766 * 4767 * @return {@link DatabaseManager} or null on error 4768 */ getDatabase()4769 public DatabaseManager getDatabase() { 4770 return mDatabaseManager; 4771 } 4772 getByteIdentityAddress(BluetoothDevice device)4773 public byte[] getByteIdentityAddress(BluetoothDevice device) { 4774 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 4775 if (deviceProp != null && deviceProp.getIdentityAddress() != null) { 4776 return Utils.getBytesFromAddress(deviceProp.getIdentityAddress()); 4777 } 4778 4779 if (Flags.identityAddressNullIfUnknown()) { 4780 // Return null if identity address unknown 4781 return null; 4782 } else { 4783 return Utils.getByteAddress(device); 4784 } 4785 } 4786 getDeviceFromByte(byte[] address)4787 public BluetoothDevice getDeviceFromByte(byte[] address) { 4788 BluetoothDevice device = mRemoteDevices.getDevice(address); 4789 if (device == null) { 4790 device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address); 4791 } 4792 return device; 4793 } 4794 getIdentityAddress(String address)4795 public String getIdentityAddress(String address) { 4796 BluetoothDevice device = 4797 BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address.toUpperCase()); 4798 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 4799 if (deviceProp != null && deviceProp.getIdentityAddress() != null) { 4800 return deviceProp.getIdentityAddress(); 4801 } else { 4802 if (Flags.identityAddressNullIfUnknown()) { 4803 // Return null if identity address unknown 4804 return null; 4805 } else { 4806 return address; 4807 } 4808 } 4809 } 4810 4811 private static class CallerInfo { 4812 public String callerPackageName; 4813 public UserHandle user; 4814 } 4815 createBond( BluetoothDevice device, int transport, OobData remoteP192Data, OobData remoteP256Data, String callingPackage)4816 boolean createBond( 4817 BluetoothDevice device, 4818 int transport, 4819 OobData remoteP192Data, 4820 OobData remoteP256Data, 4821 String callingPackage) { 4822 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 4823 if (deviceProp != null && deviceProp.getBondState() != BluetoothDevice.BOND_NONE) { 4824 // true for BONDING, false for BONDED 4825 return deviceProp.getBondState() == BluetoothDevice.BOND_BONDING; 4826 } 4827 4828 if (!isPackageNameAccurate(this, callingPackage, Binder.getCallingUid())) { 4829 return false; 4830 } 4831 4832 CallerInfo createBondCaller = new CallerInfo(); 4833 createBondCaller.callerPackageName = callingPackage; 4834 createBondCaller.user = Binder.getCallingUserHandle(); 4835 mBondAttemptCallerInfo.put(device.getAddress(), createBondCaller); 4836 4837 mRemoteDevices.setBondingInitiatedLocally(Utils.getByteAddress(device)); 4838 4839 // Pairing is unreliable while scanning, so cancel discovery 4840 // Note, remove this when native stack improves 4841 mNativeInterface.cancelDiscovery(); 4842 4843 Message msg = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND); 4844 msg.obj = device; 4845 msg.arg1 = transport; 4846 4847 Bundle remoteOobDatasBundle = new Bundle(); 4848 boolean setData = false; 4849 if (remoteP192Data != null) { 4850 remoteOobDatasBundle.putParcelable(BondStateMachine.OOBDATAP192, remoteP192Data); 4851 setData = true; 4852 } 4853 if (remoteP256Data != null) { 4854 remoteOobDatasBundle.putParcelable(BondStateMachine.OOBDATAP256, remoteP256Data); 4855 setData = true; 4856 } 4857 if (setData) { 4858 msg.setData(remoteOobDatasBundle); 4859 } 4860 mBondStateMachine.sendMessage(msg); 4861 return true; 4862 } 4863 4864 /** 4865 * Fetches the local OOB data to give out to remote. 4866 * 4867 * @param transport - specify data transport. 4868 * @param callback - callback used to receive the requested {@link OobData}; null will be 4869 * ignored silently. 4870 */ generateLocalOobData( int transport, IBluetoothOobDataCallback callback)4871 public synchronized void generateLocalOobData( 4872 int transport, IBluetoothOobDataCallback callback) { 4873 if (callback == null) { 4874 Log.e(TAG, "'callback' argument must not be null!"); 4875 return; 4876 } 4877 if (mOobDataCallbackQueue.peek() != null) { 4878 try { 4879 callback.onError(BluetoothStatusCodes.ERROR_ANOTHER_ACTIVE_OOB_REQUEST); 4880 } catch (RemoteException e) { 4881 Log.e(TAG, "Failed to make callback", e); 4882 } 4883 return; 4884 } 4885 mOobDataCallbackQueue.offer(callback); 4886 mHandler.postDelayed( 4887 () -> removeFromOobDataCallbackQueue(callback), 4888 GENERATE_LOCAL_OOB_DATA_TIMEOUT.toMillis()); 4889 mNativeInterface.generateLocalOobData(transport); 4890 } 4891 removeFromOobDataCallbackQueue(IBluetoothOobDataCallback callback)4892 private synchronized void removeFromOobDataCallbackQueue(IBluetoothOobDataCallback callback) { 4893 if (callback == null) { 4894 return; 4895 } 4896 4897 if (mOobDataCallbackQueue.peek() == callback) { 4898 try { 4899 mOobDataCallbackQueue.poll().onError(BluetoothStatusCodes.ERROR_UNKNOWN); 4900 } catch (RemoteException e) { 4901 Log.e(TAG, "Failed to make OobDataCallback to remove callback from queue", e); 4902 } 4903 } 4904 } 4905 notifyOobDataCallback(int transport, OobData oobData)4906 /* package */ synchronized void notifyOobDataCallback(int transport, OobData oobData) { 4907 if (mOobDataCallbackQueue.peek() == null) { 4908 Log.e(TAG, "Failed to make callback, no callback exists"); 4909 return; 4910 } 4911 if (oobData == null) { 4912 try { 4913 mOobDataCallbackQueue.poll().onError(BluetoothStatusCodes.ERROR_UNKNOWN); 4914 } catch (RemoteException e) { 4915 Log.e(TAG, "Failed to make callback", e); 4916 } 4917 } else { 4918 try { 4919 mOobDataCallbackQueue.poll().onOobData(transport, oobData); 4920 } catch (RemoteException e) { 4921 Log.e(TAG, "Failed to make callback", e); 4922 } 4923 } 4924 } 4925 isQuietModeEnabled()4926 public boolean isQuietModeEnabled() { 4927 Log.d(TAG, "isQuietModeEnabled() - Enabled = " + mQuietmode); 4928 return mQuietmode; 4929 } 4930 updateUuids()4931 public void updateUuids() { 4932 Log.d(TAG, "updateUuids() - Updating UUIDs for bonded devices"); 4933 BluetoothDevice[] bondedDevices = getBondedDevices(); 4934 if (bondedDevices == null) { 4935 return; 4936 } 4937 4938 for (BluetoothDevice device : bondedDevices) { 4939 mRemoteDevices.updateUuids(device); 4940 } 4941 } 4942 4943 /** 4944 * Update device UUID changed to {@link BondStateMachine} 4945 * 4946 * @param device remote device of interest 4947 */ deviceUuidUpdated(BluetoothDevice device)4948 public void deviceUuidUpdated(BluetoothDevice device) { 4949 // Notify BondStateMachine for SDP complete / UUID changed. 4950 Message msg = mBondStateMachine.obtainMessage(BondStateMachine.UUID_UPDATE); 4951 msg.obj = device; 4952 mBondStateMachine.sendMessage(msg); 4953 } 4954 4955 /** 4956 * Get the bond state of a particular {@link BluetoothDevice} 4957 * 4958 * @param device remote device of interest 4959 * @return bond state 4960 * <p>Possible values are {@link BluetoothDevice#BOND_NONE}, {@link 4961 * BluetoothDevice#BOND_BONDING}, {@link BluetoothDevice#BOND_BONDED}. 4962 */ 4963 @VisibleForTesting getBondState(BluetoothDevice device)4964 public int getBondState(BluetoothDevice device) { 4965 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 4966 if (deviceProp == null) { 4967 return BluetoothDevice.BOND_NONE; 4968 } 4969 return deviceProp.getBondState(); 4970 } 4971 getConnectionState(BluetoothDevice device)4972 int getConnectionState(BluetoothDevice device) { 4973 final String address = device.getAddress(); 4974 if (Flags.apiGetConnectionStateUsingIdentityAddress()) { 4975 int connectionState = mNativeInterface.getConnectionState(getBytesFromAddress(address)); 4976 final String identityAddress = getIdentityAddress(address); 4977 if (identityAddress != null) { 4978 connectionState |= 4979 mNativeInterface.getConnectionState(getBytesFromAddress(identityAddress)); 4980 } 4981 return connectionState; 4982 } 4983 return mNativeInterface.getConnectionState(getBytesFromAddress(address)); 4984 } 4985 getConnectionHandle(BluetoothDevice device, int transport)4986 int getConnectionHandle(BluetoothDevice device, int transport) { 4987 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 4988 if (deviceProp == null) { 4989 return BluetoothDevice.ERROR; 4990 } 4991 return deviceProp.getConnectionHandle(transport); 4992 } 4993 4994 /** 4995 * Get ASHA Capability 4996 * 4997 * @param device discovered bluetooth device 4998 * @return ASHA capability 4999 */ getAshaCapability(BluetoothDevice device)5000 public int getAshaCapability(BluetoothDevice device) { 5001 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 5002 if (deviceProp == null) { 5003 return BluetoothDevice.ERROR; 5004 } 5005 return deviceProp.getAshaCapability(); 5006 } 5007 5008 /** 5009 * Get ASHA truncated HiSyncId 5010 * 5011 * @param device discovered bluetooth device 5012 * @return ASHA truncated HiSyncId 5013 */ getAshaTruncatedHiSyncId(BluetoothDevice device)5014 public int getAshaTruncatedHiSyncId(BluetoothDevice device) { 5015 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 5016 if (deviceProp == null) { 5017 return BluetoothDevice.ERROR; 5018 } 5019 return deviceProp.getAshaTruncatedHiSyncId(); 5020 } 5021 5022 /** 5023 * Checks whether the device was recently associated with the comapnion app that called {@link 5024 * BluetoothDevice#createBond}. This allows these devices to skip the pairing dialog if their 5025 * pairing variant is {@link BluetoothDevice#PAIRING_VARIANT_CONSENT}. 5026 * 5027 * @param device the bluetooth device that is being bonded 5028 * @return true if it was recently associated and we can bypass the dialog, false otherwise 5029 */ canBondWithoutDialog(BluetoothDevice device)5030 public boolean canBondWithoutDialog(BluetoothDevice device) { 5031 if (mBondAttemptCallerInfo.containsKey(device.getAddress())) { 5032 CallerInfo bondCallerInfo = mBondAttemptCallerInfo.get(device.getAddress()); 5033 5034 return mCompanionDeviceManager.canPairWithoutPrompt( 5035 bondCallerInfo.callerPackageName, device.getAddress(), bondCallerInfo.user); 5036 } 5037 return false; 5038 } 5039 5040 /** 5041 * Returns the package name of the most recent caller that called {@link 5042 * BluetoothDevice#createBond} on the given device. 5043 */ 5044 @Nullable getPackageNameOfBondingApplication(BluetoothDevice device)5045 public String getPackageNameOfBondingApplication(BluetoothDevice device) { 5046 CallerInfo info = mBondAttemptCallerInfo.get(device.getAddress()); 5047 if (info == null) { 5048 return null; 5049 } 5050 return info.callerPackageName; 5051 } 5052 5053 /** 5054 * Sets device as the active devices for the profiles passed into the function. 5055 * 5056 * @param device is the remote bluetooth device 5057 * @param profiles is a constant that references for which profiles we'll be setting the remote 5058 * device as our active device. One of the following: {@link 5059 * BluetoothAdapter#ACTIVE_DEVICE_AUDIO}, {@link BluetoothAdapter#ACTIVE_DEVICE_PHONE_CALL} 5060 * {@link BluetoothAdapter#ACTIVE_DEVICE_ALL} 5061 * @return false if profiles value is not one of the constants we accept, true otherwise 5062 */ 5063 @RequiresPermission( 5064 allOf = { 5065 android.Manifest.permission.BLUETOOTH_PRIVILEGED, 5066 android.Manifest.permission.MODIFY_PHONE_STATE, 5067 }) setActiveDevice(BluetoothDevice device, @ActiveDeviceUse int profiles)5068 public boolean setActiveDevice(BluetoothDevice device, @ActiveDeviceUse int profiles) { 5069 boolean setA2dp = false; 5070 boolean setHeadset = false; 5071 5072 // Determine for which profiles we want to set device as our active device 5073 switch (profiles) { 5074 case BluetoothAdapter.ACTIVE_DEVICE_AUDIO: 5075 setA2dp = true; 5076 break; 5077 case BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL: 5078 setHeadset = true; 5079 break; 5080 case BluetoothAdapter.ACTIVE_DEVICE_ALL: 5081 setA2dp = true; 5082 setHeadset = true; 5083 break; 5084 default: 5085 return false; 5086 } 5087 5088 boolean a2dpSupported = 5089 mA2dpService != null 5090 && (device == null 5091 || mA2dpService.getConnectionPolicy(device) 5092 == BluetoothProfile.CONNECTION_POLICY_ALLOWED); 5093 boolean hfpSupported = 5094 mHeadsetService != null 5095 && (device == null 5096 || mHeadsetService.getConnectionPolicy(device) 5097 == BluetoothProfile.CONNECTION_POLICY_ALLOWED); 5098 boolean leAudioSupported = 5099 mLeAudioService != null 5100 && (device == null 5101 || mLeAudioService.getConnectionPolicy(device) 5102 == BluetoothProfile.CONNECTION_POLICY_ALLOWED); 5103 5104 if (leAudioSupported) { 5105 Log.i(TAG, "setActiveDevice: Setting active Le Audio device " + device); 5106 if (device == null) { 5107 /* If called by BluetoothAdapter it means Audio should not be stopped. 5108 * For this reason let's say that fallback device exists 5109 */ 5110 mLeAudioService.removeActiveDevice(true /* hasFallbackDevice */); 5111 } else { 5112 mLeAudioService.setActiveDevice(device); 5113 } 5114 } 5115 5116 if (setA2dp && a2dpSupported) { 5117 Log.i(TAG, "setActiveDevice: Setting active A2dp device " + device); 5118 if (device == null) { 5119 mA2dpService.removeActiveDevice(false); 5120 } else { 5121 /* Workaround for the controller issue which is not able to handle correctly 5122 * A2DP offloader vendor specific command while ISO Data path is set. 5123 * Proper solutions should be delivered in b/312396770 5124 */ 5125 if (mLeAudioService != null) { 5126 List<BluetoothDevice> activeLeAudioDevices = mLeAudioService.getActiveDevices(); 5127 if (activeLeAudioDevices.get(0) != null) { 5128 mLeAudioService.removeActiveDevice(true); 5129 } 5130 } 5131 mA2dpService.setActiveDevice(device); 5132 } 5133 } 5134 5135 if (mHearingAidService != null 5136 && (device == null 5137 || mHearingAidService.getConnectionPolicy(device) 5138 == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) { 5139 Log.i(TAG, "setActiveDevice: Setting active Hearing Aid " + device); 5140 if (device == null) { 5141 mHearingAidService.removeActiveDevice(false); 5142 } else { 5143 mHearingAidService.setActiveDevice(device); 5144 } 5145 } 5146 5147 if (setHeadset && hfpSupported) { 5148 Log.i(TAG, "setActiveDevice: Setting active Headset " + device); 5149 mHeadsetService.setActiveDevice(device); 5150 } 5151 5152 return true; 5153 } 5154 5155 /** 5156 * Checks if all supported classic audio profiles are active on this LE Audio device. 5157 * 5158 * @param leAudioDevice the remote device 5159 * @return {@code true} if all supported classic audio profiles are active on this device, 5160 * {@code false} otherwise 5161 */ isAllSupportedClassicAudioProfilesActive(BluetoothDevice leAudioDevice)5162 public boolean isAllSupportedClassicAudioProfilesActive(BluetoothDevice leAudioDevice) { 5163 if (mLeAudioService == null) { 5164 return false; 5165 } 5166 boolean a2dpSupported = isProfileSupported(leAudioDevice, BluetoothProfile.A2DP); 5167 boolean hfpSupported = isProfileSupported(leAudioDevice, BluetoothProfile.HEADSET); 5168 5169 List<BluetoothDevice> groupDevices = mLeAudioService.getGroupDevices(leAudioDevice); 5170 if (hfpSupported && mHeadsetService != null) { 5171 BluetoothDevice activeHfpDevice = mHeadsetService.getActiveDevice(); 5172 if (activeHfpDevice == null || !groupDevices.contains(activeHfpDevice)) { 5173 return false; 5174 } 5175 } 5176 if (a2dpSupported && mA2dpService != null) { 5177 BluetoothDevice activeA2dpDevice = mA2dpService.getActiveDevice(); 5178 if (activeA2dpDevice == null || !groupDevices.contains(activeA2dpDevice)) { 5179 return false; 5180 } 5181 } 5182 return true; 5183 } 5184 5185 /** 5186 * Get the active devices for the BluetoothProfile specified 5187 * 5188 * @param profile is the profile from which we want the active devices. Possible values are: 5189 * {@link BluetoothProfile#HEADSET}, {@link BluetoothProfile#A2DP}, {@link 5190 * BluetoothProfile#HEARING_AID} {@link BluetoothProfile#LE_AUDIO} 5191 * @return A list of active bluetooth devices 5192 */ getActiveDevices(@ctiveDeviceProfile int profile)5193 public List<BluetoothDevice> getActiveDevices(@ActiveDeviceProfile int profile) { 5194 List<BluetoothDevice> activeDevices = new ArrayList<>(); 5195 5196 switch (profile) { 5197 case BluetoothProfile.HEADSET: 5198 if (mHeadsetService == null) { 5199 Log.e(TAG, "getActiveDevices: HeadsetService is null"); 5200 } else { 5201 BluetoothDevice device = mHeadsetService.getActiveDevice(); 5202 if (device != null) { 5203 activeDevices.add(device); 5204 } 5205 Log.i(TAG, "getActiveDevices: Headset device: " + device); 5206 } 5207 break; 5208 case BluetoothProfile.A2DP: 5209 if (mA2dpService == null) { 5210 Log.e(TAG, "getActiveDevices: A2dpService is null"); 5211 } else { 5212 BluetoothDevice device = mA2dpService.getActiveDevice(); 5213 if (device != null) { 5214 activeDevices.add(device); 5215 } 5216 Log.i(TAG, "getActiveDevices: A2dp device: " + device); 5217 } 5218 break; 5219 case BluetoothProfile.HEARING_AID: 5220 if (mHearingAidService == null) { 5221 Log.e(TAG, "getActiveDevices: HearingAidService is null"); 5222 } else { 5223 activeDevices = mHearingAidService.getActiveDevices(); 5224 Log.i( 5225 TAG, 5226 "getActiveDevices: Hearing Aid devices:" 5227 + (" Left[" + activeDevices.get(0) + "] -") 5228 + (" Right[" + activeDevices.get(1) + "]")); 5229 } 5230 break; 5231 case BluetoothProfile.LE_AUDIO: 5232 if (mLeAudioService == null) { 5233 Log.e(TAG, "getActiveDevices: LeAudioService is null"); 5234 } else { 5235 activeDevices = mLeAudioService.getActiveDevices(); 5236 Log.i( 5237 TAG, 5238 "getActiveDevices: LeAudio devices:" 5239 + (" Lead[" + activeDevices.get(0) + "] -") 5240 + (" member_1[" + activeDevices.get(1) + "]")); 5241 } 5242 break; 5243 default: 5244 Log.e(TAG, "getActiveDevices: profile value is not valid"); 5245 } 5246 return activeDevices; 5247 } 5248 5249 /** 5250 * Attempts connection to all enabled and supported bluetooth profiles between the local and 5251 * remote device 5252 * 5253 * @param device is the remote device with which to connect these profiles 5254 * @return {@link BluetoothStatusCodes#SUCCESS} if all profiles connections are attempted, false 5255 * if an error occurred 5256 */ 5257 @RequiresPermission( 5258 allOf = { 5259 android.Manifest.permission.BLUETOOTH_PRIVILEGED, 5260 android.Manifest.permission.MODIFY_PHONE_STATE, 5261 }) connectAllEnabledProfiles(BluetoothDevice device)5262 public int connectAllEnabledProfiles(BluetoothDevice device) { 5263 if (!profileServicesRunning()) { 5264 Log.e(TAG, "connectAllEnabledProfiles: Not all profile services running"); 5265 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; 5266 } 5267 5268 // Checks if any profiles are enablde or disabled and if so, only connect enabled profiles 5269 if (!isAllProfilesUnknown(device)) { 5270 return connectEnabledProfiles(device); 5271 } 5272 5273 connectAllSupportedProfiles(device); 5274 5275 return BluetoothStatusCodes.SUCCESS; 5276 } 5277 5278 /** 5279 * Connect all supported bluetooth profiles between the local and remote device 5280 * 5281 * @param device is the remote device with which to connect all supported profiles 5282 */ 5283 @RequiresPermission( 5284 allOf = { 5285 android.Manifest.permission.BLUETOOTH_PRIVILEGED, 5286 android.Manifest.permission.MODIFY_PHONE_STATE, 5287 }) connectAllSupportedProfiles(BluetoothDevice device)5288 void connectAllSupportedProfiles(BluetoothDevice device) { 5289 int numProfilesConnected = 0; 5290 5291 // All profile toggles disabled, so connects all supported profiles 5292 if (mA2dpService != null && isProfileSupported(device, BluetoothProfile.A2DP)) { 5293 Log.i(TAG, "connectAllSupportedProfiles: Connecting A2dp"); 5294 // Set connection policy also connects the profile with CONNECTION_POLICY_ALLOWED 5295 mA2dpService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); 5296 numProfilesConnected++; 5297 } 5298 if (mA2dpSinkService != null && isProfileSupported(device, BluetoothProfile.A2DP_SINK)) { 5299 Log.i(TAG, "connectAllSupportedProfiles: Connecting A2dp Sink"); 5300 mA2dpSinkService.setConnectionPolicy( 5301 device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); 5302 numProfilesConnected++; 5303 } 5304 if (mHeadsetService != null && isProfileSupported(device, BluetoothProfile.HEADSET)) { 5305 Log.i(TAG, "connectAllSupportedProfiles: Connecting Headset Profile"); 5306 mHeadsetService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); 5307 numProfilesConnected++; 5308 } 5309 if (mHeadsetClientService != null 5310 && isProfileSupported(device, BluetoothProfile.HEADSET_CLIENT)) { 5311 Log.i(TAG, "connectAllSupportedProfiles: Connecting HFP"); 5312 mHeadsetClientService.setConnectionPolicy( 5313 device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); 5314 numProfilesConnected++; 5315 } 5316 if (mMapClientService != null && isProfileSupported(device, BluetoothProfile.MAP_CLIENT)) { 5317 Log.i(TAG, "connectAllSupportedProfiles: Connecting MAP"); 5318 mMapClientService.setConnectionPolicy( 5319 device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); 5320 numProfilesConnected++; 5321 } 5322 if (mHidHostService != null && isProfileSupported(device, BluetoothProfile.HID_HOST)) { 5323 Log.i(TAG, "connectAllSupportedProfiles: Connecting Hid Host Profile"); 5324 mHidHostService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); 5325 numProfilesConnected++; 5326 } 5327 if (mPanService != null && isProfileSupported(device, BluetoothProfile.PAN)) { 5328 Log.i(TAG, "connectAllSupportedProfiles: Connecting Pan Profile"); 5329 mPanService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); 5330 numProfilesConnected++; 5331 } 5332 if (mPbapClientService != null 5333 && isProfileSupported(device, BluetoothProfile.PBAP_CLIENT)) { 5334 Log.i(TAG, "connectAllSupportedProfiles: Connecting Pbap"); 5335 mPbapClientService.setConnectionPolicy( 5336 device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); 5337 numProfilesConnected++; 5338 } 5339 if (mHearingAidService != null 5340 && isProfileSupported(device, BluetoothProfile.HEARING_AID)) { 5341 if (mHapClientService != null 5342 && isProfileSupported(device, BluetoothProfile.HAP_CLIENT)) { 5343 Log.i( 5344 TAG, 5345 "connectAllSupportedProfiles: Hearing Access Client Profile is enabled at" 5346 + " the same time with Hearing Aid Profile, ignore Hearing Aid" 5347 + " Profile"); 5348 } else { 5349 Log.i(TAG, "connectAllSupportedProfiles: Connecting Hearing Aid Profile"); 5350 mHearingAidService.setConnectionPolicy( 5351 device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); 5352 numProfilesConnected++; 5353 } 5354 } 5355 if (mHapClientService != null && isProfileSupported(device, BluetoothProfile.HAP_CLIENT)) { 5356 Log.i(TAG, "connectAllSupportedProfiles: Connecting Hearing Access Client Profile"); 5357 mHapClientService.setConnectionPolicy( 5358 device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); 5359 numProfilesConnected++; 5360 } 5361 if (mVolumeControlService != null 5362 && isProfileSupported(device, BluetoothProfile.VOLUME_CONTROL)) { 5363 Log.i(TAG, "connectAllSupportedProfiles: Connecting Volume Control Profile"); 5364 mVolumeControlService.setConnectionPolicy( 5365 device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); 5366 numProfilesConnected++; 5367 } 5368 if (mCsipSetCoordinatorService != null 5369 && isProfileSupported(device, BluetoothProfile.CSIP_SET_COORDINATOR)) { 5370 Log.i(TAG, "connectAllSupportedProfiles: Connecting Coordinated Set Profile"); 5371 mCsipSetCoordinatorService.setConnectionPolicy( 5372 device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); 5373 numProfilesConnected++; 5374 } 5375 if (mLeAudioService != null && isProfileSupported(device, BluetoothProfile.LE_AUDIO)) { 5376 Log.i(TAG, "connectAllSupportedProfiles: Connecting LeAudio profile (BAP)"); 5377 mLeAudioService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); 5378 numProfilesConnected++; 5379 } 5380 if (mBassClientService != null 5381 && isProfileSupported(device, BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT)) { 5382 Log.i(TAG, "connectAllSupportedProfiles: Connecting LE Broadcast Assistant Profile"); 5383 mBassClientService.setConnectionPolicy( 5384 device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); 5385 numProfilesConnected++; 5386 } 5387 if (mBatteryService != null && isProfileSupported(device, BluetoothProfile.BATTERY)) { 5388 Log.i(TAG, "connectAllSupportedProfiles: Connecting Battery Service"); 5389 mBatteryService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); 5390 numProfilesConnected++; 5391 } 5392 5393 Log.i( 5394 TAG, 5395 "connectAllSupportedProfiles: Number of Profiles Connected: " 5396 + numProfilesConnected); 5397 } 5398 5399 /** 5400 * Disconnects all enabled and supported bluetooth profiles between the local and remote device 5401 * 5402 * @param device is the remote device with which to disconnect these profiles 5403 * @return true if all profiles successfully disconnected, false if an error occurred 5404 */ 5405 @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) disconnectAllEnabledProfiles(BluetoothDevice device)5406 public int disconnectAllEnabledProfiles(BluetoothDevice device) { 5407 if (!profileServicesRunning()) { 5408 Log.e(TAG, "disconnectAllEnabledProfiles: Not all profile services bound"); 5409 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; 5410 } 5411 5412 if (mA2dpService != null 5413 && (mA2dpService.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED 5414 || mA2dpService.getConnectionState(device) 5415 == BluetoothProfile.STATE_CONNECTING)) { 5416 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting A2dp"); 5417 mA2dpService.disconnect(device); 5418 } 5419 if (mA2dpSinkService != null 5420 && (mA2dpSinkService.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED 5421 || mA2dpSinkService.getConnectionState(device) 5422 == BluetoothProfile.STATE_CONNECTING)) { 5423 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting A2dp Sink"); 5424 mA2dpSinkService.disconnect(device); 5425 } 5426 if (mHeadsetService != null 5427 && (mHeadsetService.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED 5428 || mHeadsetService.getConnectionState(device) 5429 == BluetoothProfile.STATE_CONNECTING)) { 5430 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Headset Profile"); 5431 mHeadsetService.disconnect(device); 5432 } 5433 if (mHeadsetClientService != null 5434 && (mHeadsetClientService.getConnectionState(device) 5435 == BluetoothProfile.STATE_CONNECTED 5436 || mHeadsetClientService.getConnectionState(device) 5437 == BluetoothProfile.STATE_CONNECTING)) { 5438 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting HFP"); 5439 mHeadsetClientService.disconnect(device); 5440 } 5441 if (mMapClientService != null 5442 && (mMapClientService.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED 5443 || mMapClientService.getConnectionState(device) 5444 == BluetoothProfile.STATE_CONNECTING)) { 5445 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting MAP Client"); 5446 mMapClientService.disconnect(device); 5447 } 5448 if (mMapService != null 5449 && (mMapService.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED 5450 || mMapService.getConnectionState(device) 5451 == BluetoothProfile.STATE_CONNECTING)) { 5452 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting MAP"); 5453 mMapService.disconnect(device); 5454 } 5455 if (mHidDeviceService != null 5456 && (mHidDeviceService.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED 5457 || mHidDeviceService.getConnectionState(device) 5458 == BluetoothProfile.STATE_CONNECTING)) { 5459 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Hid Device Profile"); 5460 mHidDeviceService.disconnect(device); 5461 } 5462 if (mHidHostService != null 5463 && (mHidHostService.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED 5464 || mHidHostService.getConnectionState(device) 5465 == BluetoothProfile.STATE_CONNECTING)) { 5466 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Hid Host Profile"); 5467 mHidHostService.disconnect(device); 5468 } 5469 if (mPanService != null 5470 && (mPanService.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED 5471 || mPanService.getConnectionState(device) 5472 == BluetoothProfile.STATE_CONNECTING)) { 5473 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Pan Profile"); 5474 mPanService.disconnect(device); 5475 } 5476 if (mPbapClientService != null 5477 && (mPbapClientService.getConnectionState(device) 5478 == BluetoothProfile.STATE_CONNECTED 5479 || mPbapClientService.getConnectionState(device) 5480 == BluetoothProfile.STATE_CONNECTING)) { 5481 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Pbap Client"); 5482 mPbapClientService.disconnect(device); 5483 } 5484 if (mPbapService != null 5485 && (mPbapService.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED 5486 || mPbapService.getConnectionState(device) 5487 == BluetoothProfile.STATE_CONNECTING)) { 5488 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Pbap Server"); 5489 mPbapService.disconnect(device); 5490 } 5491 if (mHearingAidService != null 5492 && (mHearingAidService.getConnectionState(device) 5493 == BluetoothProfile.STATE_CONNECTED 5494 || mHearingAidService.getConnectionState(device) 5495 == BluetoothProfile.STATE_CONNECTING)) { 5496 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Hearing Aid Profile"); 5497 mHearingAidService.disconnect(device); 5498 } 5499 if (mHapClientService != null 5500 && (mHapClientService.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED 5501 || mHapClientService.getConnectionState(device) 5502 == BluetoothProfile.STATE_CONNECTING)) { 5503 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Hearing Access Profile Client"); 5504 mHapClientService.disconnect(device); 5505 } 5506 if (mVolumeControlService != null 5507 && (mVolumeControlService.getConnectionState(device) 5508 == BluetoothProfile.STATE_CONNECTED 5509 || mVolumeControlService.getConnectionState(device) 5510 == BluetoothProfile.STATE_CONNECTING)) { 5511 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Volume Control Profile"); 5512 mVolumeControlService.disconnect(device); 5513 } 5514 if (mSapService != null 5515 && (mSapService.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED 5516 || mSapService.getConnectionState(device) 5517 == BluetoothProfile.STATE_CONNECTING)) { 5518 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Sap Profile"); 5519 mSapService.disconnect(device); 5520 } 5521 if (mCsipSetCoordinatorService != null 5522 && (mCsipSetCoordinatorService.getConnectionState(device) 5523 == BluetoothProfile.STATE_CONNECTED 5524 || mCsipSetCoordinatorService.getConnectionState(device) 5525 == BluetoothProfile.STATE_CONNECTING)) { 5526 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Coordinater Set Profile"); 5527 mCsipSetCoordinatorService.disconnect(device); 5528 } 5529 if (mLeAudioService != null 5530 && (mLeAudioService.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED 5531 || mLeAudioService.getConnectionState(device) 5532 == BluetoothProfile.STATE_CONNECTING)) { 5533 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting LeAudio profile (BAP)"); 5534 mLeAudioService.disconnect(device); 5535 } 5536 if (mBassClientService != null 5537 && (mBassClientService.getConnectionState(device) 5538 == BluetoothProfile.STATE_CONNECTED 5539 || mBassClientService.getConnectionState(device) 5540 == BluetoothProfile.STATE_CONNECTING)) { 5541 Log.i( 5542 TAG, 5543 "disconnectAllEnabledProfiles: Disconnecting " 5544 + "LE Broadcast Assistant Profile"); 5545 mBassClientService.disconnect(device); 5546 } 5547 if (mBatteryService != null 5548 && (mBatteryService.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED 5549 || mBatteryService.getConnectionState(device) 5550 == BluetoothProfile.STATE_CONNECTING)) { 5551 Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting " + "Battery Service"); 5552 mBatteryService.disconnect(device); 5553 } 5554 5555 return BluetoothStatusCodes.SUCCESS; 5556 } 5557 5558 /** 5559 * Same as API method {@link BluetoothDevice#getName()} 5560 * 5561 * @param device remote device of interest 5562 * @return remote device name 5563 */ getRemoteName(BluetoothDevice device)5564 public String getRemoteName(BluetoothDevice device) { 5565 if (mRemoteDevices == null) { 5566 return null; 5567 } 5568 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 5569 if (deviceProp == null) { 5570 return null; 5571 } 5572 return deviceProp.getName(); 5573 } 5574 5575 /** 5576 * Get UUIDs for service supported by a remote device 5577 * 5578 * @param device the remote device that we want to get UUIDs from 5579 * @return the uuids of the remote device 5580 */ getRemoteUuids(BluetoothDevice device)5581 public ParcelUuid[] getRemoteUuids(BluetoothDevice device) { 5582 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 5583 if (deviceProp == null) { 5584 return null; 5585 } 5586 return deviceProp.getUuids(); 5587 } 5588 getBluetoothConnectionCallbacks()5589 public Set<IBluetoothConnectionCallback> getBluetoothConnectionCallbacks() { 5590 return mBluetoothConnectionCallbacks; 5591 } 5592 5593 /** 5594 * Converts HCI disconnect reasons to Android disconnect reasons. 5595 * 5596 * <p>The HCI Error Codes used for ACL disconnect reasons propagated up from native code were 5597 * copied from: packages/modules/Bluetooth/system/stack/include/hci_error_code.h 5598 * 5599 * <p>These error codes are specified and described in Bluetooth Core Spec v5.1, Vol 2, Part D. 5600 * 5601 * @param hciReason is the raw HCI disconnect reason from native. 5602 * @return the Android disconnect reason for apps. 5603 */ 5604 static @BluetoothAdapter.BluetoothConnectionCallback.DisconnectReason int hciToAndroidDisconnectReason(int hciReason)5605 hciToAndroidDisconnectReason(int hciReason) { 5606 switch (hciReason) { 5607 case /*HCI_SUCCESS*/ 0x00: 5608 case /*HCI_ERR_UNSPECIFIED*/ 0x1F: 5609 case /*HCI_ERR_UNDEFINED*/ 0xff: 5610 return BluetoothStatusCodes.ERROR_UNKNOWN; 5611 case /*HCI_ERR_ILLEGAL_COMMAND*/ 0x01: 5612 case /*HCI_ERR_NO_CONNECTION*/ 0x02: 5613 case /*HCI_ERR_HW_FAILURE*/ 0x03: 5614 case /*HCI_ERR_DIFF_TRANSACTION_COLLISION*/ 0x2A: 5615 case /*HCI_ERR_ROLE_SWITCH_PENDING*/ 0x32: 5616 case /*HCI_ERR_ROLE_SWITCH_FAILED*/ 0x35: 5617 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_LOCAL; 5618 case /*HCI_ERR_PAGE_TIMEOUT*/ 0x04: 5619 case /*HCI_ERR_CONNECTION_TOUT*/ 0x08: 5620 case /*HCI_ERR_HOST_TIMEOUT*/ 0x10: 5621 case /*HCI_ERR_LMP_RESPONSE_TIMEOUT*/ 0x22: 5622 case /*HCI_ERR_ADVERTISING_TIMEOUT*/ 0x3C: 5623 case /*HCI_ERR_CONN_FAILED_ESTABLISHMENT*/ 0x3E: 5624 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_TIMEOUT; 5625 case /*HCI_ERR_AUTH_FAILURE*/ 0x05: 5626 case /*HCI_ERR_KEY_MISSING*/ 0x06: 5627 case /*HCI_ERR_HOST_REJECT_SECURITY*/ 0x0E: 5628 case /*HCI_ERR_REPEATED_ATTEMPTS*/ 0x17: 5629 case /*HCI_ERR_PAIRING_NOT_ALLOWED*/ 0x18: 5630 case /*HCI_ERR_ENCRY_MODE_NOT_ACCEPTABLE*/ 0x25: 5631 case /*HCI_ERR_UNIT_KEY_USED*/ 0x26: 5632 case /*HCI_ERR_PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED*/ 0x29: 5633 case /*HCI_ERR_INSUFFCIENT_SECURITY*/ 0x2F: 5634 case /*HCI_ERR_HOST_BUSY_PAIRING*/ 0x38: 5635 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_SECURITY; 5636 case /*HCI_ERR_MEMORY_FULL*/ 0x07: 5637 case /*HCI_ERR_MAX_NUM_OF_CONNECTIONS*/ 0x09: 5638 case /*HCI_ERR_MAX_NUM_OF_SCOS*/ 0x0A: 5639 case /*HCI_ERR_COMMAND_DISALLOWED*/ 0x0C: 5640 case /*HCI_ERR_HOST_REJECT_RESOURCES*/ 0x0D: 5641 case /*HCI_ERR_LIMIT_REACHED*/ 0x43: 5642 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_RESOURCE_LIMIT_REACHED; 5643 case /*HCI_ERR_CONNECTION_EXISTS*/ 0x0B: 5644 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_CONNECTION_ALREADY_EXISTS; 5645 case /*HCI_ERR_HOST_REJECT_DEVICE*/ 0x0F: 5646 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_SYSTEM_POLICY; 5647 case /*HCI_ERR_ILLEGAL_PARAMETER_FMT*/ 0x12: 5648 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_BAD_PARAMETERS; 5649 case /*HCI_ERR_PEER_USER*/ 0x13: 5650 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_REMOTE_REQUEST; 5651 case /*HCI_ERR_REMOTE_POWER_OFF*/ 0x15: 5652 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_REMOTE_REQUEST; 5653 case /*HCI_ERR_CONN_CAUSE_LOCAL_HOST*/ 0x16: 5654 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_LOCAL_REQUEST; 5655 case /*HCI_ERR_UNSUPPORTED_REM_FEATURE*/ 0x1A: 5656 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_REMOTE; 5657 case /*HCI_ERR_UNACCEPT_CONN_INTERVAL*/ 0x3B: 5658 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_BAD_PARAMETERS; 5659 default: 5660 Log.e(TAG, "Invalid HCI disconnect reason: " + hciReason); 5661 return BluetoothStatusCodes.ERROR_UNKNOWN; 5662 } 5663 } 5664 logUserBondResponse(BluetoothDevice device, boolean accepted, int event)5665 void logUserBondResponse(BluetoothDevice device, boolean accepted, int event) { 5666 final long token = Binder.clearCallingIdentity(); 5667 try { 5668 BluetoothStatsLog.write( 5669 BluetoothStatsLog.BLUETOOTH_BOND_STATE_CHANGED, 5670 obfuscateAddress(device), 5671 0, 5672 device.getType(), 5673 BluetoothDevice.BOND_BONDING, 5674 event, 5675 accepted ? 0 : BluetoothDevice.UNBOND_REASON_AUTH_REJECTED); 5676 } finally { 5677 Binder.restoreCallingIdentity(token); 5678 } 5679 } 5680 getDeviceAccessFromPrefs(BluetoothDevice device, String prefFile)5681 int getDeviceAccessFromPrefs(BluetoothDevice device, String prefFile) { 5682 SharedPreferences prefs = getSharedPreferences(prefFile, Context.MODE_PRIVATE); 5683 if (!prefs.contains(device.getAddress())) { 5684 return BluetoothDevice.ACCESS_UNKNOWN; 5685 } 5686 return prefs.getBoolean(device.getAddress(), false) 5687 ? BluetoothDevice.ACCESS_ALLOWED 5688 : BluetoothDevice.ACCESS_REJECTED; 5689 } 5690 setDeviceAccessFromPrefs(BluetoothDevice device, int value, String prefFile)5691 void setDeviceAccessFromPrefs(BluetoothDevice device, int value, String prefFile) { 5692 SharedPreferences pref = getSharedPreferences(prefFile, Context.MODE_PRIVATE); 5693 SharedPreferences.Editor editor = pref.edit(); 5694 if (value == BluetoothDevice.ACCESS_UNKNOWN) { 5695 editor.remove(device.getAddress()); 5696 } else { 5697 editor.putBoolean(device.getAddress(), value == BluetoothDevice.ACCESS_ALLOWED); 5698 } 5699 editor.apply(); 5700 } 5701 setPhonebookAccessPermission(BluetoothDevice device, int value)5702 public void setPhonebookAccessPermission(BluetoothDevice device, int value) { 5703 setDeviceAccessFromPrefs(device, value, PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE); 5704 } 5705 setMessageAccessPermission(BluetoothDevice device, int value)5706 public void setMessageAccessPermission(BluetoothDevice device, int value) { 5707 setDeviceAccessFromPrefs(device, value, MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE); 5708 } 5709 setSimAccessPermission(BluetoothDevice device, int value)5710 public void setSimAccessPermission(BluetoothDevice device, int value) { 5711 setDeviceAccessFromPrefs(device, value, SIM_ACCESS_PERMISSION_PREFERENCE_FILE); 5712 } 5713 isRpaOffloadSupported()5714 public boolean isRpaOffloadSupported() { 5715 return mAdapterProperties.isRpaOffloadSupported(); 5716 } 5717 getNumOfOffloadedIrkSupported()5718 public int getNumOfOffloadedIrkSupported() { 5719 return mAdapterProperties.getNumOfOffloadedIrkSupported(); 5720 } 5721 getNumOfOffloadedScanFilterSupported()5722 public int getNumOfOffloadedScanFilterSupported() { 5723 return mAdapterProperties.getNumOfOffloadedScanFilterSupported(); 5724 } 5725 getOffloadedScanResultStorage()5726 public int getOffloadedScanResultStorage() { 5727 return mAdapterProperties.getOffloadedScanResultStorage(); 5728 } 5729 isLe2MPhySupported()5730 public boolean isLe2MPhySupported() { 5731 return mAdapterProperties.isLe2MPhySupported(); 5732 } 5733 isLeCodedPhySupported()5734 public boolean isLeCodedPhySupported() { 5735 return mAdapterProperties.isLeCodedPhySupported(); 5736 } 5737 isLeExtendedAdvertisingSupported()5738 public boolean isLeExtendedAdvertisingSupported() { 5739 return mAdapterProperties.isLeExtendedAdvertisingSupported(); 5740 } 5741 isLePeriodicAdvertisingSupported()5742 public boolean isLePeriodicAdvertisingSupported() { 5743 return mAdapterProperties.isLePeriodicAdvertisingSupported(); 5744 } 5745 5746 /** 5747 * Check if the LE audio broadcast source feature is supported. 5748 * 5749 * @return true, if the LE audio broadcast source is supported 5750 */ isLeAudioBroadcastSourceSupported()5751 public boolean isLeAudioBroadcastSourceSupported() { 5752 return mAdapterProperties.isLePeriodicAdvertisingSupported() 5753 && mAdapterProperties.isLeExtendedAdvertisingSupported() 5754 && mAdapterProperties.isLeIsochronousBroadcasterSupported(); 5755 } 5756 5757 /** 5758 * Check if the LE audio broadcast assistant feature is supported. 5759 * 5760 * @return true, if the LE audio broadcast assistant is supported 5761 */ isLeAudioBroadcastAssistantSupported()5762 public boolean isLeAudioBroadcastAssistantSupported() { 5763 return mAdapterProperties.isLePeriodicAdvertisingSupported() 5764 && mAdapterProperties.isLeExtendedAdvertisingSupported() 5765 && (mAdapterProperties.isLePeriodicAdvertisingSyncTransferSenderSupported() 5766 || mAdapterProperties 5767 .isLePeriodicAdvertisingSyncTransferRecipientSupported()); 5768 } 5769 5770 /** 5771 * Check if the LE channel sounding feature is supported. 5772 * 5773 * @return true, if the LE channel sounding is supported 5774 */ isLeChannelSoundingSupported()5775 public boolean isLeChannelSoundingSupported() { 5776 return mAdapterProperties.isLeChannelSoundingSupported(); 5777 } 5778 getSupportedProfilesBitMask()5779 public long getSupportedProfilesBitMask() { 5780 return Config.getSupportedProfilesBitMask(); 5781 } 5782 5783 /** 5784 * Check if the LE audio CIS central feature is supported. 5785 * 5786 * @return true, if the LE audio CIS central is supported 5787 */ isLeConnectedIsochronousStreamCentralSupported()5788 public boolean isLeConnectedIsochronousStreamCentralSupported() { 5789 return mAdapterProperties.isLeConnectedIsochronousStreamCentralSupported(); 5790 } 5791 getLeMaximumAdvertisingDataLength()5792 public int getLeMaximumAdvertisingDataLength() { 5793 return mAdapterProperties.getLeMaximumAdvertisingDataLength(); 5794 } 5795 5796 /** 5797 * Get the maximum number of connected audio devices. 5798 * 5799 * @return the maximum number of connected audio devices 5800 */ getMaxConnectedAudioDevices()5801 public int getMaxConnectedAudioDevices() { 5802 return mAdapterProperties.getMaxConnectedAudioDevices(); 5803 } 5804 5805 /** 5806 * Check whether A2DP offload is enabled. 5807 * 5808 * @return true if A2DP offload is enabled 5809 */ isA2dpOffloadEnabled()5810 public boolean isA2dpOffloadEnabled() { 5811 return mAdapterProperties.isA2dpOffloadEnabled(); 5812 } 5813 5814 /** Register a bluetooth state callback */ registerBluetoothStateCallback(Executor executor, BluetoothStateCallback callback)5815 public void registerBluetoothStateCallback(Executor executor, BluetoothStateCallback callback) { 5816 mLocalCallbacks.put(callback, executor); 5817 } 5818 5819 /** Unregister a bluetooth state callback */ unregisterBluetoothStateCallback(BluetoothStateCallback callback)5820 public void unregisterBluetoothStateCallback(BluetoothStateCallback callback) { 5821 mLocalCallbacks.remove(callback); 5822 } 5823 5824 @VisibleForTesting registerRemoteCallback(IBluetoothCallback callback)5825 void registerRemoteCallback(IBluetoothCallback callback) { 5826 mRemoteCallbacks.register(callback); 5827 } 5828 5829 @VisibleForTesting unregisterRemoteCallback(IBluetoothCallback callback)5830 void unregisterRemoteCallback(IBluetoothCallback callback) { 5831 mRemoteCallbacks.unregister(callback); 5832 } 5833 5834 @VisibleForTesting startBrEdr()5835 void startBrEdr() { 5836 mAdapterStateMachine.sendMessage(AdapterState.USER_TURN_ON); 5837 } 5838 5839 @VisibleForTesting stopBle()5840 void stopBle() { 5841 mAdapterStateMachine.sendMessage(AdapterState.BLE_TURN_OFF); 5842 } 5843 5844 @VisibleForTesting factoryReset()5845 boolean factoryReset() { 5846 mDatabaseManager.factoryReset(); 5847 5848 if (mBluetoothKeystoreService != null) { 5849 mBluetoothKeystoreService.factoryReset(); 5850 } 5851 5852 if (mBtCompanionManager != null) { 5853 mBtCompanionManager.factoryReset(); 5854 } 5855 5856 return mNativeInterface.factoryReset(); 5857 } 5858 5859 @VisibleForTesting getScanMode()5860 int getScanMode() { 5861 return mAdapterProperties.getScanMode(); 5862 } 5863 5864 @VisibleForTesting reportActivityInfo()5865 BluetoothActivityEnergyInfo reportActivityInfo() { 5866 if (mAdapterProperties.getState() != BluetoothAdapter.STATE_ON 5867 || !mAdapterProperties.isActivityAndEnergyReportingSupported()) { 5868 return null; 5869 } 5870 5871 // Pull the data. The callback will notify mEnergyInfoLock. 5872 mNativeInterface.readEnergyInfo(); 5873 5874 synchronized (mEnergyInfoLock) { 5875 long now = System.currentTimeMillis(); 5876 final long deadline = now + CONTROLLER_ENERGY_UPDATE_TIMEOUT_MILLIS; 5877 while (now < deadline) { 5878 try { 5879 mEnergyInfoLock.wait(deadline - now); 5880 break; 5881 } catch (InterruptedException e) { 5882 now = System.currentTimeMillis(); 5883 } 5884 } 5885 5886 final BluetoothActivityEnergyInfo info = 5887 new BluetoothActivityEnergyInfo( 5888 SystemClock.elapsedRealtime(), 5889 mStackReportedState, 5890 mTxTimeTotalMs, 5891 mRxTimeTotalMs, 5892 mIdleTimeTotalMs, 5893 mEnergyUsedTotalVoltAmpSecMicro); 5894 5895 // Copy the traffic objects whose byte counts are > 0 5896 final List<UidTraffic> result = new ArrayList<>(); 5897 for (int i = 0; i < mUidTraffic.size(); i++) { 5898 final UidTraffic traffic = mUidTraffic.valueAt(i); 5899 if (traffic.getTxBytes() != 0 || traffic.getRxBytes() != 0) { 5900 result.add(traffic.clone()); 5901 } 5902 } 5903 5904 info.setUidTraffic(result); 5905 5906 return info; 5907 } 5908 } 5909 getTotalNumOfTrackableAdvertisements()5910 public int getTotalNumOfTrackableAdvertisements() { 5911 return mAdapterProperties.getTotalNumOfTrackableAdvertisements(); 5912 } 5913 5914 /** 5915 * Return if offloaded TDS filter is supported. 5916 * 5917 * @return {@code BluetoothStatusCodes.FEATURE_SUPPORTED} if supported 5918 */ getOffloadedTransportDiscoveryDataScanSupported()5919 public int getOffloadedTransportDiscoveryDataScanSupported() { 5920 if (mAdapterProperties.isOffloadedTransportDiscoveryDataScanSupported()) { 5921 return BluetoothStatusCodes.FEATURE_SUPPORTED; 5922 } 5923 return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED; 5924 } 5925 getBluetoothGatt()5926 IBinder getBluetoothGatt() { 5927 return mGattService == null ? null : mGattService.getBinder(); 5928 } 5929 getBluetoothScan()5930 IBinder getBluetoothScan() { 5931 return mScanController == null ? null : mScanController.getBinder(); 5932 } 5933 unregAllGattClient(AttributionSource source)5934 void unregAllGattClient(AttributionSource source) { 5935 if (mGattService != null) { 5936 mGattService.unregAll(source); 5937 } 5938 } 5939 getProfile(int profileId)5940 IBinder getProfile(int profileId) { 5941 if (getState() == BluetoothAdapter.STATE_TURNING_ON) { 5942 return null; 5943 } 5944 5945 // LE_AUDIO_BROADCAST is not associated with a service and use LE_AUDIO's Binder 5946 if (profileId == BluetoothProfile.LE_AUDIO_BROADCAST) { 5947 profileId = BluetoothProfile.LE_AUDIO; 5948 } 5949 5950 ProfileService profile = mStartedProfiles.get(profileId); 5951 if (profile != null) { 5952 return profile.getBinder(); 5953 } else { 5954 return null; 5955 } 5956 } 5957 isMediaProfileConnected()5958 boolean isMediaProfileConnected() { 5959 if (mA2dpService != null && mA2dpService.getConnectedDevices().size() > 0) { 5960 Log.d(TAG, "isMediaProfileConnected. A2dp is connected"); 5961 return true; 5962 } else if (mHearingAidService != null 5963 && mHearingAidService.getConnectedDevices().size() > 0) { 5964 Log.d(TAG, "isMediaProfileConnected. HearingAid is connected"); 5965 return true; 5966 } else if (mLeAudioService != null && mLeAudioService.getConnectedDevices().size() > 0) { 5967 Log.d(TAG, "isMediaProfileConnected. LeAudio is connected"); 5968 return true; 5969 } else { 5970 Log.d( 5971 TAG, 5972 "isMediaProfileConnected: no Media connected." 5973 + (" A2dp=" + mA2dpService) 5974 + (" HearingAid=" + mHearingAidService) 5975 + (" LeAudio=" + mLeAudioService)); 5976 return false; 5977 } 5978 } 5979 5980 /** Update PhonePolicy when new {@link BluetoothDevice} creates an ACL connection. */ updatePhonePolicyOnAclConnect(BluetoothDevice device)5981 public void updatePhonePolicyOnAclConnect(BluetoothDevice device) { 5982 if (mPhonePolicy != null) { 5983 mPhonePolicy.handleAclConnected(device); 5984 } 5985 } 5986 5987 /** 5988 * Notify {@link BluetoothProfile} when ACL connection disconnects from {@link BluetoothDevice} 5989 * for a given {@code transport}. 5990 */ notifyAclDisconnected(BluetoothDevice device, int transport)5991 public void notifyAclDisconnected(BluetoothDevice device, int transport) { 5992 if (mMapService != null && mMapService.isAvailable()) { 5993 mMapService.aclDisconnected(device); 5994 } 5995 if (mMapClientService != null && mMapClientService.isAvailable()) { 5996 mMapClientService.aclDisconnected(device, transport); 5997 } 5998 if (mSapService != null && mSapService.isAvailable()) { 5999 mSapService.aclDisconnected(device); 6000 } 6001 if (mPbapClientService != null && mPbapClientService.isAvailable()) { 6002 mPbapClientService.aclDisconnected(device, transport); 6003 } 6004 } 6005 6006 /** 6007 * Notify GATT of a Bluetooth profile's connection state change for a given {@link 6008 * BluetoothProfile}. 6009 */ notifyProfileConnectionStateChangeToGatt(int profile, int fromState, int toState)6010 public void notifyProfileConnectionStateChangeToGatt(int profile, int fromState, int toState) { 6011 if (mGattService == null) { 6012 Log.w(TAG, "GATT Service is not running!"); 6013 return; 6014 } 6015 if (Flags.scanManagerRefactor()) { 6016 mScanController.notifyProfileConnectionStateChange(profile, fromState, toState); 6017 } else { 6018 mGattService.notifyProfileConnectionStateChange(profile, fromState, toState); 6019 } 6020 } 6021 6022 /** 6023 * Handle Bluetooth app state when connection state changes for a given {@code profile}. 6024 * 6025 * <p>Currently this function is limited to handling Phone policy but the eventual goal is to 6026 * move all connection logic here. 6027 */ handleProfileConnectionStateChange( int profile, BluetoothDevice device, int fromState, int toState)6028 public void handleProfileConnectionStateChange( 6029 int profile, BluetoothDevice device, int fromState, int toState) { 6030 if (mPhonePolicy != null) { 6031 mPhonePolicy.profileConnectionStateChanged(profile, device, fromState, toState); 6032 } 6033 } 6034 6035 /** Handle Bluetooth app state when active device changes for a given {@code profile}. */ handleActiveDeviceChange(int profile, BluetoothDevice device)6036 public void handleActiveDeviceChange(int profile, BluetoothDevice device) { 6037 mActiveDeviceManager.profileActiveDeviceChanged(profile, device); 6038 mSilenceDeviceManager.profileActiveDeviceChanged(profile, device); 6039 if (mPhonePolicy != null) { 6040 mPhonePolicy.profileActiveDeviceChanged(profile, device); 6041 } 6042 } 6043 6044 /** Notify MAP and Pbap when a new sdp search record is found. */ sendSdpSearchRecord( BluetoothDevice device, int status, Parcelable record, ParcelUuid uuid)6045 public void sendSdpSearchRecord( 6046 BluetoothDevice device, int status, Parcelable record, ParcelUuid uuid) { 6047 if (mMapService != null && mMapService.isAvailable()) { 6048 mMapService.receiveSdpSearchRecord(status, record, uuid); 6049 } 6050 if (mMapClientService != null && mMapClientService.isAvailable()) { 6051 mMapClientService.receiveSdpSearchRecord(device, status, record, uuid); 6052 } 6053 if (mPbapClientService != null && mPbapClientService.isAvailable()) { 6054 mPbapClientService.receiveSdpSearchRecord(device, status, record, uuid); 6055 } 6056 } 6057 6058 /** Handle Bluetooth profiles when bond state changes with a {@link BluetoothDevice} */ handleBondStateChanged(BluetoothDevice device, int fromState, int toState)6059 public void handleBondStateChanged(BluetoothDevice device, int fromState, int toState) { 6060 if (mA2dpService != null && mA2dpService.isAvailable()) { 6061 mA2dpService.handleBondStateChanged(device, fromState, toState); 6062 } 6063 if (mHeadsetService != null && mHeadsetService.isAvailable()) { 6064 mHeadsetService.handleBondStateChanged(device, fromState, toState); 6065 } 6066 if (mLeAudioService != null && mLeAudioService.isAvailable()) { 6067 mLeAudioService.handleBondStateChanged(device, fromState, toState); 6068 } 6069 if (mHearingAidService != null && mHearingAidService.isAvailable()) { 6070 mHearingAidService.handleBondStateChanged(device, fromState, toState); 6071 } 6072 if (mHapClientService != null && mHapClientService.isAvailable()) { 6073 mHapClientService.handleBondStateChanged(device, fromState, toState); 6074 } 6075 if (mBassClientService != null && mBassClientService.isAvailable()) { 6076 mBassClientService.handleBondStateChanged(device, fromState, toState); 6077 } 6078 if (mBatteryService != null && mBatteryService.isAvailable()) { 6079 mBatteryService.handleBondStateChanged(device, fromState, toState); 6080 } 6081 if (mVolumeControlService != null && mVolumeControlService.isAvailable()) { 6082 mVolumeControlService.handleBondStateChanged(device, fromState, toState); 6083 } 6084 if (mPbapService != null && mPbapService.isAvailable()) { 6085 mPbapService.handleBondStateChanged(device, fromState, toState); 6086 } 6087 if (mCsipSetCoordinatorService != null && mCsipSetCoordinatorService.isAvailable()) { 6088 mCsipSetCoordinatorService.handleBondStateChanged(device, fromState, toState); 6089 } 6090 mDatabaseManager.handleBondStateChanged(device, fromState, toState); 6091 } 6092 convertScanModeToHal(int mode)6093 static int convertScanModeToHal(int mode) { 6094 switch (mode) { 6095 case BluetoothAdapter.SCAN_MODE_NONE: 6096 return AbstractionLayer.BT_SCAN_MODE_NONE; 6097 case BluetoothAdapter.SCAN_MODE_CONNECTABLE: 6098 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE; 6099 case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE: 6100 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE; 6101 } 6102 // Log.e(TAG, "Incorrect scan mode in convertScanModeToHal"); 6103 return -1; 6104 } 6105 convertScanModeFromHal(int mode)6106 static int convertScanModeFromHal(int mode) { 6107 switch (mode) { 6108 case AbstractionLayer.BT_SCAN_MODE_NONE: 6109 return BluetoothAdapter.SCAN_MODE_NONE; 6110 case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE: 6111 return BluetoothAdapter.SCAN_MODE_CONNECTABLE; 6112 case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE: 6113 return BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE; 6114 } 6115 // Log.e(TAG, "Incorrect scan mode in convertScanModeFromHal"); 6116 return -1; 6117 } 6118 6119 // This function is called from JNI. It allows native code to acquire a single wake lock. 6120 // If the wake lock is already held, this function returns success. Although this function 6121 // only supports acquiring a single wake lock at a time right now, it will eventually be 6122 // extended to allow acquiring an arbitrary number of wake locks. The current interface 6123 // takes |lockName| as a parameter in anticipation of that implementation. acquireWakeLock(String lockName)6124 boolean acquireWakeLock(String lockName) { 6125 synchronized (this) { 6126 if (mWakeLock == null) { 6127 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, lockName); 6128 } 6129 6130 if (!mWakeLock.isHeld()) { 6131 mWakeLock.acquire(); 6132 } 6133 } 6134 return true; 6135 } 6136 6137 // This function is called from JNI. It allows native code to release a wake lock acquired 6138 // by |acquireWakeLock|. If the wake lock is not held, this function returns failure. 6139 // Note that the release() call is also invoked by {@link #cleanup()} so a synchronization is 6140 // needed here. See the comment for |acquireWakeLock| for an explanation of the interface. releaseWakeLock(String lockName)6141 boolean releaseWakeLock(String lockName) { 6142 synchronized (this) { 6143 if (mWakeLock == null) { 6144 Log.e(TAG, "Repeated wake lock release; aborting release: " + lockName); 6145 return false; 6146 } 6147 6148 if (mWakeLock.isHeld()) { 6149 mWakeLock.release(); 6150 } 6151 } 6152 return true; 6153 } 6154 energyInfoCallbackInternal( int status, int ctrlState, long txTime, long rxTime, long idleTime, long energyUsed, UidTraffic[] data)6155 void energyInfoCallbackInternal( 6156 int status, 6157 int ctrlState, 6158 long txTime, 6159 long rxTime, 6160 long idleTime, 6161 long energyUsed, 6162 UidTraffic[] data) { 6163 // Energy is product of mA, V and ms. If the chipset doesn't 6164 // report it, we have to compute it from time 6165 if (energyUsed == 0) { 6166 try { 6167 final long txMah = Math.multiplyExact(txTime, getTxCurrentMa()); 6168 final long rxMah = Math.multiplyExact(rxTime, getRxCurrentMa()); 6169 final long idleMah = Math.multiplyExact(idleTime, getIdleCurrentMa()); 6170 energyUsed = 6171 (long) 6172 (Math.addExact(Math.addExact(txMah, rxMah), idleMah) 6173 * getOperatingVolt()); 6174 } catch (ArithmeticException e) { 6175 Log.wtf(TAG, "overflow in bluetooth energy callback", e); 6176 // Energy is already 0 if the exception was thrown. 6177 } 6178 } 6179 6180 synchronized (mEnergyInfoLock) { 6181 mStackReportedState = ctrlState; 6182 long totalTxTimeMs; 6183 long totalRxTimeMs; 6184 long totalIdleTimeMs; 6185 long totalEnergy; 6186 try { 6187 totalTxTimeMs = Math.addExact(mTxTimeTotalMs, txTime); 6188 totalRxTimeMs = Math.addExact(mRxTimeTotalMs, rxTime); 6189 totalIdleTimeMs = Math.addExact(mIdleTimeTotalMs, idleTime); 6190 totalEnergy = Math.addExact(mEnergyUsedTotalVoltAmpSecMicro, energyUsed); 6191 } catch (ArithmeticException e) { 6192 // This could be because we accumulated a lot of time, or we got a very strange 6193 // value from the controller (more likely). Discard this data. 6194 Log.wtf(TAG, "overflow in bluetooth energy callback", e); 6195 totalTxTimeMs = mTxTimeTotalMs; 6196 totalRxTimeMs = mRxTimeTotalMs; 6197 totalIdleTimeMs = mIdleTimeTotalMs; 6198 totalEnergy = mEnergyUsedTotalVoltAmpSecMicro; 6199 } 6200 6201 mTxTimeTotalMs = totalTxTimeMs; 6202 mRxTimeTotalMs = totalRxTimeMs; 6203 mIdleTimeTotalMs = totalIdleTimeMs; 6204 mEnergyUsedTotalVoltAmpSecMicro = totalEnergy; 6205 6206 for (UidTraffic traffic : data) { 6207 UidTraffic existingTraffic = mUidTraffic.get(traffic.getUid()); 6208 if (existingTraffic == null) { 6209 mUidTraffic.put(traffic.getUid(), traffic); 6210 } else { 6211 existingTraffic.addRxBytes(traffic.getRxBytes()); 6212 existingTraffic.addTxBytes(traffic.getTxBytes()); 6213 } 6214 } 6215 mEnergyInfoLock.notifyAll(); 6216 } 6217 } 6218 energyInfoCallback( int status, int ctrlState, long txTime, long rxTime, long idleTime, long energyUsed, UidTraffic[] data)6219 void energyInfoCallback( 6220 int status, 6221 int ctrlState, 6222 long txTime, 6223 long rxTime, 6224 long idleTime, 6225 long energyUsed, 6226 UidTraffic[] data) { 6227 if (Flags.btSystemContextReport()) { 6228 energyInfoCallbackInternal( 6229 status, ctrlState, txTime, rxTime, idleTime, energyUsed, data); 6230 } else if (ctrlState >= BluetoothActivityEnergyInfo.BT_STACK_STATE_INVALID 6231 && ctrlState <= BluetoothActivityEnergyInfo.BT_STACK_STATE_STATE_IDLE) { 6232 energyInfoCallbackInternal( 6233 status, ctrlState, txTime, rxTime, idleTime, energyUsed, data); 6234 } 6235 Log.v( 6236 TAG, 6237 "energyInfoCallback()" 6238 + (" status = " + status) 6239 + (" txTime = " + txTime) 6240 + (" rxTime = " + rxTime) 6241 + (" idleTime = " + idleTime) 6242 + (" energyUsed = " + energyUsed) 6243 + (" ctrlState = " + String.format("0x%08x", ctrlState)) 6244 + (" traffic = " + Arrays.toString(data))); 6245 } 6246 6247 /** Update metadata change to registered listeners */ 6248 @VisibleForTesting metadataChanged(String address, int key, byte[] value)6249 public void metadataChanged(String address, int key, byte[] value) { 6250 BluetoothDevice device = mRemoteDevices.getDevice(Utils.getBytesFromAddress(address)); 6251 6252 // pass just interesting metadata to native, to reduce spam 6253 if (key == BluetoothDevice.METADATA_LE_AUDIO) { 6254 mNativeInterface.metadataChanged(Utils.getBytesFromAddress(address), key, value); 6255 } 6256 6257 if (mMetadataListeners.containsKey(device)) { 6258 List<IBluetoothMetadataListener> list = mMetadataListeners.get(device); 6259 for (IBluetoothMetadataListener listener : list) { 6260 try { 6261 listener.onMetadataChanged(device, key, value); 6262 } catch (RemoteException e) { 6263 Log.w(TAG, "RemoteException when onMetadataChanged"); 6264 } 6265 } 6266 } 6267 } 6268 getIdleCurrentMa()6269 private int getIdleCurrentMa() { 6270 return BluetoothProperties.getHardwareIdleCurrentMa().orElse(0); 6271 } 6272 getTxCurrentMa()6273 private int getTxCurrentMa() { 6274 return BluetoothProperties.getHardwareTxCurrentMa().orElse(0); 6275 } 6276 getRxCurrentMa()6277 private int getRxCurrentMa() { 6278 return BluetoothProperties.getHardwareRxCurrentMa().orElse(0); 6279 } 6280 getOperatingVolt()6281 private double getOperatingVolt() { 6282 return BluetoothProperties.getHardwareOperatingVoltageMv().orElse(0) / 1000.0; 6283 } 6284 getRemoteDevices()6285 public RemoteDevices getRemoteDevices() { 6286 return mRemoteDevices; 6287 } 6288 6289 @Override dump(FileDescriptor fd, PrintWriter writer, String[] args)6290 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 6291 if (args.length == 0) { 6292 writer.println("Skipping dump in APP SERVICES, see bluetooth_manager section."); 6293 writer.println("Use --print argument for dumpsys direct from AdapterService."); 6294 return; 6295 } 6296 6297 if ("set-test-mode".equals(args[0])) { 6298 final boolean testModeEnabled = "enabled".equalsIgnoreCase(args[1]); 6299 for (ProfileService profile : mRunningProfiles) { 6300 profile.setTestModeEnabled(testModeEnabled); 6301 } 6302 mTestModeEnabled = testModeEnabled; 6303 return; 6304 } 6305 6306 Log.v(TAG, "dumpsys arguments, check for protobuf output: " + TextUtils.join(" ", args)); 6307 if (args[0].equals("--proto-bin")) { 6308 dumpMetrics(fd); 6309 return; 6310 } 6311 6312 writer.println(); 6313 mAdapterProperties.dump(fd, writer, args); 6314 writer.println("sSnoopLogSettingAtEnable = " + sSnoopLogSettingAtEnable); 6315 writer.println("sDefaultSnoopLogSettingAtEnable = " + sDefaultSnoopLogSettingAtEnable); 6316 6317 writer.println(); 6318 writer.println("Enabled Profile Services:"); 6319 for (int profileId : Config.getSupportedProfiles()) { 6320 writer.println(" " + BluetoothProfile.getProfileName(profileId)); 6321 } 6322 writer.println(); 6323 6324 mAdapterStateMachine.dump(fd, writer, args); 6325 6326 StringBuilder sb = new StringBuilder(); 6327 for (ProfileService profile : mRegisteredProfiles) { 6328 profile.dump(sb); 6329 } 6330 mSilenceDeviceManager.dump(fd, writer, args); 6331 mDatabaseManager.dump(writer); 6332 6333 writer.write(sb.toString()); 6334 writer.flush(); 6335 6336 final int currentState = mAdapterProperties.getState(); 6337 if (currentState == BluetoothAdapter.STATE_OFF 6338 || currentState == BluetoothAdapter.STATE_BLE_TURNING_ON 6339 || currentState == BluetoothAdapter.STATE_TURNING_OFF 6340 || currentState == BluetoothAdapter.STATE_BLE_TURNING_OFF) { 6341 writer.println(); 6342 writer.println( 6343 "Impossible to dump native stack. state=" 6344 + BluetoothAdapter.nameForState(currentState)); 6345 writer.println(); 6346 } else { 6347 mNativeInterface.dump(fd, args); 6348 } 6349 } 6350 dumpMetrics(FileDescriptor fd)6351 private void dumpMetrics(FileDescriptor fd) { 6352 BluetoothMetricsProto.BluetoothLog.Builder metricsBuilder = 6353 BluetoothMetricsProto.BluetoothLog.newBuilder(); 6354 byte[] nativeMetricsBytes = mNativeInterface.dumpMetrics(); 6355 Log.d(TAG, "dumpMetrics: native metrics size is " + nativeMetricsBytes.length); 6356 if (nativeMetricsBytes.length > 0) { 6357 try { 6358 metricsBuilder.mergeFrom(nativeMetricsBytes); 6359 } catch (InvalidProtocolBufferException ex) { 6360 Log.w(TAG, "dumpMetrics: problem parsing metrics protobuf, " + ex.getMessage()); 6361 return; 6362 } 6363 } 6364 metricsBuilder.setNumBondedDevices(getBondedDevices().length); 6365 MetricsLogger.dumpProto(metricsBuilder); 6366 for (ProfileService profile : mRegisteredProfiles) { 6367 profile.dumpProto(metricsBuilder); 6368 } 6369 byte[] metricsBytes = Base64.encode(metricsBuilder.build().toByteArray(), Base64.DEFAULT); 6370 Log.d(TAG, "dumpMetrics: combined metrics size is " + metricsBytes.length); 6371 try (FileOutputStream protoOut = new FileOutputStream(fd)) { 6372 protoOut.write(metricsBytes); 6373 } catch (IOException e) { 6374 Log.e(TAG, "dumpMetrics: error writing combined protobuf to fd, " + e.getMessage()); 6375 } 6376 } 6377 6378 @SuppressLint("AndroidFrameworkRequiresPermission") enforceBluetoothPrivilegedPermissionIfNeeded( OobData remoteP192Data, OobData remoteP256Data)6379 private void enforceBluetoothPrivilegedPermissionIfNeeded( 6380 OobData remoteP192Data, OobData remoteP256Data) { 6381 if (remoteP192Data != null || remoteP256Data != null) { 6382 enforceBluetoothPrivilegedPermission(this); 6383 } 6384 } 6385 6386 @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) getInitFlags()6387 private String[] getInitFlags() { 6388 final DeviceConfig.Properties properties = 6389 DeviceConfig.getProperties(DeviceConfig.NAMESPACE_BLUETOOTH); 6390 ArrayList<String> initFlags = new ArrayList<>(); 6391 for (String property : properties.getKeyset()) { 6392 if (property.startsWith("INIT_")) { 6393 initFlags.add( 6394 String.format("%s=%s", property, properties.getString(property, null))); 6395 } 6396 } 6397 return initFlags.toArray(new String[0]); 6398 } 6399 6400 private final Object mDeviceConfigLock = new Object(); 6401 6402 /** 6403 * Predicate that can be applied to names to determine if a device is well-known to be used for 6404 * physical location. 6405 */ 6406 @GuardedBy("mDeviceConfigLock") 6407 private Predicate<String> mLocationDenylistName = (v) -> false; 6408 6409 /** 6410 * Predicate that can be applied to MAC addresses to determine if a device is well-known to be 6411 * used for physical location. 6412 */ 6413 @GuardedBy("mDeviceConfigLock") 6414 private Predicate<byte[]> mLocationDenylistMac = (v) -> false; 6415 6416 /** 6417 * Predicate that can be applied to Advertising Data payloads to determine if a device is 6418 * well-known to be used for physical location. 6419 */ 6420 @GuardedBy("mDeviceConfigLock") 6421 private Predicate<byte[]> mLocationDenylistAdvertisingData = (v) -> false; 6422 6423 @GuardedBy("mDeviceConfigLock") 6424 private int mScanQuotaCount = DeviceConfigListener.DEFAULT_SCAN_QUOTA_COUNT; 6425 6426 @GuardedBy("mDeviceConfigLock") 6427 private long mScanQuotaWindowMillis = DeviceConfigListener.DEFAULT_SCAN_QUOTA_WINDOW_MILLIS; 6428 6429 @GuardedBy("mDeviceConfigLock") 6430 private long mScanTimeoutMillis = DeviceConfigListener.DEFAULT_SCAN_TIMEOUT_MILLIS; 6431 6432 @GuardedBy("mDeviceConfigLock") 6433 private int mScanUpgradeDurationMillis = 6434 DeviceConfigListener.DEFAULT_SCAN_UPGRADE_DURATION_MILLIS; 6435 6436 @GuardedBy("mDeviceConfigLock") 6437 private int mScanDowngradeDurationMillis = 6438 DeviceConfigListener.DEFAULT_SCAN_DOWNGRADE_DURATION_BT_CONNECTING_MILLIS; 6439 6440 @GuardedBy("mDeviceConfigLock") 6441 private int mScreenOffLowPowerWindowMillis = 6442 ScanManager.SCAN_MODE_SCREEN_OFF_LOW_POWER_WINDOW_MS; 6443 6444 @GuardedBy("mDeviceConfigLock") 6445 private int mScreenOffLowPowerIntervalMillis = 6446 ScanManager.SCAN_MODE_SCREEN_OFF_LOW_POWER_INTERVAL_MS; 6447 6448 @GuardedBy("mDeviceConfigLock") 6449 private int mScreenOffBalancedWindowMillis = 6450 ScanManager.SCAN_MODE_SCREEN_OFF_BALANCED_WINDOW_MS; 6451 6452 @GuardedBy("mDeviceConfigLock") 6453 private int mScreenOffBalancedIntervalMillis = 6454 ScanManager.SCAN_MODE_SCREEN_OFF_BALANCED_INTERVAL_MS; 6455 6456 @GuardedBy("mDeviceConfigLock") 6457 private String mLeAudioAllowList; 6458 getLocationDenylistName()6459 public @NonNull Predicate<String> getLocationDenylistName() { 6460 synchronized (mDeviceConfigLock) { 6461 return mLocationDenylistName; 6462 } 6463 } 6464 getLocationDenylistMac()6465 public @NonNull Predicate<byte[]> getLocationDenylistMac() { 6466 synchronized (mDeviceConfigLock) { 6467 return mLocationDenylistMac; 6468 } 6469 } 6470 getLocationDenylistAdvertisingData()6471 public @NonNull Predicate<byte[]> getLocationDenylistAdvertisingData() { 6472 synchronized (mDeviceConfigLock) { 6473 return mLocationDenylistAdvertisingData; 6474 } 6475 } 6476 6477 /** Returns scan quota count. */ getScanQuotaCount()6478 public int getScanQuotaCount() { 6479 synchronized (mDeviceConfigLock) { 6480 return mScanQuotaCount; 6481 } 6482 } 6483 6484 /** Returns scan quota window in millis. */ getScanQuotaWindowMillis()6485 public long getScanQuotaWindowMillis() { 6486 synchronized (mDeviceConfigLock) { 6487 return mScanQuotaWindowMillis; 6488 } 6489 } 6490 6491 /** Returns scan timeout in millis. */ getScanTimeoutMillis()6492 public long getScanTimeoutMillis() { 6493 synchronized (mDeviceConfigLock) { 6494 return mScanTimeoutMillis; 6495 } 6496 } 6497 6498 /** Returns scan upgrade duration in millis. */ getScanUpgradeDurationMillis()6499 public long getScanUpgradeDurationMillis() { 6500 synchronized (mDeviceConfigLock) { 6501 return mScanUpgradeDurationMillis; 6502 } 6503 } 6504 6505 /** Returns scan downgrade duration in millis. */ getScanDowngradeDurationMillis()6506 public long getScanDowngradeDurationMillis() { 6507 synchronized (mDeviceConfigLock) { 6508 return mScanDowngradeDurationMillis; 6509 } 6510 } 6511 6512 /** Returns SCREEN_OFF_BALANCED scan window in millis. */ getScreenOffBalancedWindowMillis()6513 public int getScreenOffBalancedWindowMillis() { 6514 synchronized (mDeviceConfigLock) { 6515 return mScreenOffBalancedWindowMillis; 6516 } 6517 } 6518 6519 /** Returns SCREEN_OFF_BALANCED scan interval in millis. */ getScreenOffBalancedIntervalMillis()6520 public int getScreenOffBalancedIntervalMillis() { 6521 synchronized (mDeviceConfigLock) { 6522 return mScreenOffBalancedIntervalMillis; 6523 } 6524 } 6525 6526 /** Returns SCREEN_OFF low power scan window in millis. */ getScreenOffLowPowerWindowMillis()6527 public int getScreenOffLowPowerWindowMillis() { 6528 synchronized (mDeviceConfigLock) { 6529 return mScreenOffLowPowerWindowMillis; 6530 } 6531 } 6532 6533 /** Returns SCREEN_OFF low power scan interval in millis. */ getScreenOffLowPowerIntervalMillis()6534 public int getScreenOffLowPowerIntervalMillis() { 6535 synchronized (mDeviceConfigLock) { 6536 return mScreenOffLowPowerIntervalMillis; 6537 } 6538 } 6539 6540 private class DeviceConfigListener implements DeviceConfig.OnPropertiesChangedListener { 6541 private static final String LOCATION_DENYLIST_NAME = "location_denylist_name"; 6542 private static final String LOCATION_DENYLIST_MAC = "location_denylist_mac"; 6543 private static final String LOCATION_DENYLIST_ADVERTISING_DATA = 6544 "location_denylist_advertising_data"; 6545 private static final String SCAN_QUOTA_COUNT = "scan_quota_count"; 6546 private static final String SCAN_QUOTA_WINDOW_MILLIS = "scan_quota_window_millis"; 6547 private static final String SCAN_TIMEOUT_MILLIS = "scan_timeout_millis"; 6548 private static final String SCAN_UPGRADE_DURATION_MILLIS = "scan_upgrade_duration_millis"; 6549 private static final String SCAN_DOWNGRADE_DURATION_MILLIS = 6550 "scan_downgrade_duration_millis"; 6551 private static final String SCREEN_OFF_LOW_POWER_WINDOW_MILLIS = 6552 "screen_off_low_power_window_millis"; 6553 private static final String SCREEN_OFF_LOW_POWER_INTERVAL_MILLIS = 6554 "screen_off_low_power_interval_millis"; 6555 private static final String SCREEN_OFF_BALANCED_WINDOW_MILLIS = 6556 "screen_off_balanced_window_millis"; 6557 private static final String SCREEN_OFF_BALANCED_INTERVAL_MILLIS = 6558 "screen_off_balanced_interval_millis"; 6559 private static final String LE_AUDIO_ALLOW_LIST = "le_audio_allow_list"; 6560 6561 /** 6562 * Default denylist which matches Eddystone (except for Eddystone-E2EE-EID) and iBeacon 6563 * payloads. 6564 */ 6565 private static final String DEFAULT_LOCATION_DENYLIST_ADVERTISING_DATA = 6566 "⊈0016AAFE40/00FFFFFFF0,⊆0016AAFE/00FFFFFF,⊆00FF4C0002/00FFFFFFFF"; 6567 6568 private static final int DEFAULT_SCAN_QUOTA_COUNT = 5; 6569 private static final long DEFAULT_SCAN_QUOTA_WINDOW_MILLIS = 30 * SECOND_IN_MILLIS; 6570 private static final long DEFAULT_SCAN_TIMEOUT_MILLIS = 10 * MINUTE_IN_MILLIS; 6571 private static final int DEFAULT_SCAN_UPGRADE_DURATION_MILLIS = (int) SECOND_IN_MILLIS * 6; 6572 private static final int DEFAULT_SCAN_DOWNGRADE_DURATION_BT_CONNECTING_MILLIS = 6573 (int) SECOND_IN_MILLIS * 6; 6574 6575 @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) start()6576 public void start() { 6577 DeviceConfig.addOnPropertiesChangedListener( 6578 DeviceConfig.NAMESPACE_BLUETOOTH, BackgroundThread.getExecutor(), this); 6579 onPropertiesChanged(DeviceConfig.getProperties(DeviceConfig.NAMESPACE_BLUETOOTH)); 6580 } 6581 6582 @Override onPropertiesChanged(DeviceConfig.Properties properties)6583 public void onPropertiesChanged(DeviceConfig.Properties properties) { 6584 synchronized (mDeviceConfigLock) { 6585 final String name = properties.getString(LOCATION_DENYLIST_NAME, null); 6586 mLocationDenylistName = 6587 !TextUtils.isEmpty(name) 6588 ? Pattern.compile(name).asPredicate() 6589 : (v) -> false; 6590 mLocationDenylistMac = 6591 BytesMatcher.decode(properties.getString(LOCATION_DENYLIST_MAC, null)); 6592 mLocationDenylistAdvertisingData = 6593 BytesMatcher.decode( 6594 properties.getString( 6595 LOCATION_DENYLIST_ADVERTISING_DATA, 6596 DEFAULT_LOCATION_DENYLIST_ADVERTISING_DATA)); 6597 mScanQuotaCount = properties.getInt(SCAN_QUOTA_COUNT, DEFAULT_SCAN_QUOTA_COUNT); 6598 mScanQuotaWindowMillis = 6599 properties.getLong( 6600 SCAN_QUOTA_WINDOW_MILLIS, DEFAULT_SCAN_QUOTA_WINDOW_MILLIS); 6601 mScanTimeoutMillis = 6602 properties.getLong(SCAN_TIMEOUT_MILLIS, DEFAULT_SCAN_TIMEOUT_MILLIS); 6603 mScanUpgradeDurationMillis = 6604 properties.getInt( 6605 SCAN_UPGRADE_DURATION_MILLIS, DEFAULT_SCAN_UPGRADE_DURATION_MILLIS); 6606 mScanDowngradeDurationMillis = 6607 properties.getInt( 6608 SCAN_DOWNGRADE_DURATION_MILLIS, 6609 DEFAULT_SCAN_DOWNGRADE_DURATION_BT_CONNECTING_MILLIS); 6610 mScreenOffLowPowerWindowMillis = 6611 properties.getInt( 6612 SCREEN_OFF_LOW_POWER_WINDOW_MILLIS, 6613 ScanManager.SCAN_MODE_SCREEN_OFF_LOW_POWER_WINDOW_MS); 6614 mScreenOffLowPowerIntervalMillis = 6615 properties.getInt( 6616 SCREEN_OFF_LOW_POWER_INTERVAL_MILLIS, 6617 ScanManager.SCAN_MODE_SCREEN_OFF_LOW_POWER_INTERVAL_MS); 6618 mScreenOffBalancedWindowMillis = 6619 properties.getInt( 6620 SCREEN_OFF_BALANCED_WINDOW_MILLIS, 6621 ScanManager.SCAN_MODE_SCREEN_OFF_BALANCED_WINDOW_MS); 6622 mScreenOffBalancedIntervalMillis = 6623 properties.getInt( 6624 SCREEN_OFF_BALANCED_INTERVAL_MILLIS, 6625 ScanManager.SCAN_MODE_SCREEN_OFF_BALANCED_INTERVAL_MS); 6626 mLeAudioAllowList = properties.getString(LE_AUDIO_ALLOW_LIST, ""); 6627 6628 if (!mLeAudioAllowList.isEmpty()) { 6629 List<String> leAudioAllowlistFromDeviceConfig = 6630 Arrays.asList(mLeAudioAllowList.split(",")); 6631 BluetoothProperties.le_audio_allow_list(leAudioAllowlistFromDeviceConfig); 6632 } 6633 6634 List<String> leAudioAllowlistProp = BluetoothProperties.le_audio_allow_list(); 6635 if (leAudioAllowlistProp != null && !leAudioAllowlistProp.isEmpty()) { 6636 mLeAudioAllowDevices.clear(); 6637 mLeAudioAllowDevices.addAll(leAudioAllowlistProp); 6638 } 6639 } 6640 } 6641 } 6642 6643 /** A callback that will be called when AdapterState is changed */ 6644 public interface BluetoothStateCallback { 6645 /** 6646 * Called when the status of bluetooth adapter is changing. {@code prevState} and {@code 6647 * newState} takes one of following values defined in BluetoothAdapter.java: STATE_OFF, 6648 * STATE_TURNING_ON, STATE_ON, STATE_TURNING_OFF, STATE_BLE_TURNING_ON, STATE_BLE_ON, 6649 * STATE_BLE_TURNING_OFF 6650 * 6651 * @param prevState the previous Bluetooth state. 6652 * @param newState the new Bluetooth state. 6653 */ onBluetoothStateChange(int prevState, int newState)6654 void onBluetoothStateChange(int prevState, int newState); 6655 } 6656 6657 /** 6658 * Obfuscate Bluetooth MAC address into a PII free ID string 6659 * 6660 * @param device Bluetooth device whose MAC address will be obfuscated 6661 * @return a byte array that is unique to this MAC address on this device, or empty byte array 6662 * when either device is null or obfuscateAddressNative fails 6663 */ obfuscateAddress(BluetoothDevice device)6664 public byte[] obfuscateAddress(BluetoothDevice device) { 6665 if (device == null) { 6666 return new byte[0]; 6667 } 6668 return mNativeInterface.obfuscateAddress(Utils.getByteAddress(device)); 6669 } 6670 6671 /** 6672 * Get dynamic audio buffer size supported type 6673 * 6674 * @return support 6675 * <p>Possible values are {@link BluetoothA2dp#DYNAMIC_BUFFER_SUPPORT_NONE}, {@link 6676 * BluetoothA2dp#DYNAMIC_BUFFER_SUPPORT_A2DP_OFFLOAD}, {@link 6677 * BluetoothA2dp#DYNAMIC_BUFFER_SUPPORT_A2DP_SOFTWARE_ENCODING}. 6678 */ getDynamicBufferSupport()6679 public int getDynamicBufferSupport() { 6680 return mAdapterProperties.getDynamicBufferSupport(); 6681 } 6682 6683 /** 6684 * Get dynamic audio buffer size 6685 * 6686 * @return BufferConstraints 6687 */ getBufferConstraints()6688 public BufferConstraints getBufferConstraints() { 6689 return mAdapterProperties.getBufferConstraints(); 6690 } 6691 6692 /** 6693 * Set dynamic audio buffer size 6694 * 6695 * @param codec Audio codec 6696 * @param value buffer millis 6697 * @return true if the settings is successful, false otherwise 6698 */ setBufferLengthMillis(int codec, int value)6699 public boolean setBufferLengthMillis(int codec, int value) { 6700 return mAdapterProperties.setBufferLengthMillis(codec, value); 6701 } 6702 6703 /** 6704 * Get an incremental id of Bluetooth metrics and log 6705 * 6706 * @param device Bluetooth device 6707 * @return int of id for Bluetooth metrics and logging, 0 if the device is invalid 6708 */ getMetricId(BluetoothDevice device)6709 public int getMetricId(BluetoothDevice device) { 6710 if (device == null) { 6711 return 0; 6712 } 6713 return mNativeInterface.getMetricId(Utils.getByteAddress(device)); 6714 } 6715 getCompanionManager()6716 public CompanionManager getCompanionManager() { 6717 return mBtCompanionManager; 6718 } 6719 6720 /** 6721 * Call for the AdapterService receives bond state change 6722 * 6723 * @param device Bluetooth device 6724 * @param state bond state 6725 */ onBondStateChanged(BluetoothDevice device, int state)6726 public void onBondStateChanged(BluetoothDevice device, int state) { 6727 if (mBtCompanionManager != null) { 6728 mBtCompanionManager.onBondStateChanged(device, state); 6729 } 6730 } 6731 6732 /** 6733 * Get audio policy feature support status 6734 * 6735 * @param device Bluetooth device to be checked for audio policy support 6736 * @return int status of the remote support for audio policy feature 6737 */ isRequestAudioPolicyAsSinkSupported(BluetoothDevice device)6738 public int isRequestAudioPolicyAsSinkSupported(BluetoothDevice device) { 6739 if (mHeadsetClientService != null) { 6740 return mHeadsetClientService.getAudioPolicyRemoteSupported(device); 6741 } else { 6742 Log.e(TAG, "No audio transport connected"); 6743 return BluetoothStatusCodes.FEATURE_NOT_CONFIGURED; 6744 } 6745 } 6746 6747 /** 6748 * Set audio policy for remote device 6749 * 6750 * @param device Bluetooth device to be set policy for 6751 * @return int result status for requestAudioPolicyAsSink API 6752 */ requestAudioPolicyAsSink(BluetoothDevice device, BluetoothSinkAudioPolicy policies)6753 public int requestAudioPolicyAsSink(BluetoothDevice device, BluetoothSinkAudioPolicy policies) { 6754 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 6755 if (deviceProp == null) { 6756 return BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED; 6757 } 6758 6759 if (mHeadsetClientService != null) { 6760 if (isRequestAudioPolicyAsSinkSupported(device) 6761 != BluetoothStatusCodes.FEATURE_SUPPORTED) { 6762 throw new UnsupportedOperationException( 6763 "Request Audio Policy As Sink not supported"); 6764 } 6765 deviceProp.setHfAudioPolicyForRemoteAg(policies); 6766 mHeadsetClientService.setAudioPolicy(device, policies); 6767 return BluetoothStatusCodes.SUCCESS; 6768 } else { 6769 Log.e(TAG, "HeadsetClient not connected"); 6770 return BluetoothStatusCodes.ERROR_PROFILE_NOT_CONNECTED; 6771 } 6772 } 6773 6774 /** 6775 * Get audio policy for remote device 6776 * 6777 * @param device Bluetooth device to be set policy for 6778 * @return {@link BluetoothSinkAudioPolicy} policy stored for the device 6779 */ getRequestedAudioPolicyAsSink(BluetoothDevice device)6780 public BluetoothSinkAudioPolicy getRequestedAudioPolicyAsSink(BluetoothDevice device) { 6781 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 6782 if (deviceProp == null) { 6783 return null; 6784 } 6785 6786 if (mHeadsetClientService != null) { 6787 return deviceProp.getHfAudioPolicyForRemoteAg(); 6788 } else { 6789 Log.e(TAG, "HeadsetClient not connected"); 6790 return null; 6791 } 6792 } 6793 6794 /** 6795 * Allow audio low latency 6796 * 6797 * @param allowed true if audio low latency is being allowed 6798 * @param device device whose audio low latency will be allowed or disallowed 6799 * @return boolean true if audio low latency is successfully allowed or disallowed 6800 */ allowLowLatencyAudio(boolean allowed, BluetoothDevice device)6801 public boolean allowLowLatencyAudio(boolean allowed, BluetoothDevice device) { 6802 return mNativeInterface.allowLowLatencyAudio(allowed, Utils.getByteAddress(device)); 6803 } 6804 6805 /** 6806 * get remote PBAP PCE version. 6807 * 6808 * @param address of remote device 6809 * @return int value other than 0 if remote PBAP PCE version is found 6810 */ getRemotePbapPceVersion(String address)6811 public int getRemotePbapPceVersion(String address) { 6812 return mNativeInterface.getRemotePbapPceVersion(address); 6813 } 6814 6815 /** 6816 * check, if PBAP PSE dynamic version upgrade is enabled. 6817 * 6818 * @return true/false. 6819 */ pbapPseDynamicVersionUpgradeIsEnabled()6820 public boolean pbapPseDynamicVersionUpgradeIsEnabled() { 6821 return mNativeInterface.pbapPseDynamicVersionUpgradeIsEnabled(); 6822 } 6823 6824 /** Sets the battery level of the remote device */ setBatteryLevel(BluetoothDevice device, int batteryLevel, boolean isBas)6825 public void setBatteryLevel(BluetoothDevice device, int batteryLevel, boolean isBas) { 6826 if (batteryLevel == BATTERY_LEVEL_UNKNOWN) { 6827 mRemoteDevices.resetBatteryLevel(device, isBas); 6828 } else { 6829 mRemoteDevices.updateBatteryLevel(device, batteryLevel, isBas); 6830 } 6831 } 6832 interopMatchAddr(InteropFeature feature, String address)6833 public boolean interopMatchAddr(InteropFeature feature, String address) { 6834 return mNativeInterface.interopMatchAddr(feature.name(), address); 6835 } 6836 interopMatchName(InteropFeature feature, String name)6837 public boolean interopMatchName(InteropFeature feature, String name) { 6838 return mNativeInterface.interopMatchName(feature.name(), name); 6839 } 6840 interopMatchAddrOrName(InteropFeature feature, String address)6841 public boolean interopMatchAddrOrName(InteropFeature feature, String address) { 6842 return mNativeInterface.interopMatchAddrOrName(feature.name(), address); 6843 } 6844 interopDatabaseAddAddr(InteropFeature feature, String address, int length)6845 public void interopDatabaseAddAddr(InteropFeature feature, String address, int length) { 6846 mNativeInterface.interopDatabaseAddRemoveAddr(true, feature.name(), address, length); 6847 } 6848 interopDatabaseRemoveAddr(InteropFeature feature, String address)6849 public void interopDatabaseRemoveAddr(InteropFeature feature, String address) { 6850 mNativeInterface.interopDatabaseAddRemoveAddr(false, feature.name(), address, 0); 6851 } 6852 interopDatabaseAddName(InteropFeature feature, String name)6853 public void interopDatabaseAddName(InteropFeature feature, String name) { 6854 mNativeInterface.interopDatabaseAddRemoveName(true, feature.name(), name); 6855 } 6856 interopDatabaseRemoveName(InteropFeature feature, String name)6857 public void interopDatabaseRemoveName(InteropFeature feature, String name) { 6858 mNativeInterface.interopDatabaseAddRemoveName(false, feature.name(), name); 6859 } 6860 6861 /** 6862 * Checks the remote device is in the LE Audio allow list or not. 6863 * 6864 * @param device the device to check 6865 * @return boolean true if the device is in the allow list, false otherwise. 6866 */ isLeAudioAllowed(BluetoothDevice device)6867 public boolean isLeAudioAllowed(BluetoothDevice device) { 6868 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 6869 6870 if (deviceProp == null 6871 || deviceProp.getModelName() == null 6872 || !mLeAudioAllowDevices.contains(deviceProp.getModelName())) { 6873 6874 return false; 6875 } 6876 6877 return true; 6878 } 6879 6880 /** 6881 * Get type of the remote device 6882 * 6883 * @param device the device to check 6884 * @return int device type 6885 */ getRemoteType(BluetoothDevice device)6886 public int getRemoteType(BluetoothDevice device) { 6887 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 6888 return deviceProp != null 6889 ? deviceProp.getDeviceType() 6890 : BluetoothDevice.DEVICE_TYPE_UNKNOWN; 6891 } 6892 6893 /** 6894 * Sends service discovery UUIDs internally within the stack. This is meant to remove internal 6895 * dependencies on the broadcast {@link BluetoothDevice#ACTION_UUID}. 6896 * 6897 * @param device is the remote device whose UUIDs have been discovered 6898 * @param uuids are the services supported on the remote device 6899 */ sendUuidsInternal(BluetoothDevice device, ParcelUuid[] uuids)6900 void sendUuidsInternal(BluetoothDevice device, ParcelUuid[] uuids) { 6901 if (device == null) { 6902 Log.w(TAG, "sendUuidsInternal: null device"); 6903 return; 6904 } 6905 if (uuids == null) { 6906 Log.w(TAG, "sendUuidsInternal: uuids is null"); 6907 return; 6908 } 6909 Log.i(TAG, "sendUuidsInternal: Received service discovery UUIDs for device " + device); 6910 for (int i = 0; i < uuids.length; i++) { 6911 Log.d(TAG, "sendUuidsInternal: index=" + i + " uuid=" + uuids[i]); 6912 } 6913 if (mPhonePolicy != null) { 6914 mPhonePolicy.onUuidsDiscovered(device, uuids); 6915 } 6916 } 6917 6918 // TODO: b/339548431 delete isMock 6919 // Returns if this is a mock object. This is currently used in testing so that we may not call 6920 // System.exit() while finalizing the object. Otherwise GC of mock objects unfortunately ends up 6921 // calling finalize() which in turn calls System.exit() and the process crashes. 6922 // 6923 // Mock this in your testing framework to return true to avoid the mentioned behavior. In 6924 // production this has no effect. isMock()6925 public boolean isMock() { 6926 return false; 6927 } 6928 } 6929