1 /* 2 * Copyright 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.server.audio; 17 18 import static android.media.audio.Flags.scoManagedByAudio; 19 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.app.compat.CompatChanges; 23 import android.bluetooth.BluetoothDevice; 24 import android.bluetooth.BluetoothHeadset; 25 import android.bluetooth.BluetoothProfile; 26 import android.compat.annotation.ChangeId; 27 import android.compat.annotation.EnabledSince; 28 import android.content.ContentResolver; 29 import android.content.Context; 30 import android.content.Intent; 31 import android.media.AudioAttributes; 32 import android.media.AudioDeviceAttributes; 33 import android.media.AudioDeviceInfo; 34 import android.media.AudioManager; 35 import android.media.AudioManager.AudioDeviceCategory; 36 import android.media.AudioPlaybackConfiguration; 37 import android.media.AudioRecordingConfiguration; 38 import android.media.AudioRoutesInfo; 39 import android.media.AudioSystem; 40 import android.media.BluetoothProfileConnectionInfo; 41 import android.media.IAudioRoutesObserver; 42 import android.media.ICapturePresetDevicesRoleDispatcher; 43 import android.media.ICommunicationDeviceDispatcher; 44 import android.media.IStrategyNonDefaultDevicesDispatcher; 45 import android.media.IStrategyPreferredDevicesDispatcher; 46 import android.media.MediaMetrics; 47 import android.media.audiopolicy.AudioProductStrategy; 48 import android.os.Binder; 49 import android.os.Handler; 50 import android.os.IBinder; 51 import android.os.Looper; 52 import android.os.Message; 53 import android.os.PowerManager; 54 import android.os.RemoteCallbackList; 55 import android.os.RemoteException; 56 import android.os.SystemClock; 57 import android.os.UserHandle; 58 import android.provider.Settings; 59 import android.sysprop.BluetoothProperties; 60 import android.text.TextUtils; 61 import android.util.Log; 62 import android.util.Pair; 63 import android.util.PrintWriterPrinter; 64 65 import com.android.internal.annotations.GuardedBy; 66 import com.android.server.utils.EventLogger; 67 68 import java.io.PrintWriter; 69 import java.util.ArrayList; 70 import java.util.Arrays; 71 import java.util.Collection; 72 import java.util.HashSet; 73 import java.util.LinkedList; 74 import java.util.List; 75 import java.util.NoSuchElementException; 76 import java.util.Objects; 77 import java.util.Set; 78 import java.util.concurrent.atomic.AtomicBoolean; 79 80 /** 81 * @hide 82 * (non final for mocking/spying) 83 */ 84 public class AudioDeviceBroker { 85 86 private static final String TAG = "AS.AudioDeviceBroker"; 87 88 private static final long BROKER_WAKELOCK_TIMEOUT_MS = 5000; //5s 89 90 /*package*/ static final int BTA2DP_DOCK_TIMEOUT_MS = 8000; 91 // Timeout for connection to bluetooth headset service 92 /*package*/ static final int BT_HEADSET_CNCT_TIMEOUT_MS = 3000; 93 94 // Delay before checking it music should be unmuted after processing an A2DP message 95 private static final int BTA2DP_MUTE_CHECK_DELAY_MS = 100; 96 97 private final @NonNull AudioService mAudioService; 98 private final @NonNull Context mContext; 99 private final @NonNull AudioSystemAdapter mAudioSystem; 100 101 /** ID for Communication strategy retrieved form audio policy manager */ 102 /*package*/ int mCommunicationStrategyId = -1; 103 104 /** ID for Accessibility strategy retrieved form audio policy manager */ 105 private int mAccessibilityStrategyId = -1; 106 107 108 /** Active communication device reported by audio policy manager */ 109 /*package*/ AudioDeviceInfo mActiveCommunicationDevice; 110 /** Last preferred device set for communication strategy */ 111 private AudioDeviceAttributes mPreferredCommunicationDevice; 112 113 // Manages all connected devices, only ever accessed on the message loop 114 private final AudioDeviceInventory mDeviceInventory; 115 // Manages notifications to BT service 116 private final BtHelper mBtHelper; 117 // Adapter for system_server-reserved operations 118 private final SystemServerAdapter mSystemServer; 119 120 121 //------------------------------------------------------------------- 122 // we use a different lock than mDeviceStateLock so as not to create 123 // lock contention between enqueueing a message and handling them 124 private static final Object sLastDeviceConnectionMsgTimeLock = new Object(); 125 @GuardedBy("sLastDeviceConnectionMsgTimeLock") 126 private static long sLastDeviceConnectMsgTime = 0; 127 128 // General lock to be taken whenever the state of the audio devices is to be checked or changed 129 private final Object mDeviceStateLock = new Object(); 130 131 // Request to override default use of A2DP for media. 132 private AtomicBoolean mBluetoothA2dpEnabled = new AtomicBoolean(false); 133 134 // lock always taken when accessing AudioService.mSetModeDeathHandlers 135 // TODO do not "share" the lock between AudioService and BtHelpr, see b/123769055 136 /*package*/ final Object mSetModeLock = new Object(); 137 138 /** AudioModeInfo contains information on current audio mode owner 139 * communicated by AudioService */ 140 /* package */ static final class AudioModeInfo { 141 /** Current audio mode */ 142 final int mMode; 143 /** PID of current audio mode owner */ 144 final int mPid; 145 /** UID of current audio mode owner */ 146 final int mUid; 147 AudioModeInfo(int mode, int pid, int uid)148 AudioModeInfo(int mode, int pid, int uid) { 149 mMode = mode; 150 mPid = pid; 151 mUid = uid; 152 } 153 154 @Override toString()155 public String toString() { 156 return "AudioModeInfo: mMode=" + AudioSystem.modeToString(mMode) 157 + ", mPid=" + mPid 158 + ", mUid=" + mUid; 159 } 160 }; 161 162 private AudioModeInfo mAudioModeOwner = new AudioModeInfo(AudioSystem.MODE_NORMAL, 0, 0); 163 164 /** 165 * Indicates that default communication device is chosen by routing rules in audio policy 166 * manager and not forced by AudioDeviceBroker. 167 */ 168 @ChangeId 169 @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.S_V2) 170 public static final long USE_SET_COMMUNICATION_DEVICE = 243827847L; 171 172 /** Indicates if headset profile connection and SCO audio control use the new implementation 173 * aligned with other BT profiles. True if both the feature flag Flags.scoManagedByAudio() and 174 * the system property audio.sco.managed.by.audio are true. 175 */ 176 private final boolean mScoManagedByAudio; isScoManagedByAudio()177 /*package*/ boolean isScoManagedByAudio() { 178 return mScoManagedByAudio; 179 } 180 181 //------------------------------------------------------------------- AudioDeviceBroker(@onNull Context context, @NonNull AudioService service, @NonNull AudioSystemAdapter audioSystem)182 /*package*/ AudioDeviceBroker(@NonNull Context context, @NonNull AudioService service, 183 @NonNull AudioSystemAdapter audioSystem) { 184 mContext = context; 185 mAudioService = service; 186 mBtHelper = new BtHelper(this, context); 187 mDeviceInventory = new AudioDeviceInventory(this); 188 mSystemServer = SystemServerAdapter.getDefaultAdapter(mContext); 189 mAudioSystem = audioSystem; 190 mScoManagedByAudio = scoManagedByAudio() 191 && BluetoothProperties.isScoManagedByAudioEnabled().orElse(false); 192 init(); 193 } 194 195 /** for test purposes only, inject AudioDeviceInventory and adapter for operations running 196 * in system_server */ AudioDeviceBroker(@onNull Context context, @NonNull AudioService service, @NonNull AudioDeviceInventory mockDeviceInventory, @NonNull SystemServerAdapter mockSystemServer, @NonNull AudioSystemAdapter audioSystem)197 AudioDeviceBroker(@NonNull Context context, @NonNull AudioService service, 198 @NonNull AudioDeviceInventory mockDeviceInventory, 199 @NonNull SystemServerAdapter mockSystemServer, 200 @NonNull AudioSystemAdapter audioSystem) { 201 mContext = context; 202 mAudioService = service; 203 mBtHelper = new BtHelper(this, context); 204 mDeviceInventory = mockDeviceInventory; 205 mSystemServer = mockSystemServer; 206 mAudioSystem = audioSystem; 207 mScoManagedByAudio = scoManagedByAudio() 208 && BluetoothProperties.isScoManagedByAudioEnabled().orElse(false); 209 init(); 210 } 211 initRoutingStrategyIds()212 private void initRoutingStrategyIds() { 213 List<AudioProductStrategy> strategies = AudioProductStrategy.getAudioProductStrategies(); 214 mCommunicationStrategyId = -1; 215 mAccessibilityStrategyId = -1; 216 for (AudioProductStrategy strategy : strategies) { 217 if (mCommunicationStrategyId == -1 218 && strategy.getAudioAttributesForLegacyStreamType( 219 AudioSystem.STREAM_VOICE_CALL) != null) { 220 mCommunicationStrategyId = strategy.getId(); 221 } 222 if (mAccessibilityStrategyId == -1 223 && strategy.getAudioAttributesForLegacyStreamType( 224 AudioSystem.STREAM_ACCESSIBILITY) != null) { 225 mAccessibilityStrategyId = strategy.getId(); 226 } 227 } 228 } 229 init()230 private void init() { 231 setupMessaging(mContext); 232 233 initAudioHalBluetoothState(); 234 initRoutingStrategyIds(); 235 mPreferredCommunicationDevice = null; 236 updateActiveCommunicationDevice(); 237 238 mSystemServer.registerUserStartedReceiver(mContext); 239 } 240 getContext()241 /*package*/ Context getContext() { 242 return mContext; 243 } 244 245 //--------------------------------------------------------------------- 246 // Communication from AudioService 247 // All methods are asynchronous and never block 248 // All permission checks are done in AudioService, all incoming calls are considered "safe" 249 // All post* methods are asynchronous 250 onSystemReady()251 /*package*/ void onSystemReady() { 252 synchronized (mSetModeLock) { 253 synchronized (mDeviceStateLock) { 254 mAudioModeOwner = mAudioService.getAudioModeOwner(); 255 mBtHelper.onSystemReady(); 256 } 257 } 258 } 259 onAudioServerDied()260 /*package*/ void onAudioServerDied() { 261 // restore devices 262 sendMsgNoDelay(MSG_RESTORE_DEVICES, SENDMSG_REPLACE); 263 } 264 setForceUse_Async(int useCase, int config, String eventSource)265 /*package*/ void setForceUse_Async(int useCase, int config, String eventSource) { 266 sendIILMsgNoDelay(MSG_IIL_SET_FORCE_USE, SENDMSG_QUEUE, 267 useCase, config, eventSource); 268 } 269 toggleHdmiIfConnected_Async()270 /*package*/ void toggleHdmiIfConnected_Async() { 271 sendMsgNoDelay(MSG_TOGGLE_HDMI, SENDMSG_QUEUE); 272 } 273 274 /** 275 * Handle BluetoothHeadset intents where the action is one of 276 * {@link BluetoothHeadset#ACTION_ACTIVE_DEVICE_CHANGED} or 277 * {@link BluetoothHeadset#ACTION_AUDIO_STATE_CHANGED}. 278 * @param intent the Intent received from BT service 279 */ onReceiveBtEvent(@onNull Intent intent)280 private void onReceiveBtEvent(@NonNull Intent intent) { 281 mBtHelper.onReceiveBtEvent(intent); 282 } 283 284 @GuardedBy("mDeviceStateLock") onSetBtScoActiveDevice(BluetoothDevice btDevice)285 /*package*/ void onSetBtScoActiveDevice(BluetoothDevice btDevice) { 286 mBtHelper.onSetBtScoActiveDevice(btDevice); 287 } 288 setBluetoothA2dpOn_Async(boolean on, String source)289 /*package*/ void setBluetoothA2dpOn_Async(boolean on, String source) { 290 boolean wasOn = mBluetoothA2dpEnabled.getAndSet(on); 291 // do not mute music if we do not anticipate a change in A2DP ON state 292 sendLMsgNoDelay(wasOn == on 293 ? MSG_L_SET_FORCE_BT_A2DP_USE_NO_MUTE : MSG_L_SET_FORCE_BT_A2DP_USE, 294 SENDMSG_REPLACE, source); 295 } 296 297 /** 298 * Turns speakerphone on/off 299 * @param on true to enable speakerphone 300 * @param eventSource for logging purposes 301 */ setSpeakerphoneOn( IBinder cb, int uid, boolean on, boolean isPrivileged, String eventSource)302 /*package*/ void setSpeakerphoneOn( 303 IBinder cb, int uid, boolean on, boolean isPrivileged, String eventSource) { 304 305 if (AudioService.DEBUG_COMM_RTE) { 306 Log.v(TAG, "setSpeakerphoneOn, on: " + on + " uid: " + uid); 307 } 308 postSetCommunicationDeviceForClient(new CommunicationDeviceInfo( 309 cb, uid, new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_SPEAKER, ""), 310 on, BtHelper.SCO_MODE_UNDEFINED, eventSource, isPrivileged)); 311 } 312 313 private static final long SET_COMMUNICATION_DEVICE_TIMEOUT_MS = 3000; 314 315 /** synchronization for setCommunicationDevice() and getCommunicationDevice */ 316 private final Object mCommunicationDeviceLock = new Object(); 317 @GuardedBy("mCommunicationDeviceLock") 318 private int mCommunicationDeviceUpdateCount = 0; 319 320 /** 321 * Select device for use for communication use cases. 322 * @param cb Client binder for death detection 323 * @param uid Client uid 324 * @param device Device selected or null to unselect. 325 * @param eventSource for logging purposes 326 * @return false if there is no device and no communication client 327 */ setCommunicationDevice(IBinder cb, int uid, AudioDeviceInfo device, boolean isPrivileged, String eventSource)328 /*package*/ boolean setCommunicationDevice(IBinder cb, int uid, AudioDeviceInfo device, 329 boolean isPrivileged, String eventSource) { 330 331 if (AudioService.DEBUG_COMM_RTE) { 332 Log.v(TAG, "setCommunicationDevice, device: " + device + ", uid: " + uid); 333 } 334 335 synchronized (mDeviceStateLock) { 336 if (device == null) { 337 CommunicationRouteClient client = getCommunicationRouteClientForUid(uid); 338 if (client == null) { 339 return false; 340 } 341 } 342 } 343 synchronized (mCommunicationDeviceLock) { 344 mCommunicationDeviceUpdateCount++; 345 AudioDeviceAttributes deviceAttr = 346 (device != null) ? new AudioDeviceAttributes(device) : null; 347 CommunicationDeviceInfo deviceInfo = new CommunicationDeviceInfo(cb, uid, deviceAttr, 348 device != null, BtHelper.SCO_MODE_UNDEFINED, eventSource, isPrivileged); 349 postSetCommunicationDeviceForClient(deviceInfo); 350 } 351 return true; 352 } 353 354 /** 355 * Sets or resets the communication device for matching client. If no client matches and the 356 * request is to reset for a given device (deviceInfo.mOn == false), the method is a noop. 357 * @param deviceInfo information on the device and requester {@link #CommunicationDeviceInfo} 358 */ 359 @GuardedBy("mDeviceStateLock") onSetCommunicationDeviceForClient(CommunicationDeviceInfo deviceInfo)360 /*package*/ void onSetCommunicationDeviceForClient(CommunicationDeviceInfo deviceInfo) { 361 if (AudioService.DEBUG_COMM_RTE) { 362 Log.v(TAG, "onSetCommunicationDeviceForClient: " + deviceInfo); 363 } 364 if (!deviceInfo.mOn) { 365 CommunicationRouteClient client = getCommunicationRouteClientForUid(deviceInfo.mUid); 366 if (client == null || (deviceInfo.mDevice != null 367 && !deviceInfo.mDevice.equals(client.getDevice()))) { 368 return; 369 } 370 } 371 372 AudioDeviceAttributes device = deviceInfo.mOn ? deviceInfo.mDevice : null; 373 setCommunicationRouteForClient(deviceInfo.mCb, deviceInfo.mUid, device, 374 deviceInfo.mScoAudioMode, deviceInfo.mIsPrivileged, deviceInfo.mEventSource); 375 } 376 377 @GuardedBy("mDeviceStateLock") setCommunicationRouteForClient( IBinder cb, int uid, AudioDeviceAttributes device, int scoAudioMode, boolean isPrivileged, String eventSource)378 /*package*/ void setCommunicationRouteForClient( 379 IBinder cb, int uid, AudioDeviceAttributes device, 380 int scoAudioMode, boolean isPrivileged, String eventSource) { 381 382 if (AudioService.DEBUG_COMM_RTE) { 383 Log.v(TAG, "setCommunicationRouteForClient: device: " + device 384 + ", eventSource: " + eventSource); 385 } 386 AudioService.sDeviceLogger.enqueue((new EventLogger.StringEvent( 387 "setCommunicationRouteForClient for uid: " + uid 388 + " device: " + device + " isPrivileged: " + isPrivileged 389 + " from API: " + eventSource)).printLog(TAG)); 390 391 final boolean wasBtScoRequested = isBluetoothScoRequested(); 392 CommunicationRouteClient client; 393 394 // Save previous client route in case of failure to start BT SCO audio 395 AudioDeviceAttributes prevClientDevice = null; 396 boolean prevPrivileged = false; 397 client = getCommunicationRouteClientForUid(uid); 398 if (client != null) { 399 prevClientDevice = client.getDevice(); 400 prevPrivileged = client.isPrivileged(); 401 } 402 403 if (device != null) { 404 client = addCommunicationRouteClient(cb, uid, device, isPrivileged); 405 if (client == null) { 406 Log.w(TAG, "setCommunicationRouteForClient: could not add client for uid: " 407 + uid + " and device: " + device); 408 } 409 } else { 410 client = removeCommunicationRouteClient(cb, true); 411 } 412 if (client == null) { 413 return; 414 } 415 if (!mScoManagedByAudio) { 416 boolean isBtScoRequested = isBluetoothScoRequested(); 417 if (isBtScoRequested && (!wasBtScoRequested || !isBluetoothScoActive())) { 418 if (!mBtHelper.startBluetoothSco(scoAudioMode, eventSource)) { 419 Log.w(TAG, "setCommunicationRouteForClient: failure to start BT SCO for uid: " 420 + uid); 421 // clean up or restore previous client selection 422 if (prevClientDevice != null) { 423 addCommunicationRouteClient(cb, uid, prevClientDevice, prevPrivileged); 424 } else { 425 removeCommunicationRouteClient(cb, true); 426 } 427 postBroadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 428 } 429 } else if (!isBtScoRequested && wasBtScoRequested) { 430 mBtHelper.stopBluetoothSco(eventSource); 431 } 432 } 433 // In BT classic for communication, the device changes from a2dp to sco device, but for 434 // LE Audio it stays the same and we must trigger the proper stream volume alignment, if 435 // LE Audio communication device is activated after the audio system has already switched to 436 // MODE_IN_CALL mode. 437 if (isBluetoothLeAudioRequested() && device != null) { 438 final int streamType = mAudioService.getBluetoothContextualVolumeStream(); 439 final int leAudioVolIndex = getVssVolumeForDevice(streamType, device.getInternalType()); 440 final int leAudioMaxVolIndex = getMaxVssVolumeForStream(streamType); 441 if (AudioService.DEBUG_COMM_RTE) { 442 Log.v(TAG, "setCommunicationRouteForClient restoring LE Audio device volume lvl."); 443 } 444 postSetLeAudioVolumeIndex(leAudioVolIndex, leAudioMaxVolIndex, streamType); 445 } 446 447 updateCommunicationRoute(eventSource); 448 } 449 450 /** 451 * Returns the communication client with the highest priority: 452 * - 1) the client which is currently also controlling the audio mode 453 * - 2) the first client in the stack if there is no audio mode owner 454 * - 3) no client otherwise 455 * @return CommunicationRouteClient the client driving the communication use case routing. 456 */ 457 @GuardedBy("mDeviceStateLock") topCommunicationRouteClient()458 private CommunicationRouteClient topCommunicationRouteClient() { 459 for (CommunicationRouteClient crc : mCommunicationRouteClients) { 460 if (crc.getUid() == mAudioModeOwner.mUid) { 461 return crc; 462 } 463 } 464 if (!mCommunicationRouteClients.isEmpty() && mAudioModeOwner.mPid == 0 465 && mCommunicationRouteClients.get(0).isActive()) { 466 return mCommunicationRouteClients.get(0); 467 } 468 return null; 469 } 470 471 /** 472 * Returns the device currently requested for communication use case. 473 * Use the device requested by the communication route client selected by 474 * {@link #topCommunicationRouteClient()} if any or none otherwise. 475 * @return AudioDeviceAttributes the requested device for communication. 476 */ 477 @GuardedBy("mDeviceStateLock") requestedCommunicationDevice()478 private AudioDeviceAttributes requestedCommunicationDevice() { 479 CommunicationRouteClient crc = topCommunicationRouteClient(); 480 AudioDeviceAttributes device = crc != null ? crc.getDevice() : null; 481 if (AudioService.DEBUG_COMM_RTE) { 482 Log.v(TAG, "requestedCommunicationDevice: " 483 + device + " mAudioModeOwner: " + mAudioModeOwner.toString()); 484 } 485 return device; 486 } 487 488 private static final int[] VALID_COMMUNICATION_DEVICE_TYPES = { 489 AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, 490 AudioDeviceInfo.TYPE_BLUETOOTH_SCO, 491 AudioDeviceInfo.TYPE_WIRED_HEADSET, 492 AudioDeviceInfo.TYPE_USB_HEADSET, 493 AudioDeviceInfo.TYPE_BUILTIN_EARPIECE, 494 AudioDeviceInfo.TYPE_WIRED_HEADPHONES, 495 AudioDeviceInfo.TYPE_HEARING_AID, 496 AudioDeviceInfo.TYPE_BLE_HEADSET, 497 AudioDeviceInfo.TYPE_USB_DEVICE, 498 AudioDeviceInfo.TYPE_BLE_SPEAKER, 499 AudioDeviceInfo.TYPE_LINE_ANALOG, 500 AudioDeviceInfo.TYPE_HDMI, 501 AudioDeviceInfo.TYPE_AUX_LINE 502 }; 503 isValidCommunicationDevice(@onNull AudioDeviceInfo device)504 /*package */ static boolean isValidCommunicationDevice(@NonNull AudioDeviceInfo device) { 505 Objects.requireNonNull(device, "device must not be null"); 506 return device.isSink() && isValidCommunicationDeviceType(device.getType()); 507 } 508 isValidCommunicationDeviceType(int deviceType)509 private static boolean isValidCommunicationDeviceType(int deviceType) { 510 for (int type : VALID_COMMUNICATION_DEVICE_TYPES) { 511 if (deviceType == type) { 512 return true; 513 } 514 } 515 return false; 516 } 517 518 /*package */ postCheckCommunicationDeviceRemoval(@onNull AudioDeviceAttributes device)519 void postCheckCommunicationDeviceRemoval(@NonNull AudioDeviceAttributes device) { 520 if (!isValidCommunicationDeviceType( 521 AudioDeviceInfo.convertInternalDeviceToDeviceType(device.getInternalType()))) { 522 return; 523 } 524 sendLMsgNoDelay(MSG_L_CHECK_COMMUNICATION_DEVICE_REMOVAL, SENDMSG_QUEUE, device); 525 } 526 527 @GuardedBy("mDeviceStateLock") onCheckCommunicationDeviceRemoval(@onNull AudioDeviceAttributes device)528 void onCheckCommunicationDeviceRemoval(@NonNull AudioDeviceAttributes device) { 529 if (AudioService.DEBUG_COMM_RTE) { 530 Log.v(TAG, "onCheckCommunicationDeviceRemoval device: " + device.toString()); 531 } 532 for (CommunicationRouteClient crc : mCommunicationRouteClients) { 533 if (device.equals(crc.getDevice())) { 534 if (AudioService.DEBUG_COMM_RTE) { 535 Log.v(TAG, "onCheckCommunicationDeviceRemoval removing client: " 536 + crc.toString()); 537 } 538 // Cancelling the route for this client will remove it from the stack and update 539 // the communication route. 540 CommunicationDeviceInfo deviceInfo = new CommunicationDeviceInfo( 541 crc.getBinder(), crc.getUid(), device, false, 542 BtHelper.SCO_MODE_UNDEFINED, "onCheckCommunicationDeviceRemoval", 543 crc.isPrivileged()); 544 postSetCommunicationDeviceForClient(deviceInfo); 545 } 546 } 547 } 548 549 // check playback or record activity after 6 seconds for UIDs 550 private static final int CHECK_CLIENT_STATE_DELAY_MS = 6000; 551 552 /*package */ postCheckCommunicationRouteClientState(int uid, boolean wasActive, int delay)553 void postCheckCommunicationRouteClientState(int uid, boolean wasActive, int delay) { 554 CommunicationRouteClient client = getCommunicationRouteClientForUid(uid); 555 if (client != null) { 556 sendMsgForCheckClientState(MSG_CHECK_COMMUNICATION_ROUTE_CLIENT_STATE, 557 SENDMSG_REPLACE, 558 uid, 559 wasActive ? 1 : 0, 560 client, 561 delay); 562 } 563 } 564 565 @GuardedBy("mDeviceStateLock") onCheckCommunicationRouteClientState(int uid, boolean wasActive)566 void onCheckCommunicationRouteClientState(int uid, boolean wasActive) { 567 CommunicationRouteClient client = getCommunicationRouteClientForUid(uid); 568 if (client == null) { 569 return; 570 } 571 updateCommunicationRouteClientState(client, wasActive); 572 } 573 574 @GuardedBy("mDeviceStateLock") updateCommunicationRouteClientState( CommunicationRouteClient client, boolean wasActive)575 /*package*/ void updateCommunicationRouteClientState( 576 CommunicationRouteClient client, boolean wasActive) { 577 boolean wasBtScoRequested = isBluetoothScoRequested(); 578 client.setPlaybackActive(mAudioService.isPlaybackActiveForUid(client.getUid())); 579 client.setRecordingActive(mAudioService.isRecordingActiveForUid(client.getUid())); 580 if (wasActive != client.isActive()) { 581 postUpdateCommunicationRouteClient( 582 wasBtScoRequested, "updateCommunicationRouteClientState"); 583 } 584 } 585 586 @GuardedBy("mDeviceStateLock") setForceCommunicationClientStateAndDelayedCheck( CommunicationRouteClient client, boolean forcePlaybackActive, boolean forceRecordingActive)587 /*package*/ void setForceCommunicationClientStateAndDelayedCheck( 588 CommunicationRouteClient client, 589 boolean forcePlaybackActive, 590 boolean forceRecordingActive) { 591 if (client == null) { 592 return; 593 } 594 if (forcePlaybackActive) { 595 client.setPlaybackActive(true); 596 } 597 if (forceRecordingActive) { 598 client.setRecordingActive(true); 599 } 600 postCheckCommunicationRouteClientState( 601 client.getUid(), client.isActive(), CHECK_CLIENT_STATE_DELAY_MS); 602 } 603 getAvailableCommunicationDevices()604 /* package */ static List<AudioDeviceInfo> getAvailableCommunicationDevices() { 605 ArrayList<AudioDeviceInfo> commDevices = new ArrayList<>(); 606 AudioDeviceInfo[] allDevices = 607 AudioManager.getDevicesStatic(AudioManager.GET_DEVICES_OUTPUTS); 608 for (AudioDeviceInfo device : allDevices) { 609 if (isValidCommunicationDevice(device)) { 610 commDevices.add(device); 611 } 612 } 613 return commDevices; 614 } 615 getCommunicationDeviceOfType(int type)616 private @Nullable AudioDeviceInfo getCommunicationDeviceOfType(int type) { 617 return getAvailableCommunicationDevices().stream().filter(d -> d.getType() == type) 618 .findFirst().orElse(null); 619 } 620 621 /** 622 * Returns the device currently requested for communication use case. 623 * @return AudioDeviceInfo the requested device for communication. 624 */ getCommunicationDevice()625 /* package */ AudioDeviceInfo getCommunicationDevice() { 626 synchronized (mCommunicationDeviceLock) { 627 final long start = System.currentTimeMillis(); 628 long elapsed = 0; 629 while (mCommunicationDeviceUpdateCount > 0) { 630 try { 631 mCommunicationDeviceLock.wait( 632 SET_COMMUNICATION_DEVICE_TIMEOUT_MS - elapsed); 633 } catch (InterruptedException e) { 634 Log.w(TAG, "Interrupted while waiting for communication device update."); 635 } 636 elapsed = System.currentTimeMillis() - start; 637 if (elapsed >= SET_COMMUNICATION_DEVICE_TIMEOUT_MS) { 638 Log.e(TAG, "Timeout waiting for communication device update."); 639 break; 640 } 641 } 642 } 643 synchronized (mDeviceStateLock) { 644 return getCommunicationDeviceInt(); 645 } 646 } 647 648 @GuardedBy("mDeviceStateLock") getCommunicationDeviceInt()649 private AudioDeviceInfo getCommunicationDeviceInt() { 650 updateActiveCommunicationDevice(); 651 AudioDeviceInfo device = mActiveCommunicationDevice; 652 // make sure we return a valid communication device (i.e. a device that is allowed by 653 // setCommunicationDevice()) for consistency. 654 if (device != null) { 655 // a digital dock is used instead of the speaker in speakerphone mode and should 656 // be reflected as such 657 if (device.getType() == AudioDeviceInfo.TYPE_DOCK) { 658 device = getCommunicationDeviceOfType(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER); 659 } 660 } 661 // Try to default to earpiece when current communication device is not valid. This can 662 // happen for instance if no call is active. If no earpiece device is available take the 663 // first valid communication device 664 if (device == null || !AudioDeviceBroker.isValidCommunicationDevice(device)) { 665 device = getCommunicationDeviceOfType(AudioDeviceInfo.TYPE_BUILTIN_EARPIECE); 666 if (device == null) { 667 List<AudioDeviceInfo> commDevices = getAvailableCommunicationDevices(); 668 if (!commDevices.isEmpty()) { 669 device = commDevices.get(0); 670 } 671 } 672 } 673 return device; 674 } 675 676 /** 677 * Updates currently active communication device (mActiveCommunicationDevice). 678 */ 679 @GuardedBy("mDeviceStateLock") updateActiveCommunicationDevice()680 void updateActiveCommunicationDevice() { 681 AudioDeviceAttributes device = preferredCommunicationDevice(); 682 if (device == null) { 683 AudioAttributes attr = 684 AudioProductStrategy.getAudioAttributesForStrategyWithLegacyStreamType( 685 AudioSystem.STREAM_VOICE_CALL); 686 List<AudioDeviceAttributes> devices = mAudioSystem.getDevicesForAttributes( 687 attr, false /* forVolume */); 688 if (devices.isEmpty()) { 689 if (mAudioService.isPlatformVoice()) { 690 Log.w(TAG, 691 "updateActiveCommunicationDevice(): no device for phone strategy"); 692 } 693 mActiveCommunicationDevice = null; 694 return; 695 } 696 device = devices.get(0); 697 } 698 mActiveCommunicationDevice = AudioManager.getDeviceInfoFromTypeAndAddress( 699 device.getType(), device.getAddress()); 700 } 701 702 /** 703 * Indicates if the device which type is passed as argument is currently resquested to be used 704 * for communication. 705 * @param deviceType the device type the query applies to. 706 * @return true if this device type is requested for communication. 707 */ isDeviceRequestedForCommunication(int deviceType)708 private boolean isDeviceRequestedForCommunication(int deviceType) { 709 synchronized (mDeviceStateLock) { 710 AudioDeviceAttributes device = requestedCommunicationDevice(); 711 return device != null && device.getType() == deviceType; 712 } 713 } 714 715 /** 716 * Indicates if the device which type is passed as argument is currently either resquested 717 * to be used for communication or selected for an other reason (e.g bluetooth SCO audio 718 * is active for SCO device). 719 * @param deviceType the device type the query applies to. 720 * @return true if this device type is requested for communication. 721 */ isDeviceOnForCommunication(int deviceType)722 private boolean isDeviceOnForCommunication(int deviceType) { 723 synchronized (mDeviceStateLock) { 724 AudioDeviceAttributes device = preferredCommunicationDevice(); 725 return device != null && device.getType() == deviceType; 726 } 727 } 728 729 /** 730 * Indicates if the device which type is passed as argument is active for communication. 731 * Active means not only currently used by audio policy manager for communication strategy 732 * but also explicitly requested for use by communication strategy. 733 * @param deviceType the device type the query applies to. 734 * @return true if this device type is requested for communication. 735 */ isDeviceActiveForCommunication(int deviceType)736 private boolean isDeviceActiveForCommunication(int deviceType) { 737 return mActiveCommunicationDevice != null 738 && mActiveCommunicationDevice.getType() == deviceType 739 && mPreferredCommunicationDevice != null 740 && mPreferredCommunicationDevice.getType() == deviceType; 741 } 742 743 /** 744 * Indicates if preferred route selection for communication is speakerphone. 745 * @return true if speakerphone is active, false otherwise. 746 */ isSpeakerphoneOn()747 /*package*/ boolean isSpeakerphoneOn() { 748 return isDeviceOnForCommunication(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER); 749 } 750 isSpeakerphoneActive()751 private boolean isSpeakerphoneActive() { 752 return isDeviceActiveForCommunication(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER); 753 } 754 755 /** 756 * Helper method on top of isDeviceRequestedForCommunication() indicating if 757 * Bluetooth SCO ON is currently requested or not. 758 * @return true if Bluetooth SCO ON is requested, false otherwise. 759 */ isBluetoothScoRequested()760 /*package*/ boolean isBluetoothScoRequested() { 761 return isDeviceRequestedForCommunication(AudioDeviceInfo.TYPE_BLUETOOTH_SCO); 762 } 763 764 /** 765 * Helper method on top of isDeviceRequestedForCommunication() indicating if 766 * Bluetooth LE Audio communication device is currently requested or not. 767 * @return true if Bluetooth LE Audio device is requested, false otherwise. 768 */ isBluetoothLeAudioRequested()769 /*package*/ boolean isBluetoothLeAudioRequested() { 770 return isDeviceRequestedForCommunication(AudioDeviceInfo.TYPE_BLE_HEADSET) 771 || isDeviceRequestedForCommunication(AudioDeviceInfo.TYPE_BLE_SPEAKER); 772 } 773 774 /** 775 * Indicates if preferred route selection for communication is Bluetooth SCO. 776 * @return true if Bluetooth SCO is preferred , false otherwise. 777 */ isBluetoothScoOn()778 /*package*/ boolean isBluetoothScoOn() { 779 return isDeviceOnForCommunication(AudioDeviceInfo.TYPE_BLUETOOTH_SCO); 780 } 781 isBluetoothScoActive()782 /*package*/ boolean isBluetoothScoActive() { 783 return isDeviceActiveForCommunication(AudioDeviceInfo.TYPE_BLUETOOTH_SCO); 784 } 785 isDeviceConnected(@onNull AudioDeviceAttributes device)786 /*package*/ boolean isDeviceConnected(@NonNull AudioDeviceAttributes device) { 787 synchronized (mDeviceStateLock) { 788 return mDeviceInventory.isDeviceConnected(device); 789 } 790 } 791 setWiredDeviceConnectionState(AudioDeviceAttributes attributes, @AudioService.ConnectionState int state, String caller)792 /*package*/ void setWiredDeviceConnectionState(AudioDeviceAttributes attributes, 793 @AudioService.ConnectionState int state, String caller) { 794 //TODO move logging here just like in setBluetooth* methods 795 synchronized (mDeviceStateLock) { 796 mDeviceInventory.setWiredDeviceConnectionState(attributes, state, caller); 797 } 798 } 799 setTestDeviceConnectionState(@onNull AudioDeviceAttributes device, @AudioService.ConnectionState int state)800 /*package*/ void setTestDeviceConnectionState(@NonNull AudioDeviceAttributes device, 801 @AudioService.ConnectionState int state) { 802 synchronized (mDeviceStateLock) { 803 mDeviceInventory.setTestDeviceConnectionState(device, state); 804 } 805 } 806 807 /*package*/ static final class BleVolumeInfo { 808 final int mIndex; 809 final int mMaxIndex; 810 final int mStreamType; 811 BleVolumeInfo(int index, int maxIndex, int streamType)812 BleVolumeInfo(int index, int maxIndex, int streamType) { 813 mIndex = index; 814 mMaxIndex = maxIndex; 815 mStreamType = streamType; 816 } 817 }; 818 819 /*package*/ static final class BtDeviceChangedData { 820 final @Nullable BluetoothDevice mNewDevice; 821 final @Nullable BluetoothDevice mPreviousDevice; 822 final @NonNull BluetoothProfileConnectionInfo mInfo; 823 final @NonNull String mEventSource; 824 BtDeviceChangedData(@ullable BluetoothDevice newDevice, @Nullable BluetoothDevice previousDevice, @NonNull BluetoothProfileConnectionInfo info, @NonNull String eventSource)825 BtDeviceChangedData(@Nullable BluetoothDevice newDevice, 826 @Nullable BluetoothDevice previousDevice, 827 @NonNull BluetoothProfileConnectionInfo info, @NonNull String eventSource) { 828 mNewDevice = newDevice; 829 mPreviousDevice = previousDevice; 830 mInfo = info; 831 mEventSource = eventSource; 832 } 833 834 @Override toString()835 public String toString() { 836 return "BtDeviceChangedData profile=" + BluetoothProfile.getProfileName( 837 mInfo.getProfile()) 838 + ", switch device: [" + mPreviousDevice + "] -> [" + mNewDevice + "]"; 839 } 840 } 841 842 /*package*/ static final class BtDeviceInfo { 843 final @NonNull BluetoothDevice mDevice; 844 final @AudioService.BtProfileConnectionState int mState; 845 final @AudioService.BtProfile int mProfile; 846 final boolean mSupprNoisy; 847 final int mVolume; 848 final boolean mIsLeOutput; 849 final @NonNull String mEventSource; 850 final int mAudioSystemDevice; 851 final int mMusicDevice; 852 BtDeviceInfo(@onNull BtDeviceChangedData d, @NonNull BluetoothDevice device, int state, int audioDevice, @AudioSystem.AudioFormatNativeEnumForBtCodec int codec)853 BtDeviceInfo(@NonNull BtDeviceChangedData d, @NonNull BluetoothDevice device, int state, 854 int audioDevice, @AudioSystem.AudioFormatNativeEnumForBtCodec int codec) { 855 mDevice = device; 856 mState = state; 857 mProfile = d.mInfo.getProfile(); 858 mSupprNoisy = d.mInfo.isSuppressNoisyIntent(); 859 mVolume = d.mInfo.getVolume(); 860 mIsLeOutput = d.mInfo.isLeOutput(); 861 mEventSource = d.mEventSource; 862 mAudioSystemDevice = audioDevice; 863 mMusicDevice = AudioSystem.DEVICE_NONE; 864 } 865 866 // constructor used by AudioDeviceBroker to search similar message BtDeviceInfo(@onNull BluetoothDevice device, int profile)867 BtDeviceInfo(@NonNull BluetoothDevice device, int profile) { 868 mDevice = device; 869 mProfile = profile; 870 mEventSource = ""; 871 mMusicDevice = AudioSystem.DEVICE_NONE; 872 mAudioSystemDevice = 0; 873 mState = 0; 874 mSupprNoisy = false; 875 mVolume = -1; 876 mIsLeOutput = false; 877 } 878 879 // constructor used by AudioDeviceInventory when config change failed BtDeviceInfo(@onNull BluetoothDevice device, int profile, int state, int musicDevice, int audioSystemDevice)880 BtDeviceInfo(@NonNull BluetoothDevice device, int profile, int state, int musicDevice, 881 int audioSystemDevice) { 882 mDevice = device; 883 mProfile = profile; 884 mEventSource = ""; 885 mMusicDevice = musicDevice; 886 mAudioSystemDevice = audioSystemDevice; 887 mState = state; 888 mSupprNoisy = false; 889 mVolume = -1; 890 mIsLeOutput = false; 891 } 892 BtDeviceInfo(@onNull BtDeviceInfo src, int state)893 BtDeviceInfo(@NonNull BtDeviceInfo src, int state) { 894 mDevice = src.mDevice; 895 mState = state; 896 mProfile = src.mProfile; 897 mSupprNoisy = src.mSupprNoisy; 898 mVolume = src.mVolume; 899 mIsLeOutput = src.mIsLeOutput; 900 mEventSource = src.mEventSource; 901 mAudioSystemDevice = src.mAudioSystemDevice; 902 mMusicDevice = src.mMusicDevice; 903 } 904 905 // redefine equality op so we can match messages intended for this device 906 @Override equals(Object o)907 public boolean equals(Object o) { 908 if (o == null) { 909 return false; 910 } 911 if (this == o) { 912 return true; 913 } 914 if (o instanceof BtDeviceInfo) { 915 return mProfile == ((BtDeviceInfo) o).mProfile 916 && mDevice.equals(((BtDeviceInfo) o).mDevice); 917 } 918 return false; 919 } 920 921 @Override hashCode()922 public int hashCode() { 923 // only hashing on the fields used in equals() 924 return Objects.hash(mProfile, mDevice); 925 } 926 927 @Override toString()928 public String toString() { 929 return "BtDeviceInfo: device=" + mDevice.toString() 930 + " state=" + mState 931 + " prof=" + mProfile 932 + " supprNoisy=" + mSupprNoisy 933 + " volume=" + mVolume 934 + " isLeOutput=" + mIsLeOutput 935 + " eventSource=" + mEventSource 936 + " audioSystemDevice=" + mAudioSystemDevice 937 + " musicDevice=" + mMusicDevice; 938 } 939 } 940 createBtDeviceInfo(@onNull BtDeviceChangedData d, @NonNull BluetoothDevice device, int state)941 BtDeviceInfo createBtDeviceInfo(@NonNull BtDeviceChangedData d, @NonNull BluetoothDevice device, 942 int state) { 943 int audioDevice; 944 int codec = AudioSystem.AUDIO_FORMAT_DEFAULT; 945 switch (d.mInfo.getProfile()) { 946 case BluetoothProfile.A2DP_SINK: 947 audioDevice = AudioSystem.DEVICE_IN_BLUETOOTH_A2DP; 948 break; 949 case BluetoothProfile.A2DP: 950 audioDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP; 951 break; 952 case BluetoothProfile.HEARING_AID: 953 audioDevice = AudioSystem.DEVICE_OUT_HEARING_AID; 954 break; 955 case BluetoothProfile.LE_AUDIO: 956 if (d.mInfo.isLeOutput()) { 957 audioDevice = AudioSystem.DEVICE_OUT_BLE_HEADSET; 958 } else { 959 audioDevice = AudioSystem.DEVICE_IN_BLE_HEADSET; 960 } 961 break; 962 case BluetoothProfile.LE_AUDIO_BROADCAST: 963 audioDevice = AudioSystem.DEVICE_OUT_BLE_BROADCAST; 964 break; 965 case BluetoothProfile.HEADSET: 966 // the actual device type is not important at this point and 967 // will be set by BtHelper.handleBtScoActiveDeviceChange() 968 audioDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO; 969 break; 970 default: throw new IllegalArgumentException("Invalid profile " + d.mInfo.getProfile()); 971 } 972 return new BtDeviceInfo(d, device, state, audioDevice, codec); 973 } 974 btMediaMetricRecord(@onNull BluetoothDevice device, String state, @NonNull BtDeviceChangedData data)975 private void btMediaMetricRecord(@NonNull BluetoothDevice device, String state, 976 @NonNull BtDeviceChangedData data) { 977 final String name = TextUtils.emptyIfNull(device.getName()); 978 new MediaMetrics.Item(MediaMetrics.Name.AUDIO_DEVICE + MediaMetrics.SEPARATOR 979 + "queueOnBluetoothActiveDeviceChanged") 980 .set(MediaMetrics.Property.STATE, state) 981 .set(MediaMetrics.Property.STATUS, data.mInfo.getProfile()) 982 .set(MediaMetrics.Property.NAME, name) 983 .record(); 984 } 985 986 /** 987 * will block on mDeviceStateLock, which is held during an A2DP (dis) connection 988 * not just a simple message post 989 * @param data struct with the (dis)connection information 990 */ queueOnBluetoothActiveDeviceChanged(@onNull BtDeviceChangedData data)991 /*package*/ void queueOnBluetoothActiveDeviceChanged(@NonNull BtDeviceChangedData data) { 992 if (data.mPreviousDevice != null 993 && data.mPreviousDevice.equals(data.mNewDevice)) { 994 final String name = TextUtils.emptyIfNull(data.mNewDevice.getName()); 995 new MediaMetrics.Item(MediaMetrics.Name.AUDIO_DEVICE + MediaMetrics.SEPARATOR 996 + "queueOnBluetoothActiveDeviceChanged_update") 997 .set(MediaMetrics.Property.NAME, name) 998 .set(MediaMetrics.Property.STATUS, data.mInfo.getProfile()) 999 .record(); 1000 synchronized (mDeviceStateLock) { 1001 postBluetoothDeviceConfigChange(createBtDeviceInfo(data, data.mNewDevice, 1002 BluetoothProfile.STATE_CONNECTED)); 1003 } 1004 } else { 1005 synchronized (mDeviceStateLock) { 1006 if (data.mPreviousDevice != null) { 1007 btMediaMetricRecord(data.mPreviousDevice, MediaMetrics.Value.DISCONNECTED, 1008 data); 1009 sendLMsgNoDelay(MSG_L_BT_ACTIVE_DEVICE_CHANGE_EXT, SENDMSG_QUEUE, 1010 createBtDeviceInfo(data, data.mPreviousDevice, 1011 BluetoothProfile.STATE_DISCONNECTED)); 1012 } 1013 if (data.mNewDevice != null) { 1014 btMediaMetricRecord(data.mNewDevice, MediaMetrics.Value.CONNECTED, data); 1015 sendLMsgNoDelay(MSG_L_BT_ACTIVE_DEVICE_CHANGE_EXT, SENDMSG_QUEUE, 1016 createBtDeviceInfo(data, data.mNewDevice, 1017 BluetoothProfile.STATE_CONNECTED)); 1018 } 1019 } 1020 } 1021 } 1022 1023 // Lock protecting state variable related to Bluetooth audio state 1024 private final Object mBluetoothAudioStateLock = new Object(); 1025 1026 // Current Bluetooth SCO audio active state indicated by BtHelper via setBluetoothScoOn(). 1027 @GuardedBy("mBluetoothAudioStateLock") 1028 private boolean mBluetoothScoOn; 1029 // value of BT_SCO parameter currently applied to audio HAL. 1030 @GuardedBy("mBluetoothAudioStateLock") 1031 private boolean mBluetoothScoOnApplied; 1032 1033 // A2DP suspend state requested by AudioManager.setA2dpSuspended() API. 1034 @GuardedBy("mBluetoothAudioStateLock") 1035 private boolean mBluetoothA2dpSuspendedExt; 1036 // A2DP suspend state requested by AudioDeviceInventory. 1037 @GuardedBy("mBluetoothAudioStateLock") 1038 private boolean mBluetoothA2dpSuspendedInt; 1039 // value of BT_A2dpSuspendedSCO parameter currently applied to audio HAL. 1040 1041 @GuardedBy("mBluetoothAudioStateLock") 1042 private boolean mBluetoothA2dpSuspendedApplied; 1043 1044 // LE Audio suspend state requested by AudioManager.setLeAudioSuspended() API. 1045 @GuardedBy("mBluetoothAudioStateLock") 1046 private boolean mBluetoothLeSuspendedExt; 1047 // LE Audio suspend state requested by AudioDeviceInventory. 1048 @GuardedBy("mBluetoothAudioStateLock") 1049 private boolean mBluetoothLeSuspendedInt; 1050 // value of LeAudioSuspended parameter currently applied to audio HAL. 1051 @GuardedBy("mBluetoothAudioStateLock") 1052 private boolean mBluetoothLeSuspendedApplied; 1053 initAudioHalBluetoothState()1054 private void initAudioHalBluetoothState() { 1055 synchronized (mBluetoothAudioStateLock) { 1056 mBluetoothScoOnApplied = false; 1057 mBluetoothA2dpSuspendedApplied = false; 1058 mBluetoothLeSuspendedApplied = false; 1059 reapplyAudioHalBluetoothState(); 1060 } 1061 } 1062 1063 @GuardedBy("mBluetoothAudioStateLock") updateAudioHalBluetoothState()1064 private void updateAudioHalBluetoothState() { 1065 if (mBluetoothScoOn != mBluetoothScoOnApplied) { 1066 if (AudioService.DEBUG_COMM_RTE) { 1067 Log.v(TAG, "updateAudioHalBluetoothState() mBluetoothScoOn: " 1068 + mBluetoothScoOn + ", mBluetoothScoOnApplied: " + mBluetoothScoOnApplied); 1069 } 1070 if (mBluetoothScoOn) { 1071 if (!mBluetoothA2dpSuspendedApplied) { 1072 AudioSystem.setParameters("A2dpSuspended=true"); 1073 mBluetoothA2dpSuspendedApplied = true; 1074 } 1075 if (!mBluetoothLeSuspendedApplied) { 1076 AudioSystem.setParameters("LeAudioSuspended=true"); 1077 mBluetoothLeSuspendedApplied = true; 1078 } 1079 AudioSystem.setParameters("BT_SCO=on"); 1080 } else { 1081 AudioSystem.setParameters("BT_SCO=off"); 1082 } 1083 mBluetoothScoOnApplied = mBluetoothScoOn; 1084 } 1085 if (!mBluetoothScoOnApplied) { 1086 if ((mBluetoothA2dpSuspendedExt || mBluetoothA2dpSuspendedInt) 1087 != mBluetoothA2dpSuspendedApplied) { 1088 if (AudioService.DEBUG_COMM_RTE) { 1089 Log.v(TAG, "updateAudioHalBluetoothState() mBluetoothA2dpSuspendedExt: " 1090 + mBluetoothA2dpSuspendedExt 1091 + ", mBluetoothA2dpSuspendedInt: " + mBluetoothA2dpSuspendedInt 1092 + ", mBluetoothA2dpSuspendedApplied: " 1093 + mBluetoothA2dpSuspendedApplied); 1094 } 1095 mBluetoothA2dpSuspendedApplied = 1096 mBluetoothA2dpSuspendedExt || mBluetoothA2dpSuspendedInt; 1097 if (mBluetoothA2dpSuspendedApplied) { 1098 AudioSystem.setParameters("A2dpSuspended=true"); 1099 } else { 1100 AudioSystem.setParameters("A2dpSuspended=false"); 1101 } 1102 } 1103 if ((mBluetoothLeSuspendedExt || mBluetoothLeSuspendedInt) 1104 != mBluetoothLeSuspendedApplied) { 1105 if (AudioService.DEBUG_COMM_RTE) { 1106 Log.v(TAG, "updateAudioHalBluetoothState() mBluetoothLeSuspendedExt: " 1107 + mBluetoothLeSuspendedExt 1108 + ", mBluetoothLeSuspendedInt: " + mBluetoothLeSuspendedInt 1109 + ", mBluetoothLeSuspendedApplied: " + mBluetoothLeSuspendedApplied); 1110 } 1111 mBluetoothLeSuspendedApplied = 1112 mBluetoothLeSuspendedExt || mBluetoothLeSuspendedInt; 1113 if (mBluetoothLeSuspendedApplied) { 1114 AudioSystem.setParameters("LeAudioSuspended=true"); 1115 } else { 1116 AudioSystem.setParameters("LeAudioSuspended=false"); 1117 } 1118 } 1119 } 1120 } 1121 1122 @GuardedBy("mBluetoothAudioStateLock") reapplyAudioHalBluetoothState()1123 private void reapplyAudioHalBluetoothState() { 1124 if (AudioService.DEBUG_COMM_RTE) { 1125 Log.v(TAG, "reapplyAudioHalBluetoothState() mBluetoothScoOnApplied: " 1126 + mBluetoothScoOnApplied + ", mBluetoothA2dpSuspendedApplied: " 1127 + mBluetoothA2dpSuspendedApplied + ", mBluetoothLeSuspendedApplied: " 1128 + mBluetoothLeSuspendedApplied); 1129 } 1130 // Note: the order of parameters is important. 1131 if (mBluetoothScoOnApplied) { 1132 AudioSystem.setParameters("A2dpSuspended=true"); 1133 AudioSystem.setParameters("LeAudioSuspended=true"); 1134 AudioSystem.setParameters("BT_SCO=on"); 1135 } else { 1136 AudioSystem.setParameters("BT_SCO=off"); 1137 if (mBluetoothA2dpSuspendedApplied) { 1138 AudioSystem.setParameters("A2dpSuspended=true"); 1139 } else { 1140 AudioSystem.setParameters("A2dpSuspended=false"); 1141 } 1142 if (mBluetoothLeSuspendedApplied) { 1143 AudioSystem.setParameters("LeAudioSuspended=true"); 1144 } else { 1145 AudioSystem.setParameters("LeAudioSuspended=false"); 1146 } 1147 } 1148 } 1149 setBluetoothScoOn(boolean on, String eventSource)1150 /*package*/ void setBluetoothScoOn(boolean on, String eventSource) { 1151 if (AudioService.DEBUG_COMM_RTE) { 1152 Log.v(TAG, "setBluetoothScoOn: " + on + " " + eventSource); 1153 } 1154 synchronized (mBluetoothAudioStateLock) { 1155 mBluetoothScoOn = on; 1156 updateAudioHalBluetoothState(); 1157 postUpdateCommunicationRouteClient(isBluetoothScoRequested(), eventSource); 1158 } 1159 } 1160 setA2dpSuspended(boolean enable, boolean internal, String eventSource)1161 /*package*/ void setA2dpSuspended(boolean enable, boolean internal, String eventSource) { 1162 synchronized (mBluetoothAudioStateLock) { 1163 if (AudioService.DEBUG_COMM_RTE) { 1164 Log.v(TAG, "setA2dpSuspended source: " + eventSource + ", enable: " 1165 + enable + ", internal: " + internal 1166 + ", mBluetoothA2dpSuspendedInt: " + mBluetoothA2dpSuspendedInt 1167 + ", mBluetoothA2dpSuspendedExt: " + mBluetoothA2dpSuspendedExt); 1168 } 1169 if (internal) { 1170 mBluetoothA2dpSuspendedInt = enable; 1171 } else { 1172 mBluetoothA2dpSuspendedExt = enable; 1173 } 1174 updateAudioHalBluetoothState(); 1175 } 1176 } 1177 clearA2dpSuspended(boolean internalOnly)1178 /*package*/ void clearA2dpSuspended(boolean internalOnly) { 1179 if (AudioService.DEBUG_COMM_RTE) { 1180 Log.v(TAG, "clearA2dpSuspended, internalOnly: " + internalOnly); 1181 } 1182 synchronized (mBluetoothAudioStateLock) { 1183 mBluetoothA2dpSuspendedInt = false; 1184 if (!internalOnly) { 1185 mBluetoothA2dpSuspendedExt = false; 1186 } 1187 updateAudioHalBluetoothState(); 1188 } 1189 } 1190 setLeAudioSuspended(boolean enable, boolean internal, String eventSource)1191 /*package*/ void setLeAudioSuspended(boolean enable, boolean internal, String eventSource) { 1192 synchronized (mBluetoothAudioStateLock) { 1193 if (AudioService.DEBUG_COMM_RTE) { 1194 Log.v(TAG, "setLeAudioSuspended source: " + eventSource + ", enable: " 1195 + enable + ", internal: " + internal 1196 + ", mBluetoothLeSuspendedInt: " + mBluetoothA2dpSuspendedInt 1197 + ", mBluetoothLeSuspendedExt: " + mBluetoothA2dpSuspendedExt); 1198 } 1199 if (internal) { 1200 mBluetoothLeSuspendedInt = enable; 1201 } else { 1202 mBluetoothLeSuspendedExt = enable; 1203 } 1204 updateAudioHalBluetoothState(); 1205 } 1206 } 1207 clearLeAudioSuspended(boolean internalOnly)1208 /*package*/ void clearLeAudioSuspended(boolean internalOnly) { 1209 if (AudioService.DEBUG_COMM_RTE) { 1210 Log.v(TAG, "clearLeAudioSuspended, internalOnly: " + internalOnly); 1211 } 1212 synchronized (mBluetoothAudioStateLock) { 1213 mBluetoothLeSuspendedInt = false; 1214 if (!internalOnly) { 1215 mBluetoothLeSuspendedExt = false; 1216 } 1217 updateAudioHalBluetoothState(); 1218 } 1219 } 1220 startWatchingRoutes(IAudioRoutesObserver observer)1221 /*package*/ AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) { 1222 synchronized (mDeviceStateLock) { 1223 return mDeviceInventory.startWatchingRoutes(observer); 1224 } 1225 } 1226 getCurAudioRoutes()1227 /*package*/ AudioRoutesInfo getCurAudioRoutes() { 1228 synchronized (mDeviceStateLock) { 1229 return mDeviceInventory.getCurAudioRoutes(); 1230 } 1231 } 1232 isBluetoothA2dpOn()1233 /*package*/ boolean isBluetoothA2dpOn() { 1234 return mBluetoothA2dpEnabled.get(); 1235 } 1236 postSetAvrcpAbsoluteVolumeIndex(int index)1237 /*package*/ void postSetAvrcpAbsoluteVolumeIndex(int index) { 1238 sendIMsgNoDelay(MSG_I_SET_AVRCP_ABSOLUTE_VOLUME, SENDMSG_REPLACE, index); 1239 } 1240 postSetHearingAidVolumeIndex(int index, int streamType)1241 /*package*/ void postSetHearingAidVolumeIndex(int index, int streamType) { 1242 sendIIMsgNoDelay(MSG_II_SET_HEARING_AID_VOLUME, SENDMSG_REPLACE, index, streamType); 1243 } 1244 postSetLeAudioVolumeIndex(int index, int maxIndex, int streamType)1245 /*package*/ void postSetLeAudioVolumeIndex(int index, int maxIndex, int streamType) { 1246 BleVolumeInfo info = new BleVolumeInfo(index, maxIndex, streamType); 1247 sendLMsgNoDelay(MSG_II_SET_LE_AUDIO_OUT_VOLUME, SENDMSG_REPLACE, info); 1248 } 1249 postSetModeOwner(int mode, int pid, int uid)1250 /*package*/ void postSetModeOwner(int mode, int pid, int uid) { 1251 sendLMsgNoDelay(MSG_I_SET_MODE_OWNER, SENDMSG_REPLACE, 1252 new AudioModeInfo(mode, pid, uid)); 1253 } 1254 postBluetoothDeviceConfigChange(@onNull BtDeviceInfo info)1255 /*package*/ void postBluetoothDeviceConfigChange(@NonNull BtDeviceInfo info) { 1256 sendLMsgNoDelay(MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE, SENDMSG_QUEUE, info); 1257 } 1258 startBluetoothScoForClient(IBinder cb, int uid, int scoAudioMode, boolean isPrivileged, @NonNull String eventSource)1259 /*package*/ void startBluetoothScoForClient(IBinder cb, int uid, int scoAudioMode, 1260 boolean isPrivileged, @NonNull String eventSource) { 1261 1262 if (AudioService.DEBUG_COMM_RTE) { 1263 Log.v(TAG, "startBluetoothScoForClient, uid: " + uid); 1264 } 1265 postSetCommunicationDeviceForClient(new CommunicationDeviceInfo( 1266 cb, uid, new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO, ""), 1267 true, scoAudioMode, eventSource, isPrivileged)); 1268 } 1269 stopBluetoothScoForClient( IBinder cb, int uid, boolean isPrivileged, @NonNull String eventSource)1270 /*package*/ void stopBluetoothScoForClient( 1271 IBinder cb, int uid, boolean isPrivileged, @NonNull String eventSource) { 1272 1273 if (AudioService.DEBUG_COMM_RTE) { 1274 Log.v(TAG, "stopBluetoothScoForClient, uid: " + uid); 1275 } 1276 postSetCommunicationDeviceForClient(new CommunicationDeviceInfo( 1277 cb, uid, new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO, ""), 1278 false, BtHelper.SCO_MODE_UNDEFINED, eventSource, isPrivileged)); 1279 } 1280 setPreferredDevicesForStrategySync(int strategy, @NonNull List<AudioDeviceAttributes> devices)1281 /*package*/ int setPreferredDevicesForStrategySync(int strategy, 1282 @NonNull List<AudioDeviceAttributes> devices) { 1283 return mDeviceInventory.setPreferredDevicesForStrategyAndSave(strategy, devices); 1284 } 1285 removePreferredDevicesForStrategySync(int strategy)1286 /*package*/ int removePreferredDevicesForStrategySync(int strategy) { 1287 return mDeviceInventory.removePreferredDevicesForStrategyAndSave(strategy); 1288 } 1289 setDeviceAsNonDefaultForStrategySync(int strategy, @NonNull AudioDeviceAttributes device)1290 /*package*/ int setDeviceAsNonDefaultForStrategySync(int strategy, 1291 @NonNull AudioDeviceAttributes device) { 1292 return mDeviceInventory.setDeviceAsNonDefaultForStrategyAndSave(strategy, device); 1293 } 1294 removeDeviceAsNonDefaultForStrategySync(int strategy, @NonNull AudioDeviceAttributes device)1295 /*package*/ int removeDeviceAsNonDefaultForStrategySync(int strategy, 1296 @NonNull AudioDeviceAttributes device) { 1297 return mDeviceInventory.removeDeviceAsNonDefaultForStrategyAndSave(strategy, device); 1298 } 1299 registerStrategyPreferredDevicesDispatcher( @onNull IStrategyPreferredDevicesDispatcher dispatcher, boolean isPrivileged)1300 /*package*/ void registerStrategyPreferredDevicesDispatcher( 1301 @NonNull IStrategyPreferredDevicesDispatcher dispatcher, boolean isPrivileged) { 1302 mDeviceInventory.registerStrategyPreferredDevicesDispatcher(dispatcher, isPrivileged); 1303 } 1304 unregisterStrategyPreferredDevicesDispatcher( @onNull IStrategyPreferredDevicesDispatcher dispatcher)1305 /*package*/ void unregisterStrategyPreferredDevicesDispatcher( 1306 @NonNull IStrategyPreferredDevicesDispatcher dispatcher) { 1307 mDeviceInventory.unregisterStrategyPreferredDevicesDispatcher(dispatcher); 1308 } 1309 registerStrategyNonDefaultDevicesDispatcher( @onNull IStrategyNonDefaultDevicesDispatcher dispatcher, boolean isPrivileged)1310 /*package*/ void registerStrategyNonDefaultDevicesDispatcher( 1311 @NonNull IStrategyNonDefaultDevicesDispatcher dispatcher, boolean isPrivileged) { 1312 mDeviceInventory.registerStrategyNonDefaultDevicesDispatcher(dispatcher, isPrivileged); 1313 } 1314 unregisterStrategyNonDefaultDevicesDispatcher( @onNull IStrategyNonDefaultDevicesDispatcher dispatcher)1315 /*package*/ void unregisterStrategyNonDefaultDevicesDispatcher( 1316 @NonNull IStrategyNonDefaultDevicesDispatcher dispatcher) { 1317 mDeviceInventory.unregisterStrategyNonDefaultDevicesDispatcher(dispatcher); 1318 } 1319 setPreferredDevicesForCapturePresetSync(int capturePreset, @NonNull List<AudioDeviceAttributes> devices)1320 /*package*/ int setPreferredDevicesForCapturePresetSync(int capturePreset, 1321 @NonNull List<AudioDeviceAttributes> devices) { 1322 return mDeviceInventory.setPreferredDevicesForCapturePresetAndSave(capturePreset, devices); 1323 } 1324 clearPreferredDevicesForCapturePresetSync(int capturePreset)1325 /*package*/ int clearPreferredDevicesForCapturePresetSync(int capturePreset) { 1326 return mDeviceInventory.clearPreferredDevicesForCapturePresetAndSave(capturePreset); 1327 } 1328 registerCapturePresetDevicesRoleDispatcher( @onNull ICapturePresetDevicesRoleDispatcher dispatcher, boolean isPrivileged)1329 /*package*/ void registerCapturePresetDevicesRoleDispatcher( 1330 @NonNull ICapturePresetDevicesRoleDispatcher dispatcher, boolean isPrivileged) { 1331 mDeviceInventory.registerCapturePresetDevicesRoleDispatcher(dispatcher, isPrivileged); 1332 } 1333 unregisterCapturePresetDevicesRoleDispatcher( @onNull ICapturePresetDevicesRoleDispatcher dispatcher)1334 /*package*/ void unregisterCapturePresetDevicesRoleDispatcher( 1335 @NonNull ICapturePresetDevicesRoleDispatcher dispatcher) { 1336 mDeviceInventory.unregisterCapturePresetDevicesRoleDispatcher(dispatcher); 1337 } 1338 anonymizeAudioDeviceAttributesListUnchecked( List<AudioDeviceAttributes> devices)1339 /* package */ List<AudioDeviceAttributes> anonymizeAudioDeviceAttributesListUnchecked( 1340 List<AudioDeviceAttributes> devices) { 1341 return mAudioService.anonymizeAudioDeviceAttributesListUnchecked(devices); 1342 } 1343 registerCommunicationDeviceDispatcher( @onNull ICommunicationDeviceDispatcher dispatcher)1344 /*package*/ void registerCommunicationDeviceDispatcher( 1345 @NonNull ICommunicationDeviceDispatcher dispatcher) { 1346 mCommDevDispatchers.register(dispatcher); 1347 } 1348 unregisterCommunicationDeviceDispatcher( @onNull ICommunicationDeviceDispatcher dispatcher)1349 /*package*/ void unregisterCommunicationDeviceDispatcher( 1350 @NonNull ICommunicationDeviceDispatcher dispatcher) { 1351 mCommDevDispatchers.unregister(dispatcher); 1352 } 1353 1354 // Monitoring of communication device 1355 final RemoteCallbackList<ICommunicationDeviceDispatcher> mCommDevDispatchers = 1356 new RemoteCallbackList<ICommunicationDeviceDispatcher>(); 1357 1358 // portId of the device currently selected for communication: avoids broadcasting changes 1359 // when same communication route is applied 1360 @GuardedBy("mDeviceStateLock") 1361 int mCurCommunicationPortId = -1; 1362 1363 @GuardedBy("mDeviceStateLock") dispatchCommunicationDevice()1364 private void dispatchCommunicationDevice() { 1365 AudioDeviceInfo device = getCommunicationDeviceInt(); 1366 int portId = device != null ? device.getId() : 0; 1367 if (portId == mCurCommunicationPortId) { 1368 return; 1369 } 1370 mCurCommunicationPortId = portId; 1371 1372 final int nbDispatchers = mCommDevDispatchers.beginBroadcast(); 1373 for (int i = 0; i < nbDispatchers; i++) { 1374 try { 1375 mCommDevDispatchers.getBroadcastItem(i) 1376 .dispatchCommunicationDeviceChanged(portId); 1377 } catch (RemoteException e) { 1378 Log.e(TAG, "dispatchCommunicationDevice error", e); 1379 } 1380 } 1381 mCommDevDispatchers.finishBroadcast(); 1382 } 1383 1384 1385 //--------------------------------------------------------------------- 1386 // Communication with (to) AudioService 1387 //TODO check whether the AudioService methods are candidates to move here postAccessoryPlugMediaUnmute(int device)1388 /*package*/ void postAccessoryPlugMediaUnmute(int device) { 1389 mAudioService.postAccessoryPlugMediaUnmute(device); 1390 } 1391 getVssVolumeForDevice(int streamType, int device)1392 /*package*/ int getVssVolumeForDevice(int streamType, int device) { 1393 return mAudioService.getVssVolumeForDevice(streamType, device); 1394 } 1395 getMaxVssVolumeForStream(int streamType)1396 /*package*/ int getMaxVssVolumeForStream(int streamType) { 1397 return mAudioService.getMaxVssVolumeForStream(streamType); 1398 } 1399 getDeviceForStream(int streamType)1400 /*package*/ int getDeviceForStream(int streamType) { 1401 return mAudioService.getDeviceForStream(streamType); 1402 } 1403 postApplyVolumeOnDevice(int streamType, int device, String caller)1404 /*package*/ void postApplyVolumeOnDevice(int streamType, int device, String caller) { 1405 mAudioService.postApplyVolumeOnDevice(streamType, device, caller); 1406 } 1407 postSetVolumeIndexOnDevice(int streamType, int vssVolIndex, int device, String caller)1408 /*package*/ void postSetVolumeIndexOnDevice(int streamType, int vssVolIndex, int device, 1409 String caller) { 1410 mAudioService.postSetVolumeIndexOnDevice(streamType, vssVolIndex, device, caller); 1411 } 1412 postObserveDevicesForAllStreams()1413 /*packages*/ void postObserveDevicesForAllStreams() { 1414 mAudioService.postObserveDevicesForAllStreams(); 1415 } 1416 isInCommunication()1417 /*package*/ boolean isInCommunication() { 1418 return mAudioService.isInCommunication(); 1419 } 1420 hasMediaDynamicPolicy()1421 /*package*/ boolean hasMediaDynamicPolicy() { 1422 return mAudioService.hasMediaDynamicPolicy(); 1423 } 1424 getContentResolver()1425 /*package*/ ContentResolver getContentResolver() { 1426 return mAudioService.getContentResolver(); 1427 } 1428 checkMusicActive(int deviceType, String caller)1429 /*package*/ void checkMusicActive(int deviceType, String caller) { 1430 mAudioService.checkMusicActive(deviceType, caller); 1431 } 1432 checkVolumeCecOnHdmiConnection( @udioService.ConnectionState int state, String caller)1433 /*package*/ void checkVolumeCecOnHdmiConnection( 1434 @AudioService.ConnectionState int state, String caller) { 1435 mAudioService.postCheckVolumeCecOnHdmiConnection(state, caller); 1436 } 1437 hasAudioFocusUsers()1438 /*package*/ boolean hasAudioFocusUsers() { 1439 return mAudioService.hasAudioFocusUsers(); 1440 } 1441 postInitSpatializerHeadTrackingSensors()1442 /*package*/ void postInitSpatializerHeadTrackingSensors() { 1443 mAudioService.postInitSpatializerHeadTrackingSensors(); 1444 } 1445 1446 //--------------------------------------------------------------------- 1447 // Message handling on behalf of helper classes. 1448 // Each of these methods posts a message to mBrokerHandler message queue. postBroadcastScoConnectionState(int state)1449 /*package*/ void postBroadcastScoConnectionState(int state) { 1450 sendIMsgNoDelay(MSG_I_BROADCAST_BT_CONNECTION_STATE, SENDMSG_QUEUE, state); 1451 } 1452 postBroadcastBecomingNoisy()1453 /*package*/ void postBroadcastBecomingNoisy() { 1454 sendMsgNoDelay(MSG_BROADCAST_AUDIO_BECOMING_NOISY, SENDMSG_REPLACE); 1455 } 1456 postBluetoothActiveDevice(BtDeviceInfo info, int delay)1457 /*package*/ void postBluetoothActiveDevice(BtDeviceInfo info, int delay) { 1458 sendLMsg(MSG_L_SET_BT_ACTIVE_DEVICE, SENDMSG_QUEUE, info, delay); 1459 } 1460 postSetWiredDeviceConnectionState( AudioDeviceInventory.WiredDeviceConnectionState connectionState, int delay)1461 /*package*/ void postSetWiredDeviceConnectionState( 1462 AudioDeviceInventory.WiredDeviceConnectionState connectionState, int delay) { 1463 sendLMsg(MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE, SENDMSG_QUEUE, connectionState, delay); 1464 } 1465 postBtProfileDisconnected(int profile)1466 /*package*/ void postBtProfileDisconnected(int profile) { 1467 sendIMsgNoDelay(MSG_I_BT_SERVICE_DISCONNECTED_PROFILE, SENDMSG_QUEUE, profile); 1468 } 1469 postBtProfileConnected(int profile, BluetoothProfile proxy)1470 /*package*/ void postBtProfileConnected(int profile, BluetoothProfile proxy) { 1471 sendILMsgNoDelay(MSG_IL_BT_SERVICE_CONNECTED_PROFILE, SENDMSG_QUEUE, profile, proxy); 1472 } 1473 postCommunicationRouteClientDied(CommunicationRouteClient client)1474 /*package*/ void postCommunicationRouteClientDied(CommunicationRouteClient client) { 1475 sendLMsgNoDelay(MSG_L_COMMUNICATION_ROUTE_CLIENT_DIED, SENDMSG_QUEUE, client); 1476 } 1477 postSaveSetPreferredDevicesForStrategy(int strategy, List<AudioDeviceAttributes> devices)1478 /*package*/ void postSaveSetPreferredDevicesForStrategy(int strategy, 1479 List<AudioDeviceAttributes> devices) 1480 { 1481 sendILMsgNoDelay(MSG_IL_SAVE_PREF_DEVICES_FOR_STRATEGY, SENDMSG_QUEUE, strategy, devices); 1482 } 1483 postSaveRemovePreferredDevicesForStrategy(int strategy)1484 /*package*/ void postSaveRemovePreferredDevicesForStrategy(int strategy) { 1485 sendIMsgNoDelay(MSG_I_SAVE_REMOVE_PREF_DEVICES_FOR_STRATEGY, SENDMSG_QUEUE, strategy); 1486 } 1487 postSaveSetDeviceAsNonDefaultForStrategy( int strategy, AudioDeviceAttributes device)1488 /*package*/ void postSaveSetDeviceAsNonDefaultForStrategy( 1489 int strategy, AudioDeviceAttributes device) { 1490 sendILMsgNoDelay(MSG_IL_SAVE_NDEF_DEVICE_FOR_STRATEGY, SENDMSG_QUEUE, strategy, device); 1491 } 1492 postSaveRemoveDeviceAsNonDefaultForStrategy( int strategy, AudioDeviceAttributes device)1493 /*package*/ void postSaveRemoveDeviceAsNonDefaultForStrategy( 1494 int strategy, AudioDeviceAttributes device) { 1495 sendILMsgNoDelay( 1496 MSG_IL_SAVE_REMOVE_NDEF_DEVICE_FOR_STRATEGY, SENDMSG_QUEUE, strategy, device); 1497 } 1498 postSaveSetPreferredDevicesForCapturePreset( int capturePreset, List<AudioDeviceAttributes> devices)1499 /*package*/ void postSaveSetPreferredDevicesForCapturePreset( 1500 int capturePreset, List<AudioDeviceAttributes> devices) { 1501 sendILMsgNoDelay( 1502 MSG_IL_SAVE_PREF_DEVICES_FOR_CAPTURE_PRESET, SENDMSG_QUEUE, capturePreset, devices); 1503 } 1504 postSaveClearPreferredDevicesForCapturePreset(int capturePreset)1505 /*package*/ void postSaveClearPreferredDevicesForCapturePreset(int capturePreset) { 1506 sendIMsgNoDelay( 1507 MSG_I_SAVE_CLEAR_PREF_DEVICES_FOR_CAPTURE_PRESET, SENDMSG_QUEUE, capturePreset); 1508 } 1509 postUpdateCommunicationRouteClient( boolean wasBtScoRequested, String eventSource)1510 /*package*/ void postUpdateCommunicationRouteClient( 1511 boolean wasBtScoRequested, String eventSource) { 1512 sendILMsgNoDelay(MSG_IL_UPDATE_COMMUNICATION_ROUTE_CLIENT, SENDMSG_QUEUE, 1513 wasBtScoRequested ? 1 : 0, eventSource); 1514 } 1515 postSetCommunicationDeviceForClient(CommunicationDeviceInfo info)1516 /*package*/ void postSetCommunicationDeviceForClient(CommunicationDeviceInfo info) { 1517 sendLMsgNoDelay(MSG_L_SET_COMMUNICATION_DEVICE_FOR_CLIENT, SENDMSG_QUEUE, info); 1518 } 1519 postNotifyPreferredAudioProfileApplied(BluetoothDevice btDevice)1520 /*package*/ void postNotifyPreferredAudioProfileApplied(BluetoothDevice btDevice) { 1521 sendLMsgNoDelay(MSG_L_NOTIFY_PREFERRED_AUDIOPROFILE_APPLIED, SENDMSG_QUEUE, btDevice); 1522 } 1523 postReceiveBtEvent(Intent intent)1524 /*package*/ void postReceiveBtEvent(Intent intent) { 1525 sendLMsgNoDelay(MSG_L_RECEIVED_BT_EVENT, SENDMSG_QUEUE, intent); 1526 } 1527 postUpdateLeAudioGroupAddresses(int groupId)1528 /*package*/ void postUpdateLeAudioGroupAddresses(int groupId) { 1529 sendIMsgNoDelay( 1530 MSG_I_UPDATE_LE_AUDIO_GROUP_ADDRESSES, SENDMSG_QUEUE, groupId); 1531 } 1532 postSynchronizeAdiDevicesInInventory(AdiDeviceState deviceState)1533 /*package*/ void postSynchronizeAdiDevicesInInventory(AdiDeviceState deviceState) { 1534 sendLMsgNoDelay(MSG_L_SYNCHRONIZE_ADI_DEVICES_IN_INVENTORY, SENDMSG_QUEUE, deviceState); 1535 } 1536 postUpdatedAdiDeviceState(AdiDeviceState deviceState, boolean initSA)1537 /*package*/ void postUpdatedAdiDeviceState(AdiDeviceState deviceState, boolean initSA) { 1538 sendILMsgNoDelay( 1539 MSG_IL_UPDATED_ADI_DEVICE_STATE, SENDMSG_QUEUE, initSA ? 1 : 0, deviceState); 1540 } 1541 1542 /*package*/ static final class CommunicationDeviceInfo { 1543 final @NonNull IBinder mCb; // Identifies the requesting client for death handler 1544 final int mUid; // Requester UID 1545 final @Nullable AudioDeviceAttributes mDevice; // Device being set or reset. 1546 final boolean mOn; // true if setting, false if resetting 1547 final int mScoAudioMode; // only used for SCO: requested audio mode 1548 final boolean mIsPrivileged; // true if the client app has MODIFY_PHONE_STATE permission 1549 final @NonNull String mEventSource; // caller identifier for logging 1550 CommunicationDeviceInfo(@onNull IBinder cb, int uid, @Nullable AudioDeviceAttributes device, boolean on, int scoAudioMode, @NonNull String eventSource, boolean isPrivileged)1551 CommunicationDeviceInfo(@NonNull IBinder cb, int uid, 1552 @Nullable AudioDeviceAttributes device, boolean on, int scoAudioMode, 1553 @NonNull String eventSource, boolean isPrivileged) { 1554 mCb = cb; 1555 mUid = uid; 1556 mDevice = device; 1557 mOn = on; 1558 mScoAudioMode = scoAudioMode; 1559 mIsPrivileged = isPrivileged; 1560 mEventSource = eventSource; 1561 } 1562 1563 // redefine equality op so we can match messages intended for this client 1564 @Override equals(Object o)1565 public boolean equals(Object o) { 1566 if (o == null) { 1567 return false; 1568 } 1569 if (this == o) { 1570 return true; 1571 } 1572 if (!(o instanceof CommunicationDeviceInfo)) { 1573 return false; 1574 } 1575 1576 return mCb.equals(((CommunicationDeviceInfo) o).mCb) 1577 && mUid == ((CommunicationDeviceInfo) o).mUid; 1578 } 1579 1580 @Override hashCode()1581 public int hashCode() { 1582 // only hashing on the fields used in equals() 1583 return Objects.hash(mCb.hashCode(), mUid); 1584 } 1585 1586 @Override toString()1587 public String toString() { 1588 return "CommunicationDeviceInfo mCb=" + mCb.toString() 1589 + " mUid=" + mUid 1590 + " mDevice=[" + (mDevice != null ? mDevice.toString() : "null") + "]" 1591 + " mOn=" + mOn 1592 + " mScoAudioMode=" + mScoAudioMode 1593 + " mIsPrivileged=" + mIsPrivileged 1594 + " mEventSource=" + mEventSource; 1595 } 1596 } 1597 1598 //--------------------------------------------------------------------- 1599 // Method forwarding between the helper classes (BtHelper, AudioDeviceInventory) 1600 // only call from a "handle"* method or "on"* method 1601 1602 // Handles request to override default use of A2DP for media. 1603 //@GuardedBy("mConnectedDevices") setBluetoothA2dpOnInt(boolean on, boolean fromA2dp, String source)1604 /*package*/ void setBluetoothA2dpOnInt(boolean on, boolean fromA2dp, String source) { 1605 // for logging only 1606 final String eventSource = "setBluetoothA2dpOn(" + on 1607 + ") from u/pid:" + Binder.getCallingUid() + "/" 1608 + Binder.getCallingPid() + " src:" + source; 1609 1610 mBluetoothA2dpEnabled.set(on); 1611 onSetForceUse( 1612 AudioSystem.FOR_MEDIA, 1613 on ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP, 1614 fromA2dp, 1615 eventSource); 1616 } 1617 handleDeviceConnection(@onNull AudioDeviceAttributes attributes, boolean connect, @Nullable BluetoothDevice btDevice)1618 /*package*/ boolean handleDeviceConnection(@NonNull AudioDeviceAttributes attributes, 1619 boolean connect, @Nullable BluetoothDevice btDevice) { 1620 synchronized (mDeviceStateLock) { 1621 return mDeviceInventory.handleDeviceConnection( 1622 attributes, connect, false /*for test*/, btDevice); 1623 } 1624 } 1625 handleFailureToConnectToBtHeadsetService(int delay)1626 /*package*/ void handleFailureToConnectToBtHeadsetService(int delay) { 1627 sendMsg(MSG_BT_HEADSET_CNCT_FAILED, SENDMSG_REPLACE, delay); 1628 } 1629 handleCancelFailureToConnectToBtHeadsetService()1630 /*package*/ void handleCancelFailureToConnectToBtHeadsetService() { 1631 mBrokerHandler.removeMessages(MSG_BT_HEADSET_CNCT_FAILED); 1632 } 1633 postReportNewRoutes(boolean fromA2dp)1634 /*package*/ void postReportNewRoutes(boolean fromA2dp) { 1635 sendMsgNoDelay(fromA2dp ? MSG_REPORT_NEW_ROUTES_A2DP : MSG_REPORT_NEW_ROUTES, SENDMSG_NOOP); 1636 } 1637 1638 // must be called synchronized on mConnectedDevices hasScheduledA2dpConnection(BluetoothDevice btDevice)1639 /*package*/ boolean hasScheduledA2dpConnection(BluetoothDevice btDevice) { 1640 final BtDeviceInfo devInfoToCheck = new BtDeviceInfo(btDevice, BluetoothProfile.A2DP); 1641 return mBrokerHandler.hasEqualMessages(MSG_L_SET_BT_ACTIVE_DEVICE, devInfoToCheck); 1642 } 1643 setA2dpTimeout(String address, int a2dpCodec, int delayMs)1644 /*package*/ void setA2dpTimeout(String address, int a2dpCodec, int delayMs) { 1645 sendILMsg(MSG_IL_BTA2DP_TIMEOUT, SENDMSG_QUEUE, a2dpCodec, address, delayMs); 1646 } 1647 setLeAudioTimeout(String address, int device, int codec, int delayMs)1648 /*package*/ void setLeAudioTimeout(String address, int device, int codec, int delayMs) { 1649 sendIILMsg(MSG_IIL_BTLEAUDIO_TIMEOUT, SENDMSG_QUEUE, device, codec, address, delayMs); 1650 } 1651 setAvrcpAbsoluteVolumeSupported(boolean supported)1652 /*package*/ void setAvrcpAbsoluteVolumeSupported(boolean supported) { 1653 synchronized (mDeviceStateLock) { 1654 mBtHelper.setAvrcpAbsoluteVolumeSupported(supported); 1655 } 1656 } 1657 clearAvrcpAbsoluteVolumeSupported()1658 /*package*/ void clearAvrcpAbsoluteVolumeSupported() { 1659 setAvrcpAbsoluteVolumeSupported(false); 1660 mAudioService.setAvrcpAbsoluteVolumeSupported(false); 1661 } 1662 getBluetoothA2dpEnabled()1663 /*package*/ boolean getBluetoothA2dpEnabled() { 1664 return mBluetoothA2dpEnabled.get(); 1665 } 1666 getLeAudioDeviceGroupId(BluetoothDevice device)1667 /*package*/ int getLeAudioDeviceGroupId(BluetoothDevice device) { 1668 return mBtHelper.getLeAudioDeviceGroupId(device); 1669 } 1670 getLeAudioGroupAddresses(int groupId)1671 /*package*/ List<Pair<String, String>> getLeAudioGroupAddresses(int groupId) { 1672 return mBtHelper.getLeAudioGroupAddresses(groupId); 1673 } 1674 broadcastStickyIntentToCurrentProfileGroup(Intent intent)1675 /*package*/ void broadcastStickyIntentToCurrentProfileGroup(Intent intent) { 1676 mSystemServer.broadcastStickyIntentToCurrentProfileGroup(intent); 1677 } 1678 dump(PrintWriter pw, String prefix)1679 /*package*/ void dump(PrintWriter pw, String prefix) { 1680 if (mBrokerHandler != null) { 1681 pw.println(prefix + "Message handler (watch for unhandled messages):"); 1682 mBrokerHandler.dump(new PrintWriterPrinter(pw), prefix + " "); 1683 } else { 1684 pw.println("Message handler is null"); 1685 } 1686 1687 mDeviceInventory.dump(pw, prefix); 1688 1689 pw.println("\n" + prefix + "Communication route clients:"); 1690 mCommunicationRouteClients.forEach((cl) -> { 1691 pw.println(" " + prefix + cl.toString()); }); 1692 1693 pw.println("\n" + prefix + "Computed Preferred communication device: " 1694 + preferredCommunicationDevice()); 1695 pw.println("\n" + prefix + "Applied Preferred communication device: " 1696 + mPreferredCommunicationDevice); 1697 pw.println(prefix + "Active communication device: " 1698 + ((mActiveCommunicationDevice == null) ? "None" 1699 : new AudioDeviceAttributes(mActiveCommunicationDevice))); 1700 1701 pw.println(prefix + "mCommunicationStrategyId: " 1702 + mCommunicationStrategyId); 1703 1704 pw.println(prefix + "mAccessibilityStrategyId: " 1705 + mAccessibilityStrategyId); 1706 1707 pw.println("\n" + prefix + "mAudioModeOwner: " + mAudioModeOwner); 1708 1709 pw.println("\n" + prefix + "mScoManagedByAudio: " + mScoManagedByAudio); 1710 1711 mBtHelper.dump(pw, prefix); 1712 } 1713 1714 //--------------------------------------------------------------------- 1715 // Internal handling of messages 1716 // These methods are ALL synchronous, in response to message handling in BrokerHandler 1717 // Blocking in any of those will block the message queue 1718 onSetForceUse(int useCase, int config, boolean fromA2dp, String eventSource)1719 private void onSetForceUse(int useCase, int config, boolean fromA2dp, String eventSource) { 1720 if (useCase == AudioSystem.FOR_MEDIA) { 1721 postReportNewRoutes(fromA2dp); 1722 } 1723 AudioService.sForceUseLogger.enqueue( 1724 new AudioServiceEvents.ForceUseEvent(useCase, config, eventSource)); 1725 new MediaMetrics.Item(MediaMetrics.Name.AUDIO_FORCE_USE + MediaMetrics.SEPARATOR 1726 + AudioSystem.forceUseUsageToString(useCase)) 1727 .set(MediaMetrics.Property.EVENT, "onSetForceUse") 1728 .set(MediaMetrics.Property.FORCE_USE_DUE_TO, eventSource) 1729 .set(MediaMetrics.Property.FORCE_USE_MODE, 1730 AudioSystem.forceUseConfigToString(config)) 1731 .record(); 1732 1733 if (AudioService.DEBUG_COMM_RTE) { 1734 Log.v(TAG, "onSetForceUse(useCase<" + useCase + ">, config<" + config + ">, fromA2dp<" 1735 + fromA2dp + ">, eventSource<" + eventSource + ">)"); 1736 } 1737 mAudioSystem.setForceUse(useCase, config); 1738 } 1739 onSendBecomingNoisyIntent()1740 private void onSendBecomingNoisyIntent() { 1741 AudioService.sDeviceLogger.enqueue((new EventLogger.StringEvent( 1742 "broadcast ACTION_AUDIO_BECOMING_NOISY")).printLog(TAG)); 1743 mSystemServer.sendDeviceBecomingNoisyIntent(); 1744 } 1745 1746 //--------------------------------------------------------------------- 1747 // Message handling 1748 private BrokerHandler mBrokerHandler; 1749 private BrokerThread mBrokerThread; 1750 private PowerManager.WakeLock mBrokerEventWakeLock; 1751 setupMessaging(Context ctxt)1752 private void setupMessaging(Context ctxt) { 1753 final PowerManager pm = (PowerManager) ctxt.getSystemService(Context.POWER_SERVICE); 1754 mBrokerEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 1755 "handleAudioDeviceEvent"); 1756 mBrokerThread = new BrokerThread(); 1757 mBrokerThread.start(); 1758 waitForBrokerHandlerCreation(); 1759 } 1760 waitForBrokerHandlerCreation()1761 private void waitForBrokerHandlerCreation() { 1762 synchronized (this) { 1763 while (mBrokerHandler == null) { 1764 try { 1765 wait(); 1766 } catch (InterruptedException e) { 1767 Log.e(TAG, "Interruption while waiting on BrokerHandler"); 1768 } 1769 } 1770 } 1771 } 1772 1773 /** Class that handles the device broker's message queue */ 1774 private class BrokerThread extends Thread { BrokerThread()1775 BrokerThread() { 1776 super("AudioDeviceBroker"); 1777 } 1778 1779 @Override run()1780 public void run() { 1781 // Set this thread up so the handler will work on it 1782 Looper.prepare(); 1783 1784 synchronized (AudioDeviceBroker.this) { 1785 mBrokerHandler = new BrokerHandler(); 1786 1787 // Notify that the handler has been created 1788 AudioDeviceBroker.this.notify(); 1789 } 1790 1791 Looper.loop(); 1792 } 1793 } 1794 1795 /** Class that handles the message queue */ 1796 private class BrokerHandler extends Handler { 1797 1798 @Override handleMessage(Message msg)1799 public void handleMessage(Message msg) { 1800 int muteCheckDelayMs = BTA2DP_MUTE_CHECK_DELAY_MS; 1801 switch (msg.what) { 1802 case MSG_RESTORE_DEVICES: 1803 synchronized (mSetModeLock) { 1804 synchronized (mDeviceStateLock) { 1805 initRoutingStrategyIds(); 1806 updateActiveCommunicationDevice(); 1807 mDeviceInventory.onRestoreDevices(); 1808 synchronized (mBluetoothAudioStateLock) { 1809 reapplyAudioHalBluetoothState(); 1810 } 1811 mBtHelper.onAudioServerDiedRestoreA2dp(); 1812 updateCommunicationRoute("MSG_RESTORE_DEVICES"); 1813 } 1814 } 1815 break; 1816 case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE: 1817 synchronized (mDeviceStateLock) { 1818 mDeviceInventory.onSetWiredDeviceConnectionState( 1819 (AudioDeviceInventory.WiredDeviceConnectionState) msg.obj); 1820 } 1821 break; 1822 case MSG_I_BROADCAST_BT_CONNECTION_STATE: 1823 synchronized (mDeviceStateLock) { 1824 mBtHelper.onBroadcastScoConnectionState(msg.arg1); 1825 } 1826 break; 1827 case MSG_IIL_SET_FORCE_USE: // intended fall-through 1828 onSetForceUse(msg.arg1, msg.arg2, false, (String) msg.obj); 1829 break; 1830 case MSG_L_SET_FORCE_BT_A2DP_USE: 1831 case MSG_L_SET_FORCE_BT_A2DP_USE_NO_MUTE: 1832 int forcedUsage = mBluetoothA2dpEnabled.get() 1833 ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP; 1834 onSetForceUse(AudioSystem.FOR_MEDIA, forcedUsage, true, (String) msg.obj); 1835 break; 1836 case MSG_REPORT_NEW_ROUTES: 1837 case MSG_REPORT_NEW_ROUTES_A2DP: 1838 synchronized (mDeviceStateLock) { 1839 mDeviceInventory.onReportNewRoutes(); 1840 } 1841 break; 1842 case MSG_L_SET_BT_ACTIVE_DEVICE: { 1843 final BtDeviceInfo btInfo = (BtDeviceInfo) msg.obj; 1844 if (btInfo.mState == BluetoothProfile.STATE_CONNECTED 1845 && !mBtHelper.isProfilePoxyConnected(btInfo.mProfile)) { 1846 AudioService.sDeviceLogger.enqueue((new EventLogger.StringEvent( 1847 "msg: MSG_L_SET_BT_ACTIVE_DEVICE " 1848 + "received with null profile proxy: " 1849 + btInfo)).printLog(TAG)); 1850 } else { 1851 final Pair<Integer, Boolean> codecAndChanged = 1852 mBtHelper.getCodecWithFallback(btInfo.mDevice, 1853 btInfo.mProfile, btInfo.mIsLeOutput, 1854 "MSG_L_SET_BT_ACTIVE_DEVICE"); 1855 synchronized (mSetModeLock) { 1856 synchronized (mDeviceStateLock) { 1857 mDeviceInventory.onSetBtActiveDevice(btInfo, codecAndChanged.first, 1858 (btInfo.mProfile != BluetoothProfile.LE_AUDIO 1859 || btInfo.mIsLeOutput) 1860 ? mAudioService.getBluetoothContextualVolumeStream() 1861 : AudioSystem.STREAM_DEFAULT); 1862 if (btInfo.mProfile == BluetoothProfile.LE_AUDIO 1863 || btInfo.mProfile == BluetoothProfile.HEARING_AID 1864 || (mScoManagedByAudio 1865 && btInfo.mProfile == BluetoothProfile.HEADSET)) { 1866 onUpdateCommunicationRouteClient(isBluetoothScoRequested(), 1867 "setBluetoothActiveDevice"); 1868 } 1869 } 1870 } 1871 } 1872 } break; 1873 case MSG_BT_HEADSET_CNCT_FAILED: 1874 synchronized (mSetModeLock) { 1875 synchronized (mDeviceStateLock) { 1876 mBtHelper.resetBluetoothSco(); 1877 } 1878 } 1879 break; 1880 case MSG_IL_BTA2DP_TIMEOUT: 1881 // msg.obj == address of BTA2DP device 1882 synchronized (mDeviceStateLock) { 1883 mDeviceInventory.onMakeA2dpDeviceUnavailableNow( 1884 (String) msg.obj, msg.arg1); 1885 } 1886 break; 1887 case MSG_IIL_BTLEAUDIO_TIMEOUT: 1888 // msg.obj == address of LE Audio device 1889 synchronized (mDeviceStateLock) { 1890 mDeviceInventory.onMakeLeAudioDeviceUnavailableNow( 1891 (String) msg.obj, msg.arg1, msg.arg2); 1892 } 1893 break; 1894 case MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE: { 1895 final BtDeviceInfo btInfo = (BtDeviceInfo) msg.obj; 1896 final Pair<Integer, Boolean> codecAndChanged = mBtHelper.getCodecWithFallback( 1897 btInfo.mDevice, btInfo.mProfile, btInfo.mIsLeOutput, 1898 "MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE"); 1899 synchronized (mDeviceStateLock) { 1900 muteCheckDelayMs += mDeviceInventory.onBluetoothDeviceConfigChange(btInfo, 1901 codecAndChanged.first, codecAndChanged.second, 1902 BtHelper.EVENT_DEVICE_CONFIG_CHANGE); 1903 } 1904 } break; 1905 case MSG_BROADCAST_AUDIO_BECOMING_NOISY: 1906 onSendBecomingNoisyIntent(); 1907 break; 1908 case MSG_II_SET_HEARING_AID_VOLUME: 1909 synchronized (mDeviceStateLock) { 1910 mBtHelper.setHearingAidVolume(msg.arg1, msg.arg2, 1911 mDeviceInventory.isHearingAidConnected()); 1912 } 1913 break; 1914 case MSG_II_SET_LE_AUDIO_OUT_VOLUME: { 1915 final BleVolumeInfo info = (BleVolumeInfo) msg.obj; 1916 synchronized (mDeviceStateLock) { 1917 mBtHelper.setLeAudioVolume(info.mIndex, info.mMaxIndex, info.mStreamType); 1918 } 1919 } break; 1920 case MSG_I_SET_AVRCP_ABSOLUTE_VOLUME: 1921 synchronized (mDeviceStateLock) { 1922 mBtHelper.setAvrcpAbsoluteVolumeIndex(msg.arg1); 1923 } 1924 break; 1925 case MSG_I_SET_MODE_OWNER: 1926 synchronized (mSetModeLock) { 1927 synchronized (mDeviceStateLock) { 1928 boolean wasBtScoRequested = isBluetoothScoRequested(); 1929 mAudioModeOwner = (AudioModeInfo) msg.obj; 1930 if (mAudioModeOwner.mMode != AudioSystem.MODE_RINGTONE) { 1931 onUpdateCommunicationRouteClient( 1932 wasBtScoRequested, "setNewModeOwner"); 1933 } 1934 } 1935 } 1936 break; 1937 1938 case MSG_L_SET_COMMUNICATION_DEVICE_FOR_CLIENT: 1939 CommunicationDeviceInfo deviceInfo = (CommunicationDeviceInfo) msg.obj; 1940 synchronized (mSetModeLock) { 1941 synchronized (mDeviceStateLock) { 1942 onSetCommunicationDeviceForClient(deviceInfo); 1943 } 1944 } 1945 synchronized (mCommunicationDeviceLock) { 1946 if (mCommunicationDeviceUpdateCount > 0) { 1947 mCommunicationDeviceUpdateCount--; 1948 } else { 1949 Log.e(TAG, "mCommunicationDeviceUpdateCount already 0 in" 1950 + " MSG_L_SET_COMMUNICATION_DEVICE_FOR_CLIENT"); 1951 } 1952 mCommunicationDeviceLock.notify(); 1953 } 1954 break; 1955 1956 case MSG_IL_UPDATE_COMMUNICATION_ROUTE_CLIENT: 1957 synchronized (mSetModeLock) { 1958 synchronized (mDeviceStateLock) { 1959 onUpdateCommunicationRouteClient(msg.arg1 == 1, (String) msg.obj); 1960 } 1961 } 1962 break; 1963 1964 case MSG_L_COMMUNICATION_ROUTE_CLIENT_DIED: 1965 synchronized (mSetModeLock) { 1966 synchronized (mDeviceStateLock) { 1967 onCommunicationRouteClientDied((CommunicationRouteClient) msg.obj); 1968 } 1969 } 1970 break; 1971 1972 case MSG_L_RECEIVED_BT_EVENT: 1973 synchronized (mSetModeLock) { 1974 synchronized (mDeviceStateLock) { 1975 onReceiveBtEvent((Intent) msg.obj); 1976 } 1977 } 1978 break; 1979 1980 case MSG_TOGGLE_HDMI: 1981 synchronized (mDeviceStateLock) { 1982 mDeviceInventory.onToggleHdmi(); 1983 } 1984 break; 1985 case MSG_I_BT_SERVICE_DISCONNECTED_PROFILE: 1986 synchronized (mSetModeLock) { 1987 synchronized (mDeviceStateLock) { 1988 mBtHelper.onBtProfileDisconnected(msg.arg1); 1989 mDeviceInventory.onBtProfileDisconnected(msg.arg1); 1990 } 1991 } 1992 break; 1993 case MSG_IL_BT_SERVICE_CONNECTED_PROFILE: 1994 synchronized (mSetModeLock) { 1995 synchronized (mDeviceStateLock) { 1996 mBtHelper.onBtProfileConnected(msg.arg1, (BluetoothProfile) msg.obj); 1997 } 1998 } 1999 break; 2000 case MSG_L_BT_ACTIVE_DEVICE_CHANGE_EXT: { 2001 final BtDeviceInfo btInfo = (BtDeviceInfo) msg.obj; 2002 if (btInfo.mDevice == null) break; 2003 AudioService.sDeviceLogger.enqueue((new EventLogger.StringEvent( 2004 "msg: MSG_L_BT_ACTIVE_DEVICE_CHANGE_EXT " + btInfo)).printLog(TAG)); 2005 synchronized (mDeviceStateLock) { 2006 mDeviceInventory.setBluetoothActiveDevice(btInfo); 2007 } 2008 } break; 2009 case MSG_IL_SAVE_PREF_DEVICES_FOR_STRATEGY: { 2010 final int strategy = msg.arg1; 2011 final List<AudioDeviceAttributes> devices = 2012 (List<AudioDeviceAttributes>) msg.obj; 2013 mDeviceInventory.onSaveSetPreferredDevices(strategy, devices); 2014 } break; 2015 case MSG_I_SAVE_REMOVE_PREF_DEVICES_FOR_STRATEGY: { 2016 final int strategy = msg.arg1; 2017 mDeviceInventory.onSaveRemovePreferredDevices(strategy); 2018 } break; 2019 case MSG_IL_SAVE_NDEF_DEVICE_FOR_STRATEGY: { 2020 final int strategy = msg.arg1; 2021 final AudioDeviceAttributes device = (AudioDeviceAttributes) msg.obj; 2022 mDeviceInventory.onSaveSetDeviceAsNonDefault(strategy, device); 2023 } break; 2024 case MSG_IL_SAVE_REMOVE_NDEF_DEVICE_FOR_STRATEGY: { 2025 final int strategy = msg.arg1; 2026 final AudioDeviceAttributes device = (AudioDeviceAttributes) msg.obj; 2027 mDeviceInventory.onSaveRemoveDeviceAsNonDefault(strategy, device); 2028 } break; 2029 case MSG_CHECK_MUTE_MUSIC: 2030 checkMessagesMuteMusic(0); 2031 break; 2032 case MSG_IL_SAVE_PREF_DEVICES_FOR_CAPTURE_PRESET: { 2033 final int capturePreset = msg.arg1; 2034 final List<AudioDeviceAttributes> devices = 2035 (List<AudioDeviceAttributes>) msg.obj; 2036 mDeviceInventory.onSaveSetPreferredDevicesForCapturePreset( 2037 capturePreset, devices); 2038 } break; 2039 case MSG_I_SAVE_CLEAR_PREF_DEVICES_FOR_CAPTURE_PRESET: { 2040 final int capturePreset = msg.arg1; 2041 mDeviceInventory.onSaveClearPreferredDevicesForCapturePreset(capturePreset); 2042 } break; 2043 case MSG_L_NOTIFY_PREFERRED_AUDIOPROFILE_APPLIED: { 2044 final BluetoothDevice btDevice = (BluetoothDevice) msg.obj; 2045 BtHelper.onNotifyPreferredAudioProfileApplied(btDevice); 2046 } break; 2047 case MSG_L_CHECK_COMMUNICATION_DEVICE_REMOVAL: { 2048 synchronized (mSetModeLock) { 2049 synchronized (mDeviceStateLock) { 2050 onCheckCommunicationDeviceRemoval((AudioDeviceAttributes) msg.obj); 2051 } 2052 } 2053 } break; 2054 case MSG_PERSIST_AUDIO_DEVICE_SETTINGS: 2055 onPersistAudioDeviceSettings(); 2056 break; 2057 2058 case MSG_CHECK_COMMUNICATION_ROUTE_CLIENT_STATE: { 2059 synchronized (mDeviceStateLock) { 2060 onCheckCommunicationRouteClientState(msg.arg1, msg.arg2 == 1); 2061 } 2062 } break; 2063 2064 case MSG_I_UPDATE_LE_AUDIO_GROUP_ADDRESSES: 2065 synchronized (mSetModeLock) { 2066 synchronized (mDeviceStateLock) { 2067 mDeviceInventory.onUpdateLeAudioGroupAddresses(msg.arg1); 2068 } 2069 } break; 2070 2071 case MSG_L_SYNCHRONIZE_ADI_DEVICES_IN_INVENTORY: 2072 synchronized (mSetModeLock) { 2073 synchronized (mDeviceStateLock) { 2074 mDeviceInventory.onSynchronizeAdiDevicesInInventory( 2075 (AdiDeviceState) msg.obj); 2076 } 2077 } break; 2078 2079 case MSG_IL_UPDATED_ADI_DEVICE_STATE: 2080 mAudioService.onUpdatedAdiDeviceState((AdiDeviceState) msg.obj, msg.arg1 == 1); 2081 break; 2082 2083 default: 2084 Log.wtf(TAG, "Invalid message " + msg.what); 2085 } 2086 2087 // Give some time to Bluetooth service to post a connection message 2088 // in case of active device switch 2089 if (MESSAGES_MUTE_MUSIC.contains(msg.what)) { 2090 sendMsg(MSG_CHECK_MUTE_MUSIC, SENDMSG_REPLACE, muteCheckDelayMs); 2091 } 2092 2093 if (isMessageHandledUnderWakelock(msg.what)) { 2094 try { 2095 mBrokerEventWakeLock.release(); 2096 } catch (Exception e) { 2097 Log.e(TAG, "Exception releasing wakelock", e); 2098 } 2099 } 2100 } 2101 } 2102 2103 // List of all messages. If a message has be handled under wakelock, add it to 2104 // the isMessageHandledUnderWakelock(int) method 2105 // Naming of msg indicates arguments, using JNI argument grammar 2106 // (e.g. II indicates two int args, IL indicates int and Obj arg) 2107 private static final int MSG_RESTORE_DEVICES = 1; 2108 private static final int MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE = 2; 2109 private static final int MSG_I_BROADCAST_BT_CONNECTION_STATE = 3; 2110 private static final int MSG_IIL_SET_FORCE_USE = 4; 2111 private static final int MSG_L_SET_FORCE_BT_A2DP_USE = 5; 2112 private static final int MSG_TOGGLE_HDMI = 6; 2113 private static final int MSG_L_SET_BT_ACTIVE_DEVICE = 7; 2114 private static final int MSG_BT_HEADSET_CNCT_FAILED = 9; 2115 private static final int MSG_IL_BTA2DP_TIMEOUT = 10; 2116 2117 // process change of A2DP device configuration, obj is BluetoothDevice 2118 private static final int MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE = 11; 2119 2120 private static final int MSG_BROADCAST_AUDIO_BECOMING_NOISY = 12; 2121 private static final int MSG_REPORT_NEW_ROUTES = 13; 2122 private static final int MSG_II_SET_HEARING_AID_VOLUME = 14; 2123 private static final int MSG_I_SET_AVRCP_ABSOLUTE_VOLUME = 15; 2124 private static final int MSG_I_SET_MODE_OWNER = 16; 2125 2126 private static final int MSG_I_BT_SERVICE_DISCONNECTED_PROFILE = 22; 2127 private static final int MSG_IL_BT_SERVICE_CONNECTED_PROFILE = 23; 2128 2129 // process external command to (dis)connect an A2DP device, obj is BtDeviceConnectionInfo 2130 private static final int MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT = 29; 2131 2132 // process external command to (dis)connect a hearing aid device 2133 private static final int MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT = 31; 2134 2135 private static final int MSG_IL_SAVE_PREF_DEVICES_FOR_STRATEGY = 32; 2136 private static final int MSG_I_SAVE_REMOVE_PREF_DEVICES_FOR_STRATEGY = 33; 2137 2138 private static final int MSG_L_COMMUNICATION_ROUTE_CLIENT_DIED = 34; 2139 private static final int MSG_CHECK_MUTE_MUSIC = 35; 2140 private static final int MSG_REPORT_NEW_ROUTES_A2DP = 36; 2141 2142 private static final int MSG_IL_SAVE_PREF_DEVICES_FOR_CAPTURE_PRESET = 37; 2143 private static final int MSG_I_SAVE_CLEAR_PREF_DEVICES_FOR_CAPTURE_PRESET = 38; 2144 2145 private static final int MSG_L_SET_COMMUNICATION_DEVICE_FOR_CLIENT = 42; 2146 private static final int MSG_IL_UPDATE_COMMUNICATION_ROUTE_CLIENT = 43; 2147 2148 private static final int MSG_L_BT_ACTIVE_DEVICE_CHANGE_EXT = 45; 2149 // 2150 // process set volume for Le Audio, obj is BleVolumeInfo 2151 private static final int MSG_II_SET_LE_AUDIO_OUT_VOLUME = 46; 2152 2153 private static final int MSG_IL_SAVE_NDEF_DEVICE_FOR_STRATEGY = 47; 2154 private static final int MSG_IL_SAVE_REMOVE_NDEF_DEVICE_FOR_STRATEGY = 48; 2155 private static final int MSG_IIL_BTLEAUDIO_TIMEOUT = 49; 2156 2157 private static final int MSG_L_NOTIFY_PREFERRED_AUDIOPROFILE_APPLIED = 52; 2158 private static final int MSG_L_CHECK_COMMUNICATION_DEVICE_REMOVAL = 53; 2159 2160 private static final int MSG_PERSIST_AUDIO_DEVICE_SETTINGS = 54; 2161 2162 private static final int MSG_L_RECEIVED_BT_EVENT = 55; 2163 2164 private static final int MSG_CHECK_COMMUNICATION_ROUTE_CLIENT_STATE = 56; 2165 private static final int MSG_I_UPDATE_LE_AUDIO_GROUP_ADDRESSES = 57; 2166 private static final int MSG_L_SYNCHRONIZE_ADI_DEVICES_IN_INVENTORY = 58; 2167 private static final int MSG_IL_UPDATED_ADI_DEVICE_STATE = 59; 2168 private static final int MSG_L_SET_FORCE_BT_A2DP_USE_NO_MUTE = 60; 2169 isMessageHandledUnderWakelock(int msgId)2170 private static boolean isMessageHandledUnderWakelock(int msgId) { 2171 switch(msgId) { 2172 case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE: 2173 case MSG_L_SET_BT_ACTIVE_DEVICE: 2174 case MSG_IL_BTA2DP_TIMEOUT: 2175 case MSG_IIL_BTLEAUDIO_TIMEOUT: 2176 case MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE: 2177 case MSG_TOGGLE_HDMI: 2178 case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT: 2179 case MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT: 2180 case MSG_CHECK_MUTE_MUSIC: 2181 return true; 2182 default: 2183 return false; 2184 } 2185 } 2186 2187 // Message helper methods 2188 2189 // sendMsg() flags 2190 /** If the msg is already queued, replace it with this one. */ 2191 private static final int SENDMSG_REPLACE = 0; 2192 /** If the msg is already queued, ignore this one and leave the old. */ 2193 private static final int SENDMSG_NOOP = 1; 2194 /** If the msg is already queued, queue this one and leave the old. */ 2195 private static final int SENDMSG_QUEUE = 2; 2196 sendMsg(int msg, int existingMsgPolicy, int delay)2197 private void sendMsg(int msg, int existingMsgPolicy, int delay) { 2198 sendIILMsg(msg, existingMsgPolicy, 0, 0, null, delay); 2199 } 2200 sendILMsg(int msg, int existingMsgPolicy, int arg, Object obj, int delay)2201 private void sendILMsg(int msg, int existingMsgPolicy, int arg, Object obj, int delay) { 2202 sendIILMsg(msg, existingMsgPolicy, arg, 0, obj, delay); 2203 } 2204 sendLMsg(int msg, int existingMsgPolicy, Object obj, int delay)2205 private void sendLMsg(int msg, int existingMsgPolicy, Object obj, int delay) { 2206 sendIILMsg(msg, existingMsgPolicy, 0, 0, obj, delay); 2207 } 2208 sendMsgNoDelay(int msg, int existingMsgPolicy)2209 private void sendMsgNoDelay(int msg, int existingMsgPolicy) { 2210 sendIILMsg(msg, existingMsgPolicy, 0, 0, null, 0); 2211 } 2212 sendIMsgNoDelay(int msg, int existingMsgPolicy, int arg)2213 private void sendIMsgNoDelay(int msg, int existingMsgPolicy, int arg) { 2214 sendIILMsg(msg, existingMsgPolicy, arg, 0, null, 0); 2215 } 2216 sendIIMsgNoDelay(int msg, int existingMsgPolicy, int arg1, int arg2)2217 private void sendIIMsgNoDelay(int msg, int existingMsgPolicy, int arg1, int arg2) { 2218 sendIILMsg(msg, existingMsgPolicy, arg1, arg2, null, 0); 2219 } 2220 sendILMsgNoDelay(int msg, int existingMsgPolicy, int arg, Object obj)2221 private void sendILMsgNoDelay(int msg, int existingMsgPolicy, int arg, Object obj) { 2222 sendIILMsg(msg, existingMsgPolicy, arg, 0, obj, 0); 2223 } 2224 sendLMsgNoDelay(int msg, int existingMsgPolicy, Object obj)2225 private void sendLMsgNoDelay(int msg, int existingMsgPolicy, Object obj) { 2226 sendIILMsg(msg, existingMsgPolicy, 0, 0, obj, 0); 2227 } 2228 sendIILMsgNoDelay(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj)2229 private void sendIILMsgNoDelay(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj) { 2230 sendIILMsg(msg, existingMsgPolicy, arg1, arg2, obj, 0); 2231 } 2232 sendIILMsg(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj, int delay)2233 private void sendIILMsg(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj, 2234 int delay) { 2235 if (existingMsgPolicy == SENDMSG_REPLACE) { 2236 mBrokerHandler.removeMessages(msg); 2237 } else if (existingMsgPolicy == SENDMSG_NOOP && mBrokerHandler.hasMessages(msg)) { 2238 return; 2239 } 2240 2241 if (isMessageHandledUnderWakelock(msg)) { 2242 final long identity = Binder.clearCallingIdentity(); 2243 try { 2244 mBrokerEventWakeLock.acquire(BROKER_WAKELOCK_TIMEOUT_MS); 2245 } catch (Exception e) { 2246 Log.e(TAG, "Exception acquiring wakelock", e); 2247 } finally { 2248 Binder.restoreCallingIdentity(identity); 2249 } 2250 } 2251 2252 if (MESSAGES_MUTE_MUSIC.contains(msg)) { 2253 checkMessagesMuteMusic(msg); 2254 } 2255 2256 synchronized (sLastDeviceConnectionMsgTimeLock) { 2257 long time = SystemClock.uptimeMillis() + delay; 2258 2259 switch (msg) { 2260 case MSG_L_SET_BT_ACTIVE_DEVICE: 2261 case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE: 2262 case MSG_IL_BTA2DP_TIMEOUT: 2263 case MSG_IIL_BTLEAUDIO_TIMEOUT: 2264 case MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE: 2265 if (sLastDeviceConnectMsgTime >= time) { 2266 // add a little delay to make sure messages are ordered as expected 2267 time = sLastDeviceConnectMsgTime + 30; 2268 } 2269 sLastDeviceConnectMsgTime = time; 2270 break; 2271 default: 2272 break; 2273 } 2274 mBrokerHandler.sendMessageAtTime(mBrokerHandler.obtainMessage(msg, arg1, arg2, obj), 2275 time); 2276 } 2277 } 2278 removeMsgForCheckClientState(int uid)2279 private void removeMsgForCheckClientState(int uid) { 2280 CommunicationRouteClient crc = getCommunicationRouteClientForUid(uid); 2281 if (crc != null) { 2282 mBrokerHandler.removeEqualMessages(MSG_CHECK_COMMUNICATION_ROUTE_CLIENT_STATE, crc); 2283 } 2284 } 2285 sendMsgForCheckClientState(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj, int delay)2286 private void sendMsgForCheckClientState(int msg, int existingMsgPolicy, 2287 int arg1, int arg2, Object obj, int delay) { 2288 if ((existingMsgPolicy == SENDMSG_REPLACE) && (obj != null)) { 2289 mBrokerHandler.removeEqualMessages(msg, obj); 2290 } 2291 2292 long time = SystemClock.uptimeMillis() + delay; 2293 mBrokerHandler.sendMessageAtTime(mBrokerHandler.obtainMessage(msg, arg1, arg2, obj), time); 2294 } 2295 2296 /** List of messages for which music is muted while processing is pending */ 2297 private static final Set<Integer> MESSAGES_MUTE_MUSIC; 2298 static { 2299 MESSAGES_MUTE_MUSIC = new HashSet<>(); 2300 MESSAGES_MUTE_MUSIC.add(MSG_L_SET_BT_ACTIVE_DEVICE); 2301 MESSAGES_MUTE_MUSIC.add(MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE); 2302 MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT); 2303 MESSAGES_MUTE_MUSIC.add(MSG_L_SET_FORCE_BT_A2DP_USE); 2304 } 2305 2306 private AtomicBoolean mMusicMuted = new AtomicBoolean(false); 2307 hasIntersection(Set<T> a, Set<T> b)2308 private static <T> boolean hasIntersection(Set<T> a, Set<T> b) { 2309 for (T e : a) { 2310 if (b.contains(e)) return true; 2311 } 2312 return false; 2313 } 2314 messageMutesMusic(int message)2315 boolean messageMutesMusic(int message) { 2316 if (message == 0) { 2317 return false; 2318 } 2319 // Do not mute on bluetooth event if music is playing on a wired headset. 2320 if ((message == MSG_L_SET_BT_ACTIVE_DEVICE 2321 || message == MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT 2322 || message == MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE) 2323 && AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0) 2324 && hasIntersection(mDeviceInventory.DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET, 2325 mAudioService.getDeviceSetForStream(AudioSystem.STREAM_MUSIC))) { 2326 return false; 2327 } 2328 return true; 2329 } 2330 2331 /** Mutes or unmutes music according to pending A2DP messages */ checkMessagesMuteMusic(int message)2332 private void checkMessagesMuteMusic(int message) { 2333 boolean mute = messageMutesMusic(message); 2334 if (!mute) { 2335 for (int msg : MESSAGES_MUTE_MUSIC) { 2336 if (mBrokerHandler.hasMessages(msg)) { 2337 if (messageMutesMusic(msg)) { 2338 mute = true; 2339 break; 2340 } 2341 } 2342 } 2343 } 2344 2345 if (mute != mMusicMuted.getAndSet(mute)) { 2346 mAudioService.setMusicMute(mute); 2347 } 2348 } 2349 2350 // List of applications requesting a specific route for communication. 2351 @GuardedBy("mDeviceStateLock") 2352 private final @NonNull LinkedList<CommunicationRouteClient> mCommunicationRouteClients = 2353 new LinkedList<CommunicationRouteClient>(); 2354 2355 private class CommunicationRouteClient implements IBinder.DeathRecipient { 2356 private final IBinder mCb; 2357 private final int mUid; 2358 private final boolean mIsPrivileged; 2359 private AudioDeviceAttributes mDevice; 2360 private boolean mPlaybackActive; 2361 private boolean mRecordingActive; 2362 CommunicationRouteClient(IBinder cb, int uid, AudioDeviceAttributes device, boolean isPrivileged)2363 CommunicationRouteClient(IBinder cb, int uid, AudioDeviceAttributes device, 2364 boolean isPrivileged) { 2365 mCb = cb; 2366 mUid = uid; 2367 mDevice = device; 2368 mIsPrivileged = isPrivileged; 2369 mPlaybackActive = mAudioService.isPlaybackActiveForUid(uid); 2370 mRecordingActive = mAudioService.isRecordingActiveForUid(uid); 2371 } 2372 registerDeathRecipient()2373 public boolean registerDeathRecipient() { 2374 boolean status = false; 2375 try { 2376 mCb.linkToDeath(this, 0); 2377 status = true; 2378 } catch (RemoteException e) { 2379 Log.w(TAG, "CommunicationRouteClient could not link to " + mCb + " binder death"); 2380 } 2381 return status; 2382 } 2383 unregisterDeathRecipient()2384 public void unregisterDeathRecipient() { 2385 try { 2386 mCb.unlinkToDeath(this, 0); 2387 } catch (NoSuchElementException e) { 2388 Log.w(TAG, "CommunicationRouteClient could not unlink to " + mCb + " binder death"); 2389 } 2390 } 2391 2392 @Override binderDied()2393 public void binderDied() { 2394 postCommunicationRouteClientDied(this); 2395 } 2396 getBinder()2397 IBinder getBinder() { 2398 return mCb; 2399 } 2400 getUid()2401 int getUid() { 2402 return mUid; 2403 } 2404 isPrivileged()2405 boolean isPrivileged() { 2406 return mIsPrivileged; 2407 } 2408 getDevice()2409 AudioDeviceAttributes getDevice() { 2410 return mDevice; 2411 } 2412 setPlaybackActive(boolean active)2413 public void setPlaybackActive(boolean active) { 2414 mPlaybackActive = active; 2415 } 2416 setRecordingActive(boolean active)2417 public void setRecordingActive(boolean active) { 2418 mRecordingActive = active; 2419 } 2420 isActive()2421 public boolean isActive() { 2422 return mIsPrivileged || mRecordingActive || mPlaybackActive; 2423 } 2424 2425 @Override toString()2426 public String toString() { 2427 return "[CommunicationRouteClient: mUid: " + mUid 2428 + " mDevice: " + mDevice.toString() 2429 + " mIsPrivileged: " + mIsPrivileged 2430 + " mPlaybackActive: " + mPlaybackActive 2431 + " mRecordingActive: " + mRecordingActive + "]"; 2432 } 2433 } 2434 2435 // @GuardedBy("mSetModeLock") 2436 @GuardedBy("mDeviceStateLock") onCommunicationRouteClientDied(CommunicationRouteClient client)2437 private void onCommunicationRouteClientDied(CommunicationRouteClient client) { 2438 if (client == null) { 2439 return; 2440 } 2441 Log.w(TAG, "Communication client died"); 2442 setCommunicationRouteForClient(client.getBinder(), client.getUid(), null, 2443 BtHelper.SCO_MODE_UNDEFINED, client.isPrivileged(), 2444 "onCommunicationRouteClientDied"); 2445 } 2446 2447 /** 2448 * Determines which preferred device for phone strategy should be sent to audio policy manager 2449 * as a function of current SCO audio activation state and active communication route requests. 2450 * SCO audio state has the highest priority as it can result from external activation by 2451 * telephony service. 2452 * @return selected forced usage for communication. 2453 */ 2454 @GuardedBy("mDeviceStateLock") preferredCommunicationDevice()2455 @Nullable private AudioDeviceAttributes preferredCommunicationDevice() { 2456 boolean btSCoOn = mBtHelper.isBluetoothScoOn(); 2457 synchronized (mBluetoothAudioStateLock) { 2458 btSCoOn = btSCoOn && mBluetoothScoOn; 2459 } 2460 2461 if (btSCoOn) { 2462 // Use the SCO device known to BtHelper so that it matches exactly 2463 // what has been communicated to audio policy manager. The device 2464 // returned by requestedCommunicationDevice() can be a placeholder SCO device if legacy 2465 // APIs are used to start SCO audio. 2466 AudioDeviceAttributes device = mBtHelper.getHeadsetAudioDevice(); 2467 if (device != null) { 2468 return device; 2469 } 2470 } 2471 AudioDeviceAttributes device = requestedCommunicationDevice(); 2472 if (device == null || device.getType() == AudioDeviceInfo.TYPE_BLUETOOTH_SCO) { 2473 // Do not indicate BT SCO selection if SCO is requested but SCO is not ON 2474 return null; 2475 } 2476 return device; 2477 } 2478 2479 /** 2480 * Configures audio policy manager and audio HAL according to active communication route. 2481 * Always called from message Handler. 2482 */ 2483 // @GuardedBy("mSetModeLock") 2484 @GuardedBy("mDeviceStateLock") updateCommunicationRoute(String eventSource)2485 private void updateCommunicationRoute(String eventSource) { 2486 AudioDeviceAttributes preferredCommunicationDevice = preferredCommunicationDevice(); 2487 if (AudioService.DEBUG_COMM_RTE) { 2488 Log.v(TAG, "updateCommunicationRoute, preferredCommunicationDevice: " 2489 + preferredCommunicationDevice + " eventSource: " + eventSource); 2490 } 2491 AudioService.sDeviceLogger.enqueue((new EventLogger.StringEvent( 2492 "updateCommunicationRoute, preferredCommunicationDevice: " 2493 + preferredCommunicationDevice + " eventSource: " + eventSource))); 2494 2495 if (preferredCommunicationDevice == null) { 2496 AudioDeviceAttributes defaultDevice = getDefaultCommunicationDevice(); 2497 if (defaultDevice != null) { 2498 mDeviceInventory.setPreferredDevicesForStrategyInt( 2499 mCommunicationStrategyId, Arrays.asList(defaultDevice)); 2500 mDeviceInventory.setPreferredDevicesForStrategyInt( 2501 mAccessibilityStrategyId, Arrays.asList(defaultDevice)); 2502 } else { 2503 mDeviceInventory.removePreferredDevicesForStrategyInt(mCommunicationStrategyId); 2504 mDeviceInventory.removePreferredDevicesForStrategyInt(mAccessibilityStrategyId); 2505 } 2506 mDeviceInventory.applyConnectedDevicesRoles(); 2507 mDeviceInventory.reapplyExternalDevicesRoles(); 2508 } else { 2509 mDeviceInventory.setPreferredDevicesForStrategyInt( 2510 mCommunicationStrategyId, Arrays.asList(preferredCommunicationDevice)); 2511 mDeviceInventory.setPreferredDevicesForStrategyInt( 2512 mAccessibilityStrategyId, Arrays.asList(preferredCommunicationDevice)); 2513 } 2514 onUpdatePhoneStrategyDevice(preferredCommunicationDevice); 2515 } 2516 2517 /** 2518 * Select new communication device from communication route client at the top of the stack 2519 * and restore communication route including restarting SCO audio if needed. 2520 */ 2521 // @GuardedBy("mSetModeLock") 2522 @GuardedBy("mDeviceStateLock") onUpdateCommunicationRouteClient(boolean wasBtScoRequested, String eventSource)2523 private void onUpdateCommunicationRouteClient(boolean wasBtScoRequested, String eventSource) { 2524 CommunicationRouteClient crc = topCommunicationRouteClient(); 2525 if (AudioService.DEBUG_COMM_RTE) { 2526 Log.v(TAG, "onUpdateCommunicationRouteClient, crc: " + crc 2527 + " wasBtScoRequested: " + wasBtScoRequested + " eventSource: " + eventSource); 2528 } 2529 if (crc != null) { 2530 setCommunicationRouteForClient(crc.getBinder(), crc.getUid(), crc.getDevice(), 2531 BtHelper.SCO_MODE_UNDEFINED, crc.isPrivileged(), eventSource); 2532 } else { 2533 if (!mScoManagedByAudio && !isBluetoothScoRequested() && wasBtScoRequested) { 2534 mBtHelper.stopBluetoothSco(eventSource); 2535 } 2536 updateCommunicationRoute(eventSource); 2537 } 2538 } 2539 2540 // @GuardedBy("mSetModeLock") 2541 @GuardedBy("mDeviceStateLock") onUpdatePhoneStrategyDevice(AudioDeviceAttributes device)2542 private void onUpdatePhoneStrategyDevice(AudioDeviceAttributes device) { 2543 boolean wasSpeakerphoneActive = isSpeakerphoneActive(); 2544 mPreferredCommunicationDevice = device; 2545 updateActiveCommunicationDevice(); 2546 if (wasSpeakerphoneActive != isSpeakerphoneActive()) { 2547 try { 2548 mContext.sendBroadcastAsUser( 2549 new Intent(AudioManager.ACTION_SPEAKERPHONE_STATE_CHANGED) 2550 .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY), 2551 UserHandle.ALL); 2552 } catch (Exception e) { 2553 Log.w(TAG, "failed to broadcast ACTION_SPEAKERPHONE_STATE_CHANGED: " + e); 2554 } 2555 } 2556 mAudioService.postUpdateRingerModeServiceInt(); 2557 dispatchCommunicationDevice(); 2558 } 2559 2560 @GuardedBy("mDeviceStateLock") removeCommunicationRouteClient( IBinder cb, boolean unregister)2561 private CommunicationRouteClient removeCommunicationRouteClient( 2562 IBinder cb, boolean unregister) { 2563 for (CommunicationRouteClient cl : mCommunicationRouteClients) { 2564 if (cl.getBinder() == cb) { 2565 if (unregister) { 2566 cl.unregisterDeathRecipient(); 2567 } 2568 removeMsgForCheckClientState(cl.getUid()); 2569 mCommunicationRouteClients.remove(cl); 2570 return cl; 2571 } 2572 } 2573 return null; 2574 } 2575 2576 @GuardedBy("mDeviceStateLock") addCommunicationRouteClient(IBinder cb, int uid, AudioDeviceAttributes device, boolean isPrivileged)2577 private CommunicationRouteClient addCommunicationRouteClient(IBinder cb, int uid, 2578 AudioDeviceAttributes device, boolean isPrivileged) { 2579 // always insert new request at first position 2580 removeCommunicationRouteClient(cb, true); 2581 CommunicationRouteClient client = 2582 new CommunicationRouteClient(cb, uid, device, isPrivileged); 2583 if (client.registerDeathRecipient()) { 2584 mCommunicationRouteClients.add(0, client); 2585 if (!client.isActive()) { 2586 // initialize the inactive client's state as active and check it after 6 seconds 2587 setForceCommunicationClientStateAndDelayedCheck( 2588 client, 2589 !mAudioService.isPlaybackActiveForUid(client.getUid()), 2590 !mAudioService.isRecordingActiveForUid(client.getUid())); 2591 } 2592 return client; 2593 } 2594 return null; 2595 } 2596 2597 @GuardedBy("mDeviceStateLock") getCommunicationRouteClientForUid(int uid)2598 private CommunicationRouteClient getCommunicationRouteClientForUid(int uid) { 2599 for (CommunicationRouteClient cl : mCommunicationRouteClients) { 2600 if (cl.getUid() == uid) { 2601 return cl; 2602 } 2603 } 2604 return null; 2605 } 2606 2607 @GuardedBy("mDeviceStateLock") 2608 // LE Audio: For system server (Telecom) and APKs targeting S and above, we let the audio 2609 // policy routing rules select the default communication device. 2610 // For older APKs, we force LE Audio headset when connected as those APKs cannot select a LE 2611 // Audiodevice explicitly. communnicationDeviceLeAudioCompatOn()2612 private boolean communnicationDeviceLeAudioCompatOn() { 2613 return mAudioModeOwner.mMode == AudioSystem.MODE_IN_COMMUNICATION 2614 && !(CompatChanges.isChangeEnabled( 2615 USE_SET_COMMUNICATION_DEVICE, mAudioModeOwner.mUid) 2616 || mAudioModeOwner.mUid == android.os.Process.SYSTEM_UID); 2617 } 2618 2619 @GuardedBy("mDeviceStateLock") 2620 // Hearing Aid: For system server (Telecom) and IN_CALL mode we let the audio 2621 // policy routing rules select the default communication device. 2622 // For 3p apps and IN_COMMUNICATION mode we force Hearing aid when connected to maintain 2623 // backwards compatibility communnicationDeviceHaCompatOn()2624 private boolean communnicationDeviceHaCompatOn() { 2625 return mAudioModeOwner.mMode == AudioSystem.MODE_IN_COMMUNICATION 2626 && !(mAudioModeOwner.mUid == android.os.Process.SYSTEM_UID); 2627 } 2628 2629 @GuardedBy("mDeviceStateLock") getDefaultCommunicationDevice()2630 AudioDeviceAttributes getDefaultCommunicationDevice() { 2631 AudioDeviceAttributes device = null; 2632 // If both LE and Hearing Aid are active (thie should not happen), 2633 // priority to Hearing Aid. 2634 if (communnicationDeviceHaCompatOn()) { 2635 device = mDeviceInventory.getDeviceOfType(AudioSystem.DEVICE_OUT_HEARING_AID); 2636 } 2637 if (device == null && communnicationDeviceLeAudioCompatOn()) { 2638 device = mDeviceInventory.getDeviceOfType(AudioSystem.DEVICE_OUT_BLE_HEADSET); 2639 } 2640 return device; 2641 } 2642 updateCommunicationRouteClientsActivity( List<AudioPlaybackConfiguration> playbackConfigs, List<AudioRecordingConfiguration> recordConfigs)2643 void updateCommunicationRouteClientsActivity( 2644 List<AudioPlaybackConfiguration> playbackConfigs, 2645 List<AudioRecordingConfiguration> recordConfigs) { 2646 synchronized (mSetModeLock) { 2647 synchronized (mDeviceStateLock) { 2648 for (CommunicationRouteClient crc : mCommunicationRouteClients) { 2649 boolean wasActive = crc.isActive(); 2650 boolean updateClientState = false; 2651 if (playbackConfigs != null) { 2652 crc.setPlaybackActive(false); 2653 for (AudioPlaybackConfiguration config : playbackConfigs) { 2654 if (config.getClientUid() == crc.getUid() 2655 && config.isActive()) { 2656 crc.setPlaybackActive(true); 2657 updateClientState = true; 2658 break; 2659 } 2660 } 2661 } 2662 if (recordConfigs != null) { 2663 crc.setRecordingActive(false); 2664 for (AudioRecordingConfiguration config : recordConfigs) { 2665 if (config.getClientUid() == crc.getUid() 2666 && !config.isClientSilenced()) { 2667 crc.setRecordingActive(true); 2668 updateClientState = true; 2669 break; 2670 } 2671 } 2672 } 2673 if (updateClientState) { 2674 removeMsgForCheckClientState(crc.getUid()); 2675 updateCommunicationRouteClientState(crc, wasActive); 2676 } else { 2677 if (wasActive) { 2678 setForceCommunicationClientStateAndDelayedCheck( 2679 crc, 2680 playbackConfigs != null /* forcePlaybackActive */, 2681 recordConfigs != null /* forceRecordingActive */); 2682 } 2683 } 2684 } 2685 } 2686 } 2687 } 2688 getDeviceIdentityAddresses(AudioDeviceAttributes device)2689 List<String> getDeviceIdentityAddresses(AudioDeviceAttributes device) { 2690 synchronized (mDeviceStateLock) { 2691 return mDeviceInventory.getDeviceIdentityAddresses(device); 2692 } 2693 } 2694 dispatchPreferredMixerAttributesChangedCausedByDeviceRemoved(AudioDeviceInfo info)2695 void dispatchPreferredMixerAttributesChangedCausedByDeviceRemoved(AudioDeviceInfo info) { 2696 // Currently, only media usage will be allowed to set preferred mixer attributes 2697 mAudioService.dispatchPreferredMixerAttributesChanged( 2698 new AudioAttributes.Builder() 2699 .setUsage(AudioAttributes.USAGE_MEDIA).build(), 2700 info.getId(), 2701 null /*mixerAttributes*/); 2702 } 2703 2704 /** 2705 * post a message to persist the audio device settings. 2706 * Message is delayed by 1s on purpose in case of successive changes in quick succession (at 2707 * init time for instance) 2708 * Note this method is made public to work around a Mockito bug where it needs to be public 2709 * in order to be mocked by a test a the same package 2710 * (see https://code.google.com/archive/p/mockito/issues/127) 2711 */ postPersistAudioDeviceSettings()2712 public void postPersistAudioDeviceSettings() { 2713 sendMsg(MSG_PERSIST_AUDIO_DEVICE_SETTINGS, SENDMSG_REPLACE, /*delay*/ 1000); 2714 } 2715 onPersistAudioDeviceSettings()2716 void onPersistAudioDeviceSettings() { 2717 final String deviceSettings = mDeviceInventory.getDeviceSettings(); 2718 Log.v(TAG, "onPersistAudioDeviceSettings AdiDeviceState: " + deviceSettings); 2719 String currentSettings = readDeviceSettings(); 2720 if (deviceSettings.equals(currentSettings)) { 2721 return; 2722 } 2723 final SettingsAdapter settingsAdapter = mAudioService.getSettings(); 2724 try { 2725 boolean res = settingsAdapter.putSecureStringForUser(mAudioService.getContentResolver(), 2726 Settings.Secure.AUDIO_DEVICE_INVENTORY, 2727 deviceSettings, UserHandle.USER_CURRENT); 2728 if (!res) { 2729 Log.e(TAG, "error saving AdiDeviceState: " + deviceSettings); 2730 } 2731 } catch (IllegalArgumentException e) { 2732 Log.e(TAG, "error saving AdiDeviceState: " + deviceSettings, e); 2733 } 2734 } 2735 readDeviceSettings()2736 private String readDeviceSettings() { 2737 final SettingsAdapter settingsAdapter = mAudioService.getSettings(); 2738 final ContentResolver contentResolver = mAudioService.getContentResolver(); 2739 return settingsAdapter.getSecureStringForUser(contentResolver, 2740 Settings.Secure.AUDIO_DEVICE_INVENTORY, UserHandle.USER_CURRENT); 2741 } 2742 onReadAudioDeviceSettings()2743 void onReadAudioDeviceSettings() { 2744 final SettingsAdapter settingsAdapter = mAudioService.getSettings(); 2745 final ContentResolver contentResolver = mAudioService.getContentResolver(); 2746 String settings = readDeviceSettings(); 2747 if (settings == null) { 2748 Log.i(TAG, "reading AdiDeviceState from legacy key" 2749 + Settings.Secure.SPATIAL_AUDIO_ENABLED); 2750 // legacy string format for key SPATIAL_AUDIO_ENABLED has the same order of fields like 2751 // the strings for key AUDIO_DEVICE_INVENTORY. This will ensure to construct valid 2752 // device settings when calling {@link #setDeviceSettings()} 2753 settings = settingsAdapter.getSecureStringForUser(contentResolver, 2754 Settings.Secure.SPATIAL_AUDIO_ENABLED, UserHandle.USER_CURRENT); 2755 if (settings == null) { 2756 Log.i(TAG, "no AdiDeviceState stored with legacy key"); 2757 } else if (!settings.equals("")) { 2758 // Delete old key value and update the new key 2759 if (!settingsAdapter.putSecureStringForUser(contentResolver, 2760 Settings.Secure.SPATIAL_AUDIO_ENABLED, 2761 /*value=*/"", 2762 UserHandle.USER_CURRENT)) { 2763 Log.w(TAG, "cannot erase the legacy AdiDeviceState with key " 2764 + Settings.Secure.SPATIAL_AUDIO_ENABLED); 2765 } 2766 if (!settingsAdapter.putSecureStringForUser(contentResolver, 2767 Settings.Secure.AUDIO_DEVICE_INVENTORY, 2768 settings, 2769 UserHandle.USER_CURRENT)) { 2770 Log.e(TAG, "error updating the new AdiDeviceState with key " 2771 + Settings.Secure.AUDIO_DEVICE_INVENTORY); 2772 } 2773 } 2774 } 2775 2776 if (settings != null && !settings.equals("")) { 2777 setDeviceSettings(settings); 2778 } 2779 } 2780 setDeviceSettings(String settings)2781 void setDeviceSettings(String settings) { 2782 mDeviceInventory.setDeviceSettings(settings); 2783 } 2784 2785 /** Test only method. */ getDeviceSettings()2786 String getDeviceSettings() { 2787 return mDeviceInventory.getDeviceSettings(); 2788 } 2789 getImmutableDeviceInventory()2790 Collection<AdiDeviceState> getImmutableDeviceInventory() { 2791 return mDeviceInventory.getImmutableDeviceInventory(); 2792 } 2793 addOrUpdateDeviceSAStateInInventory(AdiDeviceState deviceState, boolean syncInventory)2794 void addOrUpdateDeviceSAStateInInventory(AdiDeviceState deviceState, boolean syncInventory) { 2795 mDeviceInventory.addOrUpdateDeviceSAStateInInventory(deviceState, syncInventory); 2796 } 2797 addOrUpdateBtAudioDeviceCategoryInInventory( AdiDeviceState deviceState, boolean syncInventory)2798 void addOrUpdateBtAudioDeviceCategoryInInventory( 2799 AdiDeviceState deviceState, boolean syncInventory) { 2800 mDeviceInventory.addOrUpdateAudioDeviceCategoryInInventory(deviceState, syncInventory); 2801 } 2802 2803 @Nullable findDeviceStateForAudioDeviceAttributes(AudioDeviceAttributes ada, int canonicalType)2804 AdiDeviceState findDeviceStateForAudioDeviceAttributes(AudioDeviceAttributes ada, 2805 int canonicalType) { 2806 return mDeviceInventory.findDeviceStateForAudioDeviceAttributes(ada, canonicalType); 2807 } 2808 2809 @Nullable findBtDeviceStateForAddress(String address, int deviceType)2810 AdiDeviceState findBtDeviceStateForAddress(String address, int deviceType) { 2811 return mDeviceInventory.findBtDeviceStateForAddress(address, deviceType); 2812 } 2813 addAudioDeviceWithCategoryInInventoryIfNeeded(@onNull String address, @AudioDeviceCategory int btAudioDeviceCategory)2814 void addAudioDeviceWithCategoryInInventoryIfNeeded(@NonNull String address, 2815 @AudioDeviceCategory int btAudioDeviceCategory) { 2816 mDeviceInventory.addAudioDeviceWithCategoryInInventoryIfNeeded(address, 2817 btAudioDeviceCategory); 2818 } 2819 2820 @AudioDeviceCategory getAndUpdateBtAdiDeviceStateCategoryForAddress(@onNull String address)2821 int getAndUpdateBtAdiDeviceStateCategoryForAddress(@NonNull String address) { 2822 return mDeviceInventory.getAndUpdateBtAdiDeviceStateCategoryForAddress(address); 2823 } 2824 isBluetoothAudioDeviceCategoryFixed(@onNull String address)2825 boolean isBluetoothAudioDeviceCategoryFixed(@NonNull String address) { 2826 return mDeviceInventory.isBluetoothAudioDeviceCategoryFixed(address); 2827 } 2828 isSADevice(AdiDeviceState deviceState)2829 /*package*/ boolean isSADevice(AdiDeviceState deviceState) { 2830 return mAudioService.isSADevice(deviceState); 2831 } 2832 2833 //------------------------------------------------ 2834 // for testing purposes only clearDeviceInventory()2835 void clearDeviceInventory() { 2836 mDeviceInventory.clearDeviceInventory(); 2837 } 2838 2839 } 2840