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