1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * Copyright (C) 2016-2017 The Linux Foundation 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package com.android.bluetooth.btservice; 19 20 import static android.Manifest.permission.BLUETOOTH_CONNECT; 21 import static android.Manifest.permission.BLUETOOTH_SCAN; 22 23 import android.annotation.NonNull; 24 import android.annotation.RequiresPermission; 25 import android.app.BroadcastOptions; 26 import android.bluetooth.BluetoothA2dp; 27 import android.bluetooth.BluetoothA2dpSink; 28 import android.bluetooth.BluetoothAdapter; 29 import android.bluetooth.BluetoothAvrcpController; 30 import android.bluetooth.BluetoothClass; 31 import android.bluetooth.BluetoothDevice; 32 import android.bluetooth.BluetoothHeadset; 33 import android.bluetooth.BluetoothHeadsetClient; 34 import android.bluetooth.BluetoothHearingAid; 35 import android.bluetooth.BluetoothHidDevice; 36 import android.bluetooth.BluetoothHidHost; 37 import android.bluetooth.BluetoothLeAudio; 38 import android.bluetooth.BluetoothMap; 39 import android.bluetooth.BluetoothMapClient; 40 import android.bluetooth.BluetoothPan; 41 import android.bluetooth.BluetoothPbap; 42 import android.bluetooth.BluetoothPbapClient; 43 import android.bluetooth.BluetoothProfile; 44 import android.bluetooth.BluetoothSap; 45 import android.bluetooth.BufferConstraint; 46 import android.bluetooth.BufferConstraints; 47 import android.content.BroadcastReceiver; 48 import android.content.Context; 49 import android.content.Intent; 50 import android.content.IntentFilter; 51 import android.os.Bundle; 52 import android.os.ParcelUuid; 53 import android.os.SystemProperties; 54 import android.os.UserHandle; 55 import android.util.Log; 56 import android.util.Pair; 57 58 import androidx.annotation.VisibleForTesting; 59 60 import com.android.bluetooth.BluetoothStatsLog; 61 import com.android.bluetooth.Utils; 62 import com.android.bluetooth.btservice.RemoteDevices.DeviceProperties; 63 import com.android.modules.utils.build.SdkLevel; 64 65 import com.google.common.collect.EvictingQueue; 66 67 import java.io.FileDescriptor; 68 import java.io.PrintWriter; 69 import java.util.ArrayList; 70 import java.util.HashMap; 71 import java.util.List; 72 import java.util.concurrent.CopyOnWriteArrayList; 73 74 class AdapterProperties { 75 private static final boolean DBG = true; 76 private static final boolean VDBG = false; 77 private static final String TAG = "AdapterProperties"; 78 79 private static final String MAX_CONNECTED_AUDIO_DEVICES_PROPERTY = 80 "persist.bluetooth.maxconnectedaudiodevices"; 81 private static final int MAX_CONNECTED_AUDIO_DEVICES_LOWER_BOUND = 1; 82 private static final int MAX_CONNECTED_AUDIO_DEVICES_UPPER_BOUND = 5; 83 private static final String A2DP_OFFLOAD_SUPPORTED_PROPERTY = 84 "ro.bluetooth.a2dp_offload.supported"; 85 private static final String A2DP_OFFLOAD_DISABLED_PROPERTY = 86 "persist.bluetooth.a2dp_offload.disabled"; 87 88 private static final long DEFAULT_DISCOVERY_TIMEOUT_MS = 12800; 89 private static final int BD_ADDR_LEN = 6; // in bytes 90 91 private volatile String mName; 92 private volatile byte[] mAddress; 93 private volatile BluetoothClass mBluetoothClass; 94 private volatile int mScanMode; 95 private volatile int mDiscoverableTimeout; 96 private volatile ParcelUuid[] mUuids; 97 private volatile int mLocalIOCapability = BluetoothAdapter.IO_CAPABILITY_UNKNOWN; 98 99 private CopyOnWriteArrayList<BluetoothDevice> mBondedDevices = 100 new CopyOnWriteArrayList<BluetoothDevice>(); 101 102 private static final int SCAN_MODE_CHANGES_MAX_SIZE = 10; 103 private EvictingQueue<String> mScanModeChanges; 104 private CopyOnWriteArrayList<String> mAllowlistedPlayers = 105 new CopyOnWriteArrayList<String>(); 106 107 private int mProfilesConnecting, mProfilesConnected, mProfilesDisconnecting; 108 private final HashMap<Integer, Pair<Integer, Integer>> mProfileConnectionState = 109 new HashMap<>(); 110 111 private volatile int mConnectionState = BluetoothAdapter.STATE_DISCONNECTED; 112 private volatile int mState = BluetoothAdapter.STATE_OFF; 113 private int mMaxConnectedAudioDevices = 1; 114 private boolean mA2dpOffloadEnabled = false; 115 116 private AdapterService mService; 117 private boolean mDiscovering; 118 private long mDiscoveryEndMs; //< Time (ms since epoch) that discovery ended or will end. 119 private RemoteDevices mRemoteDevices; 120 private BluetoothAdapter mAdapter; 121 //TODO - all hw capabilities to be exposed as a class 122 private int mNumOfAdvertisementInstancesSupported; 123 private boolean mRpaOffloadSupported; 124 private int mNumOfOffloadedIrkSupported; 125 private int mNumOfOffloadedScanFilterSupported; 126 private int mOffloadedScanResultStorageBytes; 127 private int mVersSupported; 128 private int mTotNumOfTrackableAdv; 129 private boolean mIsExtendedScanSupported; 130 private boolean mIsDebugLogSupported; 131 private boolean mIsActivityAndEnergyReporting; 132 private boolean mIsLe2MPhySupported; 133 private boolean mIsLeCodedPhySupported; 134 private boolean mIsLeExtendedAdvertisingSupported; 135 private boolean mIsLePeriodicAdvertisingSupported; 136 private int mLeMaximumAdvertisingDataLength; 137 private boolean mIsOffloadedTransportDiscoveryDataScanSupported; 138 139 private int mIsDynamicAudioBufferSizeSupported; 140 private int mDynamicAudioBufferSizeSupportedCodecsGroup1; 141 private int mDynamicAudioBufferSizeSupportedCodecsGroup2; 142 143 private boolean mIsLePeriodicAdvertisingSyncTransferSenderSupported; 144 private boolean mIsLePeriodicAdvertisingSyncTransferRecipientSupported; 145 private boolean mIsLeConnectedIsochronousStreamCentralSupported; 146 private boolean mIsLeIsochronousBroadcasterSupported; 147 148 private List<BufferConstraint> mBufferConstraintList; 149 150 private boolean mReceiverRegistered; 151 private BroadcastReceiver mReceiver = new BroadcastReceiver() { 152 @Override 153 public void onReceive(Context context, Intent intent) { 154 String action = intent.getAction(); 155 if (action == null) { 156 Log.w(TAG, "Received intent with null action"); 157 return; 158 } 159 switch (action) { 160 case BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED: 161 sendConnectionStateChange(BluetoothProfile.HEADSET, intent); 162 break; 163 case BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED: 164 sendConnectionStateChange(BluetoothProfile.A2DP, intent); 165 break; 166 case BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED: 167 sendConnectionStateChange(BluetoothProfile.HEADSET_CLIENT, intent); 168 break; 169 case BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED: 170 sendConnectionStateChange(BluetoothProfile.HEARING_AID, intent); 171 break; 172 case BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED: 173 sendConnectionStateChange(BluetoothProfile.A2DP_SINK, intent); 174 break; 175 case BluetoothHidDevice.ACTION_CONNECTION_STATE_CHANGED: 176 sendConnectionStateChange(BluetoothProfile.HID_DEVICE, intent); 177 break; 178 case BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED: 179 sendConnectionStateChange(BluetoothProfile.HID_HOST, intent); 180 break; 181 case BluetoothAvrcpController.ACTION_CONNECTION_STATE_CHANGED: 182 sendConnectionStateChange(BluetoothProfile.AVRCP_CONTROLLER, intent); 183 break; 184 case BluetoothPan.ACTION_CONNECTION_STATE_CHANGED: 185 sendConnectionStateChange(BluetoothProfile.PAN, intent); 186 break; 187 case BluetoothMap.ACTION_CONNECTION_STATE_CHANGED: 188 sendConnectionStateChange(BluetoothProfile.MAP, intent); 189 break; 190 case BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED: 191 sendConnectionStateChange(BluetoothProfile.MAP_CLIENT, intent); 192 break; 193 case BluetoothSap.ACTION_CONNECTION_STATE_CHANGED: 194 sendConnectionStateChange(BluetoothProfile.SAP, intent); 195 break; 196 case BluetoothPbapClient.ACTION_CONNECTION_STATE_CHANGED: 197 sendConnectionStateChange(BluetoothProfile.PBAP_CLIENT, intent); 198 break; 199 case BluetoothPbap.ACTION_CONNECTION_STATE_CHANGED: 200 sendConnectionStateChange(BluetoothProfile.PBAP, intent); 201 break; 202 case BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED: 203 sendConnectionStateChange(BluetoothProfile.LE_AUDIO, intent); 204 break; 205 default: 206 Log.w(TAG, "Received unknown intent " + intent); 207 break; 208 } 209 } 210 }; 211 212 // Lock for all getters and setters. 213 // If finer grained locking is needer, more locks 214 // can be added here. 215 private final Object mObject = new Object(); 216 AdapterProperties(AdapterService service)217 AdapterProperties(AdapterService service) { 218 mService = service; 219 mAdapter = BluetoothAdapter.getDefaultAdapter(); 220 mScanModeChanges = EvictingQueue.create(SCAN_MODE_CHANGES_MAX_SIZE); 221 invalidateBluetoothCaches(); 222 } 223 init(RemoteDevices remoteDevices)224 public void init(RemoteDevices remoteDevices) { 225 mProfileConnectionState.clear(); 226 mRemoteDevices = remoteDevices; 227 228 // Get default max connected audio devices from config.xml 229 int configDefaultMaxConnectedAudioDevices = mService.getResources().getInteger( 230 com.android.bluetooth.R.integer.config_bluetooth_max_connected_audio_devices); 231 // Override max connected audio devices if MAX_CONNECTED_AUDIO_DEVICES_PROPERTY is set 232 int propertyOverlayedMaxConnectedAudioDevices = 233 SystemProperties.getInt(MAX_CONNECTED_AUDIO_DEVICES_PROPERTY, 234 configDefaultMaxConnectedAudioDevices); 235 // Make sure the final value of max connected audio devices is within allowed range 236 mMaxConnectedAudioDevices = Math.min(Math.max(propertyOverlayedMaxConnectedAudioDevices, 237 MAX_CONNECTED_AUDIO_DEVICES_LOWER_BOUND), MAX_CONNECTED_AUDIO_DEVICES_UPPER_BOUND); 238 Log.i(TAG, "init(), maxConnectedAudioDevices, default=" 239 + configDefaultMaxConnectedAudioDevices + ", propertyOverlayed=" 240 + propertyOverlayedMaxConnectedAudioDevices + ", finalValue=" 241 + mMaxConnectedAudioDevices); 242 243 mA2dpOffloadEnabled = 244 SystemProperties.getBoolean(A2DP_OFFLOAD_SUPPORTED_PROPERTY, false) 245 && !SystemProperties.getBoolean(A2DP_OFFLOAD_DISABLED_PROPERTY, false); 246 247 IntentFilter filter = new IntentFilter(); 248 filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); 249 filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); 250 filter.addAction(BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED); 251 filter.addAction(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED); 252 filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED); 253 filter.addAction(BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED); 254 filter.addAction(BluetoothHidDevice.ACTION_CONNECTION_STATE_CHANGED); 255 filter.addAction(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED); 256 filter.addAction(BluetoothAvrcpController.ACTION_CONNECTION_STATE_CHANGED); 257 filter.addAction(BluetoothPan.ACTION_CONNECTION_STATE_CHANGED); 258 filter.addAction(BluetoothMap.ACTION_CONNECTION_STATE_CHANGED); 259 filter.addAction(BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED); 260 filter.addAction(BluetoothSap.ACTION_CONNECTION_STATE_CHANGED); 261 filter.addAction(BluetoothPbapClient.ACTION_CONNECTION_STATE_CHANGED); 262 filter.addAction(BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED); 263 mService.registerReceiver(mReceiver, filter); 264 mReceiverRegistered = true; 265 invalidateBluetoothCaches(); 266 } 267 cleanup()268 public void cleanup() { 269 mRemoteDevices = null; 270 mProfileConnectionState.clear(); 271 if (mReceiverRegistered) { 272 mService.unregisterReceiver(mReceiver); 273 mReceiverRegistered = false; 274 } 275 mService = null; 276 mBondedDevices.clear(); 277 mScanModeChanges.clear(); 278 invalidateBluetoothCaches(); 279 mAllowlistedPlayers.clear(); 280 } 281 invalidateGetProfileConnectionStateCache()282 private static void invalidateGetProfileConnectionStateCache() { 283 BluetoothAdapter.invalidateGetProfileConnectionStateCache(); 284 } invalidateIsOffloadedFilteringSupportedCache()285 private static void invalidateIsOffloadedFilteringSupportedCache() { 286 BluetoothAdapter.invalidateIsOffloadedFilteringSupportedCache(); 287 } invalidateBluetoothGetConnectionStateCache()288 private static void invalidateBluetoothGetConnectionStateCache() { 289 BluetoothMap.invalidateBluetoothGetConnectionStateCache(); 290 BluetoothSap.invalidateBluetoothGetConnectionStateCache(); 291 } invalidateGetConnectionStateCache()292 private static void invalidateGetConnectionStateCache() { 293 BluetoothAdapter.invalidateGetAdapterConnectionStateCache(); 294 } invalidateGetBondStateCache()295 private static void invalidateGetBondStateCache() { 296 BluetoothDevice.invalidateBluetoothGetBondStateCache(); 297 } invalidateBluetoothCaches()298 private static void invalidateBluetoothCaches() { 299 invalidateGetProfileConnectionStateCache(); 300 invalidateIsOffloadedFilteringSupportedCache(); 301 invalidateGetConnectionStateCache(); 302 invalidateGetBondStateCache(); 303 invalidateBluetoothGetConnectionStateCache(); 304 } 305 306 @Override clone()307 public Object clone() throws CloneNotSupportedException { 308 throw new CloneNotSupportedException(); 309 } 310 311 /** 312 * @return the mName 313 */ getName()314 String getName() { 315 return mName; 316 } 317 318 /** 319 * Set the local adapter property - name 320 * @param name the name to set 321 */ setName(String name)322 boolean setName(String name) { 323 synchronized (mObject) { 324 return mService.setAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDNAME, 325 name.getBytes()); 326 } 327 } 328 setIoCapability(int capability)329 boolean setIoCapability(int capability) { 330 synchronized (mObject) { 331 boolean result = mService.setAdapterPropertyNative( 332 AbstractionLayer.BT_PROPERTY_LOCAL_IO_CAPS, Utils.intToByteArray(capability)); 333 334 if (result) { 335 mLocalIOCapability = capability; 336 } 337 338 return result; 339 } 340 } 341 getIoCapability()342 int getIoCapability() { 343 synchronized (mObject) { 344 return mLocalIOCapability; 345 } 346 } 347 348 /** 349 * @return the mScanMode 350 */ getScanMode()351 int getScanMode() { 352 return mScanMode; 353 } 354 355 /** 356 * Set the local adapter property - scanMode 357 * 358 * @param scanMode the ScanMode to set, valid values are: { 359 * BluetoothAdapter.SCAN_MODE_NONE, 360 * BluetoothAdapter.SCAN_MODE_CONNECTABLE, 361 * BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE, 362 * } 363 */ setScanMode(int scanMode)364 boolean setScanMode(int scanMode) { 365 addScanChangeLog(scanMode); 366 synchronized (mObject) { 367 return mService.setAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_ADAPTER_SCAN_MODE, 368 Utils.intToByteArray(AdapterService.convertScanModeToHal(scanMode))); 369 } 370 } 371 addScanChangeLog(int scanMode)372 private void addScanChangeLog(int scanMode) { 373 String time = Utils.getLocalTimeString(); 374 String uidPid = Utils.getUidPidString(); 375 String scanModeString = dumpScanMode(scanMode); 376 377 mScanModeChanges.add(time + " (" + uidPid + ") " + scanModeString); 378 } 379 380 /** 381 * @return the mUuids 382 */ getUuids()383 ParcelUuid[] getUuids() { 384 return mUuids; 385 } 386 387 /** 388 * @return the mAddress 389 */ getAddress()390 byte[] getAddress() { 391 return mAddress; 392 } 393 394 /** 395 * @param connectionState the mConnectionState to set 396 */ setConnectionState(int connectionState)397 void setConnectionState(int connectionState) { 398 mConnectionState = connectionState; 399 invalidateGetConnectionStateCache(); 400 } 401 402 /** 403 * @return the mConnectionState 404 */ getConnectionState()405 int getConnectionState() { 406 return mConnectionState; 407 } 408 409 /** 410 * @param state the mState to set 411 */ setState(int state)412 void setState(int state) { 413 debugLog("Setting state to " + BluetoothAdapter.nameForState(state)); 414 mState = state; 415 } 416 417 /** 418 * @return the mState 419 */ getState()420 int getState() { 421 return mState; 422 } 423 424 /** 425 * @return the mNumOfAdvertisementInstancesSupported 426 */ getNumOfAdvertisementInstancesSupported()427 int getNumOfAdvertisementInstancesSupported() { 428 return mNumOfAdvertisementInstancesSupported; 429 } 430 431 /** 432 * @return the mRpaOffloadSupported 433 */ isRpaOffloadSupported()434 boolean isRpaOffloadSupported() { 435 return mRpaOffloadSupported; 436 } 437 438 /** 439 * @return the mNumOfOffloadedIrkSupported 440 */ getNumOfOffloadedIrkSupported()441 int getNumOfOffloadedIrkSupported() { 442 return mNumOfOffloadedIrkSupported; 443 } 444 445 /** 446 * @return the mNumOfOffloadedScanFilterSupported 447 */ getNumOfOffloadedScanFilterSupported()448 int getNumOfOffloadedScanFilterSupported() { 449 return mNumOfOffloadedScanFilterSupported; 450 } 451 452 /** 453 * @return the mOffloadedScanResultStorageBytes 454 */ getOffloadedScanResultStorage()455 int getOffloadedScanResultStorage() { 456 return mOffloadedScanResultStorageBytes; 457 } 458 459 /** 460 * @return tx/rx/idle activity and energy info 461 */ isActivityAndEnergyReportingSupported()462 boolean isActivityAndEnergyReportingSupported() { 463 return mIsActivityAndEnergyReporting; 464 } 465 466 /** 467 * @return the mIsLe2MPhySupported 468 */ isLe2MPhySupported()469 boolean isLe2MPhySupported() { 470 return mIsLe2MPhySupported; 471 } 472 473 /** 474 * @return the mIsLeCodedPhySupported 475 */ isLeCodedPhySupported()476 boolean isLeCodedPhySupported() { 477 return mIsLeCodedPhySupported; 478 } 479 480 /** 481 * @return the mIsLeExtendedAdvertisingSupported 482 */ isLeExtendedAdvertisingSupported()483 boolean isLeExtendedAdvertisingSupported() { 484 return mIsLeExtendedAdvertisingSupported; 485 } 486 487 /** 488 * @return the mIsLePeriodicAdvertisingSupported 489 */ isLePeriodicAdvertisingSupported()490 boolean isLePeriodicAdvertisingSupported() { 491 return mIsLePeriodicAdvertisingSupported; 492 } 493 494 /** 495 * @return the mIsLePeriodicAdvertisingSyncTransferSenderSupported 496 */ isLePeriodicAdvertisingSyncTransferSenderSupported()497 boolean isLePeriodicAdvertisingSyncTransferSenderSupported() { 498 return mIsLePeriodicAdvertisingSyncTransferSenderSupported; 499 } 500 501 /** 502 * @return the mIsLePeriodicAdvertisingSyncTransferRecipientSupported 503 */ isLePeriodicAdvertisingSyncTransferRecipientSupported()504 boolean isLePeriodicAdvertisingSyncTransferRecipientSupported() { 505 return mIsLePeriodicAdvertisingSyncTransferRecipientSupported; 506 } 507 508 /** 509 * @return the mIsLeConnectedIsochronousStreamCentralSupported 510 */ isLeConnectedIsochronousStreamCentralSupported()511 boolean isLeConnectedIsochronousStreamCentralSupported() { 512 return mIsLeConnectedIsochronousStreamCentralSupported; 513 } 514 515 /** 516 * @return the mIsLeIsochronousBroadcasterSupported 517 */ isLeIsochronousBroadcasterSupported()518 boolean isLeIsochronousBroadcasterSupported() { 519 return mIsLeIsochronousBroadcasterSupported; 520 } 521 522 /** 523 * @return the getLeMaximumAdvertisingDataLength 524 */ getLeMaximumAdvertisingDataLength()525 int getLeMaximumAdvertisingDataLength() { 526 return mLeMaximumAdvertisingDataLength; 527 } 528 529 /** 530 * @return total number of trackable advertisements 531 */ getTotalNumOfTrackableAdvertisements()532 int getTotalNumOfTrackableAdvertisements() { 533 return mTotNumOfTrackableAdv; 534 } 535 536 537 /** 538 * @return the isOffloadedTransportDiscoveryDataScanSupported 539 */ isOffloadedTransportDiscoveryDataScanSupported()540 public boolean isOffloadedTransportDiscoveryDataScanSupported() { 541 return mIsOffloadedTransportDiscoveryDataScanSupported; 542 } 543 544 /** 545 * @return the maximum number of connected audio devices 546 */ getMaxConnectedAudioDevices()547 int getMaxConnectedAudioDevices() { 548 return mMaxConnectedAudioDevices; 549 } 550 551 /** 552 * @return A2DP offload support 553 */ isA2dpOffloadEnabled()554 boolean isA2dpOffloadEnabled() { 555 return mA2dpOffloadEnabled; 556 } 557 558 /** 559 * @return Dynamic Audio Buffer support 560 */ getDynamicBufferSupport()561 int getDynamicBufferSupport() { 562 if (!mA2dpOffloadEnabled) { 563 // TODO: Enable Dynamic Audio Buffer for A2DP software encoding when ready. 564 mIsDynamicAudioBufferSizeSupported = 565 BluetoothA2dp.DYNAMIC_BUFFER_SUPPORT_NONE; 566 } else { 567 if ((mDynamicAudioBufferSizeSupportedCodecsGroup1 != 0) 568 || (mDynamicAudioBufferSizeSupportedCodecsGroup2 != 0)) { 569 mIsDynamicAudioBufferSizeSupported = 570 BluetoothA2dp.DYNAMIC_BUFFER_SUPPORT_A2DP_OFFLOAD; 571 } else { 572 mIsDynamicAudioBufferSizeSupported = 573 BluetoothA2dp.DYNAMIC_BUFFER_SUPPORT_NONE; 574 } 575 } 576 return mIsDynamicAudioBufferSizeSupported; 577 } 578 579 /** 580 * @return Dynamic Audio Buffer Capability 581 */ getBufferConstraints()582 BufferConstraints getBufferConstraints() { 583 return new BufferConstraints(mBufferConstraintList); 584 } 585 586 /** 587 * Set the dynamic audio buffer size 588 * 589 * @param codec the codecs to set 590 * @param size the size to set 591 */ setBufferLengthMillis(int codec, int size)592 boolean setBufferLengthMillis(int codec, int size) { 593 return mService.setBufferLengthMillisNative(codec, size); 594 } 595 596 /** 597 * @return the mBondedDevices 598 */ getBondedDevices()599 BluetoothDevice[] getBondedDevices() { 600 BluetoothDevice[] bondedDeviceList = new BluetoothDevice[0]; 601 try { 602 bondedDeviceList = mBondedDevices.toArray(bondedDeviceList); 603 } catch (ArrayStoreException ee) { 604 errorLog("Error retrieving bonded device array"); 605 } 606 infoLog("getBondedDevices: length=" + bondedDeviceList.length); 607 return bondedDeviceList; 608 } 609 610 // This function shall be invoked from BondStateMachine whenever the bond 611 // state changes. 612 @VisibleForTesting onBondStateChanged(BluetoothDevice device, int state)613 void onBondStateChanged(BluetoothDevice device, int state) { 614 if (device == null) { 615 Log.w(TAG, "onBondStateChanged, device is null"); 616 return; 617 } 618 try { 619 byte[] addrByte = Utils.getByteAddress(device); 620 DeviceProperties prop = mRemoteDevices.getDeviceProperties(device); 621 if (prop == null) { 622 prop = mRemoteDevices.addDeviceProperties(addrByte); 623 } 624 device = prop.getDevice(); 625 prop.setBondState(state); 626 627 if (state == BluetoothDevice.BOND_BONDED) { 628 // add if not already in list 629 if (!mBondedDevices.contains(device)) { 630 debugLog("Adding bonded device:" + device); 631 mBondedDevices.add(device); 632 cleanupPrevBondRecordsFor(device); 633 } 634 } else if (state == BluetoothDevice.BOND_NONE) { 635 // remove device from list 636 if (mBondedDevices.remove(device)) { 637 debugLog("Removing bonded device:" + device); 638 } else { 639 debugLog("Failed to remove device: " + device); 640 } 641 } 642 invalidateGetBondStateCache(); 643 } catch (Exception ee) { 644 Log.w(TAG, "onBondStateChanged: Exception ", ee); 645 } 646 } 647 cleanupPrevBondRecordsFor(BluetoothDevice currentDevice)648 void cleanupPrevBondRecordsFor(BluetoothDevice currentDevice) { 649 String currentAddress = currentDevice.getAddress(); 650 String currentIdentityAddress = mService.getIdentityAddress(currentAddress); 651 debugLog("cleanupPrevBondRecordsFor: " + currentDevice); 652 if (currentIdentityAddress == null) { 653 return; 654 } 655 656 for (BluetoothDevice device : mBondedDevices) { 657 String address = device.getAddress(); 658 String identityAddress = mService.getIdentityAddress(address); 659 if (currentIdentityAddress.equals(identityAddress) && !currentAddress.equals(address)) { 660 if (mService.removeBondNative(Utils.getBytesFromAddress(device.getAddress()))) { 661 mBondedDevices.remove(device); 662 infoLog("Removing old bond record: " 663 + device 664 + " for current device: " 665 + currentDevice); 666 } else { 667 Log.e(TAG, "Unexpected error while removing old bond record:" 668 + device 669 + " for current device: " 670 + currentDevice); 671 } 672 break; 673 } 674 } 675 } 676 getDiscoverableTimeout()677 int getDiscoverableTimeout() { 678 return mDiscoverableTimeout; 679 } 680 setDiscoverableTimeout(int timeout)681 boolean setDiscoverableTimeout(int timeout) { 682 synchronized (mObject) { 683 return mService.setAdapterPropertyNative( 684 AbstractionLayer.BT_PROPERTY_ADAPTER_DISCOVERABLE_TIMEOUT, 685 Utils.intToByteArray(timeout)); 686 } 687 } 688 getProfileConnectionState(int profile)689 int getProfileConnectionState(int profile) { 690 synchronized (mObject) { 691 Pair<Integer, Integer> p = mProfileConnectionState.get(profile); 692 if (p != null) { 693 return p.first; 694 } 695 return BluetoothProfile.STATE_DISCONNECTED; 696 } 697 } 698 699 /** 700 * @return the mAllowlistedPlayers 701 */ getAllowlistedMediaPlayers()702 String[] getAllowlistedMediaPlayers() { 703 String[] AllowlistedPlayersList = new String[0]; 704 try { 705 AllowlistedPlayersList = mAllowlistedPlayers.toArray(AllowlistedPlayersList); 706 } catch (ArrayStoreException ee) { 707 errorLog("Error retrieving Allowlisted Players array"); 708 } 709 Log.d(TAG, "getAllowlistedMediaPlayers: numAllowlistedPlayers = " 710 + AllowlistedPlayersList.length); 711 for (int i = 0; i < AllowlistedPlayersList.length; i++) { 712 Log.d(TAG, "players :" + AllowlistedPlayersList[i]); 713 } 714 return AllowlistedPlayersList; 715 } 716 discoveryEndMillis()717 long discoveryEndMillis() { 718 return mDiscoveryEndMs; 719 } 720 isDiscovering()721 boolean isDiscovering() { 722 return mDiscovering; 723 } 724 725 @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) sendConnectionStateChange(int profile, Intent connIntent)726 private void sendConnectionStateChange(int profile, Intent connIntent) { 727 BluetoothDevice device = connIntent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 728 int prevState = connIntent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, -1); 729 int state = connIntent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1); 730 int metricId = mService.getMetricId(device); 731 if (state == BluetoothProfile.STATE_CONNECTING) { 732 BluetoothStatsLog.write(BluetoothStatsLog.BLUETOOTH_DEVICE_NAME_REPORTED, 733 metricId, device.getName()); 734 MetricsLogger.getInstance().logSanitizedBluetoothDeviceName(metricId, device.getName()); 735 } 736 Log.d(TAG, 737 "PROFILE_CONNECTION_STATE_CHANGE: profile=" + profile + ", device=" + device + ", " 738 + prevState + " -> " + state); 739 BluetoothStatsLog.write(BluetoothStatsLog.BLUETOOTH_CONNECTION_STATE_CHANGED, state, 740 0 /* deprecated */, profile, mService.obfuscateAddress(device), 741 metricId, 0, -1); 742 743 if (!isNormalStateTransition(prevState, state)) { 744 Log.w(TAG, 745 "PROFILE_CONNECTION_STATE_CHANGE: unexpected transition for profile=" + profile 746 + ", device=" + device + ", " + prevState + " -> " + state); 747 } 748 sendConnectionStateChange(device, profile, state, prevState); 749 } 750 751 @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) sendConnectionStateChange(BluetoothDevice device, int profile, int state, int prevState)752 void sendConnectionStateChange(BluetoothDevice device, int profile, int state, int prevState) { 753 if (!validateProfileConnectionState(state) || !validateProfileConnectionState(prevState)) { 754 // Previously, an invalid state was broadcast anyway, 755 // with the invalid state converted to -1 in the intent. 756 // Better to log an error and not send an intent with 757 // invalid contents or set mAdapterConnectionState to -1. 758 errorLog("sendConnectionStateChange: invalid state transition " + prevState + " -> " 759 + state); 760 return; 761 } 762 763 synchronized (mObject) { 764 updateProfileConnectionState(profile, state, prevState); 765 766 if (updateCountersAndCheckForConnectionStateChange(state, prevState)) { 767 int newAdapterState = convertToAdapterState(state); 768 int prevAdapterState = convertToAdapterState(prevState); 769 setConnectionState(newAdapterState); 770 771 Intent intent = new Intent(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED); 772 intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); 773 intent.putExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, newAdapterState); 774 intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_CONNECTION_STATE, prevAdapterState); 775 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 776 Log.d(TAG, "ADAPTER_CONNECTION_STATE_CHANGE: " + device + ": " + prevAdapterState 777 + " -> " + newAdapterState); 778 if (!isNormalStateTransition(prevState, state)) { 779 Log.w(TAG, "ADAPTER_CONNECTION_STATE_CHANGE: unexpected transition for profile=" 780 + profile + ", device=" + device + ", " + prevState + " -> " + state); 781 } 782 mService.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_CONNECT, 783 Utils.getTempAllowlistBroadcastOptions()); 784 } 785 } 786 } 787 validateProfileConnectionState(int state)788 private boolean validateProfileConnectionState(int state) { 789 return (state == BluetoothProfile.STATE_DISCONNECTED 790 || state == BluetoothProfile.STATE_CONNECTING 791 || state == BluetoothProfile.STATE_CONNECTED 792 || state == BluetoothProfile.STATE_DISCONNECTING); 793 } 794 convertToAdapterState(int state)795 private static int convertToAdapterState(int state) { 796 switch (state) { 797 case BluetoothProfile.STATE_DISCONNECTED: 798 return BluetoothAdapter.STATE_DISCONNECTED; 799 case BluetoothProfile.STATE_DISCONNECTING: 800 return BluetoothAdapter.STATE_DISCONNECTING; 801 case BluetoothProfile.STATE_CONNECTED: 802 return BluetoothAdapter.STATE_CONNECTED; 803 case BluetoothProfile.STATE_CONNECTING: 804 return BluetoothAdapter.STATE_CONNECTING; 805 } 806 Log.e(TAG, "convertToAdapterState, unknow state " + state); 807 return -1; 808 } 809 isNormalStateTransition(int prevState, int nextState)810 private static boolean isNormalStateTransition(int prevState, int nextState) { 811 switch (prevState) { 812 case BluetoothProfile.STATE_DISCONNECTED: 813 return nextState == BluetoothProfile.STATE_CONNECTING; 814 case BluetoothProfile.STATE_CONNECTED: 815 return nextState == BluetoothProfile.STATE_DISCONNECTING; 816 case BluetoothProfile.STATE_DISCONNECTING: 817 case BluetoothProfile.STATE_CONNECTING: 818 return (nextState == BluetoothProfile.STATE_DISCONNECTED) || (nextState 819 == BluetoothProfile.STATE_CONNECTED); 820 default: 821 return false; 822 } 823 } 824 updateCountersAndCheckForConnectionStateChange(int state, int prevState)825 private boolean updateCountersAndCheckForConnectionStateChange(int state, int prevState) { 826 switch (prevState) { 827 case BluetoothProfile.STATE_CONNECTING: 828 if (mProfilesConnecting > 0) { 829 mProfilesConnecting--; 830 } else { 831 Log.e(TAG, "mProfilesConnecting " + mProfilesConnecting); 832 throw new IllegalStateException( 833 "Invalid state transition, " + prevState + " -> " + state); 834 } 835 break; 836 837 case BluetoothProfile.STATE_CONNECTED: 838 if (mProfilesConnected > 0) { 839 mProfilesConnected--; 840 } else { 841 Log.e(TAG, "mProfilesConnected " + mProfilesConnected); 842 throw new IllegalStateException( 843 "Invalid state transition, " + prevState + " -> " + state); 844 } 845 break; 846 847 case BluetoothProfile.STATE_DISCONNECTING: 848 if (mProfilesDisconnecting > 0) { 849 mProfilesDisconnecting--; 850 } else { 851 Log.e(TAG, "mProfilesDisconnecting " + mProfilesDisconnecting); 852 throw new IllegalStateException( 853 "Invalid state transition, " + prevState + " -> " + state); 854 } 855 break; 856 } 857 858 switch (state) { 859 case BluetoothProfile.STATE_CONNECTING: 860 mProfilesConnecting++; 861 return (mProfilesConnected == 0 && mProfilesConnecting == 1); 862 863 case BluetoothProfile.STATE_CONNECTED: 864 mProfilesConnected++; 865 return (mProfilesConnected == 1); 866 867 case BluetoothProfile.STATE_DISCONNECTING: 868 mProfilesDisconnecting++; 869 return (mProfilesConnected == 0 && mProfilesDisconnecting == 1); 870 871 case BluetoothProfile.STATE_DISCONNECTED: 872 return (mProfilesConnected == 0 && mProfilesConnecting == 0); 873 874 default: 875 return true; 876 } 877 } 878 updateProfileConnectionState(int profile, int newState, int oldState)879 private void updateProfileConnectionState(int profile, int newState, int oldState) { 880 // mProfileConnectionState is a hashmap - 881 // <Integer, Pair<Integer, Integer>> 882 // The key is the profile, the value is a pair. first element 883 // is the state and the second element is the number of devices 884 // in that state. 885 int numDev = 1; 886 int newHashState = newState; 887 boolean update = true; 888 889 // The following conditions are considered in this function: 890 // 1. If there is no record of profile and state - update 891 // 2. If a new device's state is current hash state - increment 892 // number of devices in the state. 893 // 3. If a state change has happened to Connected or Connecting 894 // (if current state is not connected), update. 895 // 4. If numDevices is 1 and that device state is being updated, update 896 // 5. If numDevices is > 1 and one of the devices is changing state, 897 // decrement numDevices but maintain oldState if it is Connected or 898 // Connecting 899 Pair<Integer, Integer> stateNumDev = mProfileConnectionState.get(profile); 900 if (stateNumDev != null) { 901 int currHashState = stateNumDev.first; 902 numDev = stateNumDev.second; 903 904 if (newState == currHashState) { 905 numDev++; 906 } else if (newState == BluetoothProfile.STATE_CONNECTED || ( 907 newState == BluetoothProfile.STATE_CONNECTING 908 && currHashState != BluetoothProfile.STATE_CONNECTED)) { 909 numDev = 1; 910 } else if (numDev == 1 && oldState == currHashState) { 911 update = true; 912 } else if (numDev > 1 && oldState == currHashState) { 913 numDev--; 914 915 if (currHashState == BluetoothProfile.STATE_CONNECTED 916 || currHashState == BluetoothProfile.STATE_CONNECTING) { 917 newHashState = currHashState; 918 } 919 } else { 920 update = false; 921 } 922 } 923 924 if (update) { 925 mProfileConnectionState.put(profile, new Pair<Integer, Integer>(newHashState, numDev)); 926 invalidateGetProfileConnectionStateCache(); 927 } 928 } 929 updateAllowlistedMediaPlayers(String playername)930 void updateAllowlistedMediaPlayers(String playername) { 931 Log.d(TAG, "updateAllowlistedMediaPlayers "); 932 933 if (!mAllowlistedPlayers.contains(playername)) { 934 Log.d(TAG, "Adding to Allowlisted Players list:" + playername); 935 mAllowlistedPlayers.add(playername); 936 } 937 } 938 939 @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) adapterPropertyChangedCallback(int[] types, byte[][] values)940 void adapterPropertyChangedCallback(int[] types, byte[][] values) { 941 Intent intent; 942 int type; 943 byte[] val; 944 for (int i = 0; i < types.length; i++) { 945 val = values[i]; 946 type = types[i]; 947 infoLog("adapterPropertyChangedCallback with type:" + type + " len:" + val.length); 948 synchronized (mObject) { 949 switch (type) { 950 case AbstractionLayer.BT_PROPERTY_BDNAME: 951 mName = new String(val); 952 intent = new Intent(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); 953 intent.putExtra(BluetoothAdapter.EXTRA_LOCAL_NAME, mName); 954 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 955 mService.sendBroadcastAsUser(intent, UserHandle.ALL, 956 BLUETOOTH_CONNECT, Utils.getTempAllowlistBroadcastOptions()); 957 debugLog("Name is: " + mName); 958 break; 959 case AbstractionLayer.BT_PROPERTY_BDADDR: 960 mAddress = val; 961 String address = Utils.getAddressStringFromByte(mAddress); 962 intent = new Intent(BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED); 963 intent.putExtra(BluetoothAdapter.EXTRA_BLUETOOTH_ADDRESS, address); 964 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 965 mService.sendBroadcastAsUser(intent, UserHandle.ALL, 966 BLUETOOTH_CONNECT, Utils.getTempAllowlistBroadcastOptions()); 967 break; 968 case AbstractionLayer.BT_PROPERTY_CLASS_OF_DEVICE: 969 if (val == null || val.length != 3) { 970 debugLog("Invalid BT CoD value from stack."); 971 return; 972 } 973 int bluetoothClass = 974 ((int) val[0] << 16) + ((int) val[1] << 8) + (int) val[2]; 975 if (bluetoothClass != 0) { 976 mBluetoothClass = new BluetoothClass(bluetoothClass); 977 } 978 debugLog("BT Class:" + mBluetoothClass); 979 break; 980 case AbstractionLayer.BT_PROPERTY_ADAPTER_SCAN_MODE: 981 int mode = Utils.byteArrayToInt(val, 0); 982 mScanMode = AdapterService.convertScanModeFromHal(mode); 983 intent = new Intent(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED); 984 intent.putExtra(BluetoothAdapter.EXTRA_SCAN_MODE, mScanMode); 985 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 986 Utils.sendBroadcast(mService, intent, BLUETOOTH_SCAN, 987 Utils.getTempAllowlistBroadcastOptions()); 988 debugLog("Scan Mode:" + mScanMode); 989 break; 990 case AbstractionLayer.BT_PROPERTY_UUIDS: 991 mUuids = Utils.byteArrayToUuid(val); 992 break; 993 case AbstractionLayer.BT_PROPERTY_ADAPTER_BONDED_DEVICES: 994 int number = val.length / BD_ADDR_LEN; 995 byte[] addrByte = new byte[BD_ADDR_LEN]; 996 for (int j = 0; j < number; j++) { 997 System.arraycopy(val, j * BD_ADDR_LEN, addrByte, 0, BD_ADDR_LEN); 998 onBondStateChanged(mAdapter.getRemoteDevice( 999 Utils.getAddressStringFromByte(addrByte)), 1000 BluetoothDevice.BOND_BONDED); 1001 } 1002 break; 1003 case AbstractionLayer.BT_PROPERTY_ADAPTER_DISCOVERABLE_TIMEOUT: 1004 mDiscoverableTimeout = Utils.byteArrayToInt(val, 0); 1005 debugLog("Discoverable Timeout:" + mDiscoverableTimeout); 1006 break; 1007 1008 case AbstractionLayer.BT_PROPERTY_LOCAL_LE_FEATURES: 1009 updateFeatureSupport(val); 1010 mService.updateLeAudioProfileServiceState(); 1011 break; 1012 1013 case AbstractionLayer.BT_PROPERTY_DYNAMIC_AUDIO_BUFFER: 1014 updateDynamicAudioBufferSupport(val); 1015 break; 1016 1017 case AbstractionLayer.BT_PROPERTY_LOCAL_IO_CAPS: 1018 mLocalIOCapability = Utils.byteArrayToInt(val); 1019 debugLog("mLocalIOCapability set to " + mLocalIOCapability); 1020 break; 1021 1022 case AbstractionLayer.BT_PROPERTY_WL_MEDIA_PLAYERS_LIST: 1023 int pos = 0; 1024 for (int j = 0; j < val.length; j++) { 1025 if (val[j] != 0) { 1026 continue; 1027 } 1028 int name_len = j - pos; 1029 1030 byte[] buf = new byte[name_len]; 1031 System.arraycopy(val, pos, buf, 0, name_len); 1032 String player_name = new String(buf, 0, name_len); 1033 Log.d(TAG, "player_name: " + player_name); 1034 updateAllowlistedMediaPlayers(player_name); 1035 pos += (name_len + 1); 1036 } 1037 break; 1038 1039 default: 1040 errorLog("Property change not handled in Java land:" + type); 1041 } 1042 } 1043 } 1044 } 1045 updateFeatureSupport(byte[] val)1046 private void updateFeatureSupport(byte[] val) { 1047 mVersSupported = ((0xFF & ((int) val[1])) << 8) + (0xFF & ((int) val[0])); 1048 mNumOfAdvertisementInstancesSupported = (0xFF & ((int) val[3])); 1049 mRpaOffloadSupported = ((0xFF & ((int) val[4])) != 0); 1050 mNumOfOffloadedIrkSupported = (0xFF & ((int) val[5])); 1051 mNumOfOffloadedScanFilterSupported = (0xFF & ((int) val[6])); 1052 mIsActivityAndEnergyReporting = ((0xFF & ((int) val[7])) != 0); 1053 mOffloadedScanResultStorageBytes = ((0xFF & ((int) val[9])) << 8) + (0xFF & ((int) val[8])); 1054 mTotNumOfTrackableAdv = ((0xFF & ((int) val[11])) << 8) + (0xFF & ((int) val[10])); 1055 mIsExtendedScanSupported = ((0xFF & ((int) val[12])) != 0); 1056 mIsDebugLogSupported = ((0xFF & ((int) val[13])) != 0); 1057 mIsLe2MPhySupported = ((0xFF & ((int) val[14])) != 0); 1058 mIsLeCodedPhySupported = ((0xFF & ((int) val[15])) != 0); 1059 mIsLeExtendedAdvertisingSupported = ((0xFF & ((int) val[16])) != 0); 1060 mIsLePeriodicAdvertisingSupported = ((0xFF & ((int) val[17])) != 0); 1061 mLeMaximumAdvertisingDataLength = 1062 (0xFF & ((int) val[18])) + ((0xFF & ((int) val[19])) << 8); 1063 mDynamicAudioBufferSizeSupportedCodecsGroup1 = 1064 ((0xFF & ((int) val[21])) << 8) + (0xFF & ((int) val[20])); 1065 mDynamicAudioBufferSizeSupportedCodecsGroup2 = 1066 ((0xFF & ((int) val[23])) << 8) + (0xFF & ((int) val[22])); 1067 mIsLePeriodicAdvertisingSyncTransferSenderSupported = ((0xFF & ((int) val[24])) != 0); 1068 mIsLeConnectedIsochronousStreamCentralSupported = ((0xFF & ((int) val[25])) != 0); 1069 mIsLeIsochronousBroadcasterSupported = ((0xFF & ((int) val[26])) != 0); 1070 mIsLePeriodicAdvertisingSyncTransferRecipientSupported = ((0xFF & ((int) val[27])) != 0); 1071 mIsOffloadedTransportDiscoveryDataScanSupported = ((0x01 & ((int) val[28])) != 0); 1072 1073 Log.d(TAG, "BT_PROPERTY_LOCAL_LE_FEATURES: update from BT controller" 1074 + " mNumOfAdvertisementInstancesSupported = " 1075 + mNumOfAdvertisementInstancesSupported + " mRpaOffloadSupported = " 1076 + mRpaOffloadSupported + " mNumOfOffloadedIrkSupported = " 1077 + mNumOfOffloadedIrkSupported + " mNumOfOffloadedScanFilterSupported = " 1078 + mNumOfOffloadedScanFilterSupported + " mOffloadedScanResultStorageBytes= " 1079 + mOffloadedScanResultStorageBytes + " mIsActivityAndEnergyReporting = " 1080 + mIsActivityAndEnergyReporting + " mVersSupported = " + mVersSupported 1081 + " mTotNumOfTrackableAdv = " + mTotNumOfTrackableAdv 1082 + " mIsExtendedScanSupported = " + mIsExtendedScanSupported 1083 + " mIsDebugLogSupported = " + mIsDebugLogSupported + " mIsLe2MPhySupported = " 1084 + mIsLe2MPhySupported + " mIsLeCodedPhySupported = " + mIsLeCodedPhySupported 1085 + " mIsLeExtendedAdvertisingSupported = " + mIsLeExtendedAdvertisingSupported 1086 + " mIsLePeriodicAdvertisingSupported = " + mIsLePeriodicAdvertisingSupported 1087 + " mLeMaximumAdvertisingDataLength = " + mLeMaximumAdvertisingDataLength 1088 + " mDynamicAudioBufferSizeSupportedCodecsGroup1 = " 1089 + mDynamicAudioBufferSizeSupportedCodecsGroup1 1090 + " mDynamicAudioBufferSizeSupportedCodecsGroup2 = " 1091 + mDynamicAudioBufferSizeSupportedCodecsGroup2 1092 + " mIsLePeriodicAdvertisingSyncTransferSenderSupported = " 1093 + mIsLePeriodicAdvertisingSyncTransferSenderSupported 1094 + " mIsLeConnectedIsochronousStreamCentralSupported = " 1095 + mIsLeConnectedIsochronousStreamCentralSupported 1096 + " mIsLeIsochronousBroadcasterSupported = " 1097 + mIsLeIsochronousBroadcasterSupported 1098 + " mIsLePeriodicAdvertisingSyncTransferRecipientSupported = " 1099 + mIsLePeriodicAdvertisingSyncTransferRecipientSupported 1100 + " mIsOffloadedTransportDiscoveryDataScanSupported = " 1101 + mIsOffloadedTransportDiscoveryDataScanSupported); 1102 invalidateIsOffloadedFilteringSupportedCache(); 1103 } 1104 updateDynamicAudioBufferSupport(byte[] val)1105 private void updateDynamicAudioBufferSupport(byte[] val) { 1106 // bufferConstraints is the table indicates the capability of all the codecs 1107 // with buffer time. The raw is codec number, and the column is buffer type. There are 3 1108 // buffer types - default/maximum/minimum. 1109 // The maximum number of raw is BUFFER_CODEC_MAX_NUM(32). 1110 // The maximum number of column is BUFFER_TYPE_MAX(3). 1111 // The array element indicates the buffer time, the size is two octet. 1112 mBufferConstraintList = new ArrayList<BufferConstraint>(); 1113 1114 for (int i = 0; i < BufferConstraints.BUFFER_CODEC_MAX_NUM; i++) { 1115 int defaultBufferTime = ((0xFF & ((int) val[i * 6 + 1])) << 8) 1116 + (0xFF & ((int) val[i * 6])); 1117 int maximumBufferTime = ((0xFF & ((int) val[i * 6 + 3])) << 8) 1118 + (0xFF & ((int) val[i * 6 + 2])); 1119 int minimumBufferTime = ((0xFF & ((int) val[i * 6 + 5])) << 8) 1120 + (0xFF & ((int) val[i * 6 + 4])); 1121 BufferConstraint bufferConstraint = new BufferConstraint(defaultBufferTime, 1122 maximumBufferTime, minimumBufferTime); 1123 mBufferConstraintList.add(bufferConstraint); 1124 } 1125 } 1126 onBluetoothReady()1127 void onBluetoothReady() { 1128 debugLog("onBluetoothReady, state=" + BluetoothAdapter.nameForState(getState()) 1129 + ", ScanMode=" + mScanMode); 1130 1131 synchronized (mObject) { 1132 // Reset adapter and profile connection states 1133 setConnectionState(BluetoothAdapter.STATE_DISCONNECTED); 1134 mProfileConnectionState.clear(); 1135 invalidateGetProfileConnectionStateCache(); 1136 mProfilesConnected = 0; 1137 mProfilesConnecting = 0; 1138 mProfilesDisconnecting = 0; 1139 // adapterPropertyChangedCallback has already been received. Set the scan mode. 1140 setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE); 1141 // This keeps NV up-to date on first-boot after flash. 1142 setDiscoverableTimeout(mDiscoverableTimeout); 1143 } 1144 } 1145 onBleDisable()1146 void onBleDisable() { 1147 // Sequence BLE_ON to STATE_OFF - that is _complete_ OFF state. 1148 debugLog("onBleDisable"); 1149 // Set the scan_mode to NONE (no incoming connections). 1150 setScanMode(BluetoothAdapter.SCAN_MODE_NONE); 1151 } 1152 discoveryStateChangeCallback(int state)1153 void discoveryStateChangeCallback(int state) { 1154 infoLog("Callback:discoveryStateChangeCallback with state:" + state); 1155 synchronized (mObject) { 1156 Intent intent; 1157 if (state == AbstractionLayer.BT_DISCOVERY_STOPPED) { 1158 mDiscovering = false; 1159 mService.clearDiscoveringPackages(); 1160 mDiscoveryEndMs = System.currentTimeMillis(); 1161 intent = new Intent(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); 1162 Utils.sendBroadcast(mService, intent, BLUETOOTH_SCAN, 1163 getBroadcastOptionsForDiscoveryFinished()); 1164 } else if (state == AbstractionLayer.BT_DISCOVERY_STARTED) { 1165 mDiscovering = true; 1166 mDiscoveryEndMs = System.currentTimeMillis() + DEFAULT_DISCOVERY_TIMEOUT_MS; 1167 intent = new Intent(BluetoothAdapter.ACTION_DISCOVERY_STARTED); 1168 Utils.sendBroadcast(mService, intent, BLUETOOTH_SCAN, 1169 Utils.getTempAllowlistBroadcastOptions()); 1170 } 1171 } 1172 } 1173 1174 /** 1175 * @return broadcast options for ACTION_DISCOVERY_FINISHED broadcast 1176 */ getBroadcastOptionsForDiscoveryFinished()1177 private static @NonNull Bundle getBroadcastOptionsForDiscoveryFinished() { 1178 final BroadcastOptions options = Utils.getTempBroadcastOptions(); 1179 if (SdkLevel.isAtLeastU()) { 1180 options.setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT); 1181 options.setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE); 1182 } 1183 return options.toBundle(); 1184 } 1185 1186 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) dump(FileDescriptor fd, PrintWriter writer, String[] args)1187 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 1188 writer.println(TAG); 1189 writer.println(" " + "Name: " + getName()); 1190 writer.println(" " + "Address: " + Utils.getAddressStringFromByte(mAddress)); 1191 writer.println(" " + "ScanMode: " + dumpScanMode(getScanMode())); 1192 writer.println(" " + "ConnectionState: " + dumpConnectionState(getConnectionState())); 1193 writer.println(" " + "State: " + BluetoothAdapter.nameForState(getState())); 1194 writer.println(" " + "MaxConnectedAudioDevices: " + getMaxConnectedAudioDevices()); 1195 writer.println(" " + "A2dpOffloadEnabled: " + mA2dpOffloadEnabled); 1196 writer.println(" " + "Discovering: " + mDiscovering); 1197 writer.println(" " + "DiscoveryEndMs: " + mDiscoveryEndMs); 1198 1199 writer.println(" " + "Bonded devices:"); 1200 StringBuilder sb = new StringBuilder(); 1201 for (BluetoothDevice device : mBondedDevices) { 1202 String address = device.getAddress(); 1203 String identityAddress = mService.getIdentityAddress(address); 1204 if (identityAddress.equals(address)) { 1205 writer.println(" " + address 1206 + " [" + dumpDeviceType(device.getType()) + "] " 1207 + Utils.getName(device)); 1208 } else { 1209 sb.append(" " + address + " => " + identityAddress 1210 + " [" + dumpDeviceType(device.getType()) + "] " 1211 + Utils.getName(device) + "\n"); 1212 } 1213 } 1214 writer.println(sb.toString()); 1215 1216 writer.println(" " + "Scan Mode Changes:"); 1217 for (String log : mScanModeChanges) { 1218 writer.println(" " + log); 1219 } 1220 1221 } 1222 dumpDeviceType(int deviceType)1223 private String dumpDeviceType(int deviceType) { 1224 switch (deviceType) { 1225 case BluetoothDevice.DEVICE_TYPE_UNKNOWN: 1226 return " ???? "; 1227 case BluetoothDevice.DEVICE_TYPE_CLASSIC: 1228 return "BR/EDR"; 1229 case BluetoothDevice.DEVICE_TYPE_LE: 1230 return " LE "; 1231 case BluetoothDevice.DEVICE_TYPE_DUAL: 1232 return " DUAL "; 1233 default: 1234 return "Invalid device type: " + deviceType; 1235 } 1236 } 1237 dumpConnectionState(int state)1238 private String dumpConnectionState(int state) { 1239 switch (state) { 1240 case BluetoothAdapter.STATE_DISCONNECTED: 1241 return "STATE_DISCONNECTED"; 1242 case BluetoothAdapter.STATE_DISCONNECTING: 1243 return "STATE_DISCONNECTING"; 1244 case BluetoothAdapter.STATE_CONNECTING: 1245 return "STATE_CONNECTING"; 1246 case BluetoothAdapter.STATE_CONNECTED: 1247 return "STATE_CONNECTED"; 1248 default: 1249 return "Unknown Connection State " + state; 1250 } 1251 } 1252 dumpScanMode(int scanMode)1253 private String dumpScanMode(int scanMode) { 1254 switch (scanMode) { 1255 case BluetoothAdapter.SCAN_MODE_NONE: 1256 return "SCAN_MODE_NONE"; 1257 case BluetoothAdapter.SCAN_MODE_CONNECTABLE: 1258 return "SCAN_MODE_CONNECTABLE"; 1259 case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE: 1260 return "SCAN_MODE_CONNECTABLE_DISCOVERABLE"; 1261 default: 1262 return "Unknown Scan Mode " + scanMode; 1263 } 1264 } 1265 infoLog(String msg)1266 private static void infoLog(String msg) { 1267 if (VDBG) { 1268 Log.i(TAG, msg); 1269 } 1270 } 1271 debugLog(String msg)1272 private static void debugLog(String msg) { 1273 if (DBG) { 1274 Log.d(TAG, msg); 1275 } 1276 } 1277 errorLog(String msg)1278 private static void errorLog(String msg) { 1279 Log.e(TAG, msg); 1280 } 1281 } 1282