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