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)1252 /*package*/ void registerStrategyPreferredDevicesDispatcher( 1253 @NonNull IStrategyPreferredDevicesDispatcher dispatcher) { 1254 mDeviceInventory.registerStrategyPreferredDevicesDispatcher(dispatcher); 1255 } 1256 unregisterStrategyPreferredDevicesDispatcher( @onNull IStrategyPreferredDevicesDispatcher dispatcher)1257 /*package*/ void unregisterStrategyPreferredDevicesDispatcher( 1258 @NonNull IStrategyPreferredDevicesDispatcher dispatcher) { 1259 mDeviceInventory.unregisterStrategyPreferredDevicesDispatcher(dispatcher); 1260 } 1261 registerStrategyNonDefaultDevicesDispatcher( @onNull IStrategyNonDefaultDevicesDispatcher dispatcher)1262 /*package*/ void registerStrategyNonDefaultDevicesDispatcher( 1263 @NonNull IStrategyNonDefaultDevicesDispatcher dispatcher) { 1264 mDeviceInventory.registerStrategyNonDefaultDevicesDispatcher(dispatcher); 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)1281 /*package*/ void registerCapturePresetDevicesRoleDispatcher( 1282 @NonNull ICapturePresetDevicesRoleDispatcher dispatcher) { 1283 mDeviceInventory.registerCapturePresetDevicesRoleDispatcher(dispatcher); 1284 } 1285 unregisterCapturePresetDevicesRoleDispatcher( @onNull ICapturePresetDevicesRoleDispatcher dispatcher)1286 /*package*/ void unregisterCapturePresetDevicesRoleDispatcher( 1287 @NonNull ICapturePresetDevicesRoleDispatcher dispatcher) { 1288 mDeviceInventory.unregisterCapturePresetDevicesRoleDispatcher(dispatcher); 1289 } 1290 registerCommunicationDeviceDispatcher( @onNull ICommunicationDeviceDispatcher dispatcher)1291 /*package*/ void registerCommunicationDeviceDispatcher( 1292 @NonNull ICommunicationDeviceDispatcher dispatcher) { 1293 mCommDevDispatchers.register(dispatcher); 1294 } 1295 unregisterCommunicationDeviceDispatcher( @onNull ICommunicationDeviceDispatcher dispatcher)1296 /*package*/ void unregisterCommunicationDeviceDispatcher( 1297 @NonNull ICommunicationDeviceDispatcher dispatcher) { 1298 mCommDevDispatchers.unregister(dispatcher); 1299 } 1300 1301 // Monitoring of communication device 1302 final RemoteCallbackList<ICommunicationDeviceDispatcher> mCommDevDispatchers = 1303 new RemoteCallbackList<ICommunicationDeviceDispatcher>(); 1304 1305 // portId of the device currently selected for communication: avoids broadcasting changes 1306 // when same communication route is applied 1307 @GuardedBy("mDeviceStateLock") 1308 int mCurCommunicationPortId = -1; 1309 1310 @GuardedBy("mDeviceStateLock") dispatchCommunicationDevice()1311 private void dispatchCommunicationDevice() { 1312 AudioDeviceInfo device = getCommunicationDevice(); 1313 int portId = device != null ? device.getId() : 0; 1314 if (portId == mCurCommunicationPortId) { 1315 return; 1316 } 1317 mCurCommunicationPortId = portId; 1318 1319 final int nbDispatchers = mCommDevDispatchers.beginBroadcast(); 1320 for (int i = 0; i < nbDispatchers; i++) { 1321 try { 1322 mCommDevDispatchers.getBroadcastItem(i) 1323 .dispatchCommunicationDeviceChanged(portId); 1324 } catch (RemoteException e) { 1325 } 1326 } 1327 mCommDevDispatchers.finishBroadcast(); 1328 } 1329 1330 1331 //--------------------------------------------------------------------- 1332 // Communication with (to) AudioService 1333 //TODO check whether the AudioService methods are candidates to move here postAccessoryPlugMediaUnmute(int device)1334 /*package*/ void postAccessoryPlugMediaUnmute(int device) { 1335 mAudioService.postAccessoryPlugMediaUnmute(device); 1336 } 1337 getVssVolumeForDevice(int streamType, int device)1338 /*package*/ int getVssVolumeForDevice(int streamType, int device) { 1339 return mAudioService.getVssVolumeForDevice(streamType, device); 1340 } 1341 getMaxVssVolumeForStream(int streamType)1342 /*package*/ int getMaxVssVolumeForStream(int streamType) { 1343 return mAudioService.getMaxVssVolumeForStream(streamType); 1344 } 1345 getDeviceForStream(int streamType)1346 /*package*/ int getDeviceForStream(int streamType) { 1347 return mAudioService.getDeviceForStream(streamType); 1348 } 1349 postApplyVolumeOnDevice(int streamType, int device, String caller)1350 /*package*/ void postApplyVolumeOnDevice(int streamType, int device, String caller) { 1351 mAudioService.postApplyVolumeOnDevice(streamType, device, caller); 1352 } 1353 postSetVolumeIndexOnDevice(int streamType, int vssVolIndex, int device, String caller)1354 /*package*/ void postSetVolumeIndexOnDevice(int streamType, int vssVolIndex, int device, 1355 String caller) { 1356 mAudioService.postSetVolumeIndexOnDevice(streamType, vssVolIndex, device, caller); 1357 } 1358 postObserveDevicesForAllStreams()1359 /*packages*/ void postObserveDevicesForAllStreams() { 1360 mAudioService.postObserveDevicesForAllStreams(); 1361 } 1362 isInCommunication()1363 /*package*/ boolean isInCommunication() { 1364 return mAudioService.isInCommunication(); 1365 } 1366 hasMediaDynamicPolicy()1367 /*package*/ boolean hasMediaDynamicPolicy() { 1368 return mAudioService.hasMediaDynamicPolicy(); 1369 } 1370 getContentResolver()1371 /*package*/ ContentResolver getContentResolver() { 1372 return mAudioService.getContentResolver(); 1373 } 1374 checkMusicActive(int deviceType, String caller)1375 /*package*/ void checkMusicActive(int deviceType, String caller) { 1376 mAudioService.checkMusicActive(deviceType, caller); 1377 } 1378 checkVolumeCecOnHdmiConnection( @udioService.ConnectionState int state, String caller)1379 /*package*/ void checkVolumeCecOnHdmiConnection( 1380 @AudioService.ConnectionState int state, String caller) { 1381 mAudioService.postCheckVolumeCecOnHdmiConnection(state, caller); 1382 } 1383 hasAudioFocusUsers()1384 /*package*/ boolean hasAudioFocusUsers() { 1385 return mAudioService.hasAudioFocusUsers(); 1386 } 1387 1388 //--------------------------------------------------------------------- 1389 // Message handling on behalf of helper classes. 1390 // Each of these methods posts a message to mBrokerHandler message queue. postBroadcastScoConnectionState(int state)1391 /*package*/ void postBroadcastScoConnectionState(int state) { 1392 sendIMsgNoDelay(MSG_I_BROADCAST_BT_CONNECTION_STATE, SENDMSG_QUEUE, state); 1393 } 1394 postBroadcastBecomingNoisy()1395 /*package*/ void postBroadcastBecomingNoisy() { 1396 sendMsgNoDelay(MSG_BROADCAST_AUDIO_BECOMING_NOISY, SENDMSG_REPLACE); 1397 } 1398 1399 @GuardedBy("mDeviceStateLock") postBluetoothActiveDevice(BtDeviceInfo info, int delay)1400 /*package*/ void postBluetoothActiveDevice(BtDeviceInfo info, int delay) { 1401 sendLMsg(MSG_L_SET_BT_ACTIVE_DEVICE, SENDMSG_QUEUE, info, delay); 1402 } 1403 postSetWiredDeviceConnectionState( AudioDeviceInventory.WiredDeviceConnectionState connectionState, int delay)1404 /*package*/ void postSetWiredDeviceConnectionState( 1405 AudioDeviceInventory.WiredDeviceConnectionState connectionState, int delay) { 1406 sendLMsg(MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE, SENDMSG_QUEUE, connectionState, delay); 1407 } 1408 postBtProfileDisconnected(int profile)1409 /*package*/ void postBtProfileDisconnected(int profile) { 1410 sendIMsgNoDelay(MSG_I_BT_SERVICE_DISCONNECTED_PROFILE, SENDMSG_QUEUE, profile); 1411 } 1412 postBtProfileConnected(int profile, BluetoothProfile proxy)1413 /*package*/ void postBtProfileConnected(int profile, BluetoothProfile proxy) { 1414 sendILMsgNoDelay(MSG_IL_BT_SERVICE_CONNECTED_PROFILE, SENDMSG_QUEUE, profile, proxy); 1415 } 1416 postCommunicationRouteClientDied(CommunicationRouteClient client)1417 /*package*/ void postCommunicationRouteClientDied(CommunicationRouteClient client) { 1418 sendLMsgNoDelay(MSG_L_COMMUNICATION_ROUTE_CLIENT_DIED, SENDMSG_QUEUE, client); 1419 } 1420 postSaveSetPreferredDevicesForStrategy(int strategy, List<AudioDeviceAttributes> devices)1421 /*package*/ void postSaveSetPreferredDevicesForStrategy(int strategy, 1422 List<AudioDeviceAttributes> devices) 1423 { 1424 sendILMsgNoDelay(MSG_IL_SAVE_PREF_DEVICES_FOR_STRATEGY, SENDMSG_QUEUE, strategy, devices); 1425 } 1426 postSaveRemovePreferredDevicesForStrategy(int strategy)1427 /*package*/ void postSaveRemovePreferredDevicesForStrategy(int strategy) { 1428 sendIMsgNoDelay(MSG_I_SAVE_REMOVE_PREF_DEVICES_FOR_STRATEGY, SENDMSG_QUEUE, strategy); 1429 } 1430 postSaveSetDeviceAsNonDefaultForStrategy( int strategy, AudioDeviceAttributes device)1431 /*package*/ void postSaveSetDeviceAsNonDefaultForStrategy( 1432 int strategy, AudioDeviceAttributes device) { 1433 sendILMsgNoDelay(MSG_IL_SAVE_NDEF_DEVICE_FOR_STRATEGY, SENDMSG_QUEUE, strategy, device); 1434 } 1435 postSaveRemoveDeviceAsNonDefaultForStrategy( int strategy, AudioDeviceAttributes device)1436 /*package*/ void postSaveRemoveDeviceAsNonDefaultForStrategy( 1437 int strategy, AudioDeviceAttributes device) { 1438 sendILMsgNoDelay( 1439 MSG_IL_SAVE_REMOVE_NDEF_DEVICE_FOR_STRATEGY, SENDMSG_QUEUE, strategy, device); 1440 } 1441 postSaveSetPreferredDevicesForCapturePreset( int capturePreset, List<AudioDeviceAttributes> devices)1442 /*package*/ void postSaveSetPreferredDevicesForCapturePreset( 1443 int capturePreset, List<AudioDeviceAttributes> devices) { 1444 sendILMsgNoDelay( 1445 MSG_IL_SAVE_PREF_DEVICES_FOR_CAPTURE_PRESET, SENDMSG_QUEUE, capturePreset, devices); 1446 } 1447 postSaveClearPreferredDevicesForCapturePreset(int capturePreset)1448 /*package*/ void postSaveClearPreferredDevicesForCapturePreset(int capturePreset) { 1449 sendIMsgNoDelay( 1450 MSG_I_SAVE_CLEAR_PREF_DEVICES_FOR_CAPTURE_PRESET, SENDMSG_QUEUE, capturePreset); 1451 } 1452 postUpdateCommunicationRouteClient( boolean wasBtScoRequested, String eventSource)1453 /*package*/ void postUpdateCommunicationRouteClient( 1454 boolean wasBtScoRequested, String eventSource) { 1455 sendILMsgNoDelay(MSG_IL_UPDATE_COMMUNICATION_ROUTE_CLIENT, SENDMSG_QUEUE, 1456 wasBtScoRequested ? 1 : 0, eventSource); 1457 } 1458 postSetCommunicationDeviceForClient(CommunicationDeviceInfo info)1459 /*package*/ void postSetCommunicationDeviceForClient(CommunicationDeviceInfo info) { 1460 sendLMsgNoDelay(MSG_L_SET_COMMUNICATION_DEVICE_FOR_CLIENT, SENDMSG_QUEUE, info); 1461 } 1462 postNotifyPreferredAudioProfileApplied(BluetoothDevice btDevice)1463 /*package*/ void postNotifyPreferredAudioProfileApplied(BluetoothDevice btDevice) { 1464 sendLMsgNoDelay(MSG_L_NOTIFY_PREFERRED_AUDIOPROFILE_APPLIED, SENDMSG_QUEUE, btDevice); 1465 } 1466 postReceiveBtEvent(Intent intent)1467 /*package*/ void postReceiveBtEvent(Intent intent) { 1468 sendLMsgNoDelay(MSG_L_RECEIVED_BT_EVENT, SENDMSG_QUEUE, intent); 1469 } 1470 1471 /*package*/ static final class CommunicationDeviceInfo { 1472 final @NonNull IBinder mCb; // Identifies the requesting client for death handler 1473 final int mUid; // Requester UID 1474 final @Nullable AudioDeviceAttributes mDevice; // Device being set or reset. 1475 final boolean mOn; // true if setting, false if resetting 1476 final int mScoAudioMode; // only used for SCO: requested audio mode 1477 final boolean mIsPrivileged; // true if the client app has MODIFY_PHONE_STATE permission 1478 final @NonNull String mEventSource; // caller identifier for logging 1479 boolean mWaitForStatus; // true if the caller waits for a completion status (API dependent) 1480 boolean mStatus = false; // completion status only used if mWaitForStatus is true 1481 CommunicationDeviceInfo(@onNull IBinder cb, int uid, @Nullable AudioDeviceAttributes device, boolean on, int scoAudioMode, @NonNull String eventSource, boolean waitForStatus, boolean isPrivileged)1482 CommunicationDeviceInfo(@NonNull IBinder cb, int uid, 1483 @Nullable AudioDeviceAttributes device, boolean on, int scoAudioMode, 1484 @NonNull String eventSource, boolean waitForStatus, boolean isPrivileged) { 1485 mCb = cb; 1486 mUid = uid; 1487 mDevice = device; 1488 mOn = on; 1489 mScoAudioMode = scoAudioMode; 1490 mIsPrivileged = isPrivileged; 1491 mEventSource = eventSource; 1492 mWaitForStatus = waitForStatus; 1493 } 1494 1495 // redefine equality op so we can match messages intended for this client 1496 @Override equals(Object o)1497 public boolean equals(Object o) { 1498 if (o == null) { 1499 return false; 1500 } 1501 if (this == o) { 1502 return true; 1503 } 1504 if (!(o instanceof CommunicationDeviceInfo)) { 1505 return false; 1506 } 1507 1508 return mCb.equals(((CommunicationDeviceInfo) o).mCb) 1509 && mUid == ((CommunicationDeviceInfo) o).mUid; 1510 } 1511 1512 @Override toString()1513 public String toString() { 1514 return "CommunicationDeviceInfo mCb=" + mCb.toString() 1515 + " mUid=" + mUid 1516 + " mDevice=[" + (mDevice != null ? mDevice.toString() : "null") + "]" 1517 + " mOn=" + mOn 1518 + " mScoAudioMode=" + mScoAudioMode 1519 + " mIsPrivileged=" + mIsPrivileged 1520 + " mEventSource=" + mEventSource 1521 + " mWaitForStatus=" + mWaitForStatus 1522 + " mStatus=" + mStatus; 1523 } 1524 } 1525 1526 //--------------------------------------------------------------------- 1527 // Method forwarding between the helper classes (BtHelper, AudioDeviceInventory) 1528 // only call from a "handle"* method or "on"* method 1529 1530 // Handles request to override default use of A2DP for media. 1531 //@GuardedBy("mConnectedDevices") setBluetoothA2dpOnInt(boolean on, boolean fromA2dp, String source)1532 /*package*/ void setBluetoothA2dpOnInt(boolean on, boolean fromA2dp, String source) { 1533 // for logging only 1534 final String eventSource = new StringBuilder("setBluetoothA2dpOn(").append(on) 1535 .append(") from u/pid:").append(Binder.getCallingUid()).append("/") 1536 .append(Binder.getCallingPid()).append(" src:").append(source).toString(); 1537 1538 synchronized (mDeviceStateLock) { 1539 mBluetoothA2dpEnabled = on; 1540 mBrokerHandler.removeMessages(MSG_IIL_SET_FORCE_BT_A2DP_USE); 1541 onSetForceUse( 1542 AudioSystem.FOR_MEDIA, 1543 mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP, 1544 fromA2dp, 1545 eventSource); 1546 } 1547 } 1548 handleDeviceConnection(@onNull AudioDeviceAttributes attributes, boolean connect, @Nullable BluetoothDevice btDevice)1549 /*package*/ boolean handleDeviceConnection(@NonNull AudioDeviceAttributes attributes, 1550 boolean connect, @Nullable BluetoothDevice btDevice) { 1551 synchronized (mDeviceStateLock) { 1552 return mDeviceInventory.handleDeviceConnection( 1553 attributes, connect, false /*for test*/, btDevice); 1554 } 1555 } 1556 handleFailureToConnectToBtHeadsetService(int delay)1557 /*package*/ void handleFailureToConnectToBtHeadsetService(int delay) { 1558 sendMsg(MSG_BT_HEADSET_CNCT_FAILED, SENDMSG_REPLACE, delay); 1559 } 1560 handleCancelFailureToConnectToBtHeadsetService()1561 /*package*/ void handleCancelFailureToConnectToBtHeadsetService() { 1562 mBrokerHandler.removeMessages(MSG_BT_HEADSET_CNCT_FAILED); 1563 } 1564 postReportNewRoutes(boolean fromA2dp)1565 /*package*/ void postReportNewRoutes(boolean fromA2dp) { 1566 sendMsgNoDelay(fromA2dp ? MSG_REPORT_NEW_ROUTES_A2DP : MSG_REPORT_NEW_ROUTES, SENDMSG_NOOP); 1567 } 1568 1569 // must be called synchronized on mConnectedDevices hasScheduledA2dpConnection(BluetoothDevice btDevice)1570 /*package*/ boolean hasScheduledA2dpConnection(BluetoothDevice btDevice) { 1571 final BtDeviceInfo devInfoToCheck = new BtDeviceInfo(btDevice, BluetoothProfile.A2DP); 1572 return mBrokerHandler.hasEqualMessages(MSG_L_SET_BT_ACTIVE_DEVICE, devInfoToCheck); 1573 } 1574 setA2dpTimeout(String address, int a2dpCodec, int delayMs)1575 /*package*/ void setA2dpTimeout(String address, int a2dpCodec, int delayMs) { 1576 sendILMsg(MSG_IL_BTA2DP_TIMEOUT, SENDMSG_QUEUE, a2dpCodec, address, delayMs); 1577 } 1578 setLeAudioTimeout(String address, int device, int delayMs)1579 /*package*/ void setLeAudioTimeout(String address, int device, int delayMs) { 1580 sendILMsg(MSG_IL_BTLEAUDIO_TIMEOUT, SENDMSG_QUEUE, device, address, delayMs); 1581 } 1582 setAvrcpAbsoluteVolumeSupported(boolean supported)1583 /*package*/ void setAvrcpAbsoluteVolumeSupported(boolean supported) { 1584 synchronized (mDeviceStateLock) { 1585 mBtHelper.setAvrcpAbsoluteVolumeSupported(supported); 1586 } 1587 } 1588 clearAvrcpAbsoluteVolumeSupported()1589 /*package*/ void clearAvrcpAbsoluteVolumeSupported() { 1590 setAvrcpAbsoluteVolumeSupported(false); 1591 mAudioService.setAvrcpAbsoluteVolumeSupported(false); 1592 } 1593 getBluetoothA2dpEnabled()1594 /*package*/ boolean getBluetoothA2dpEnabled() { 1595 synchronized (mDeviceStateLock) { 1596 return mBluetoothA2dpEnabled; 1597 } 1598 } 1599 broadcastStickyIntentToCurrentProfileGroup(Intent intent)1600 /*package*/ void broadcastStickyIntentToCurrentProfileGroup(Intent intent) { 1601 mSystemServer.broadcastStickyIntentToCurrentProfileGroup(intent); 1602 } 1603 dump(PrintWriter pw, String prefix)1604 /*package*/ void dump(PrintWriter pw, String prefix) { 1605 if (mBrokerHandler != null) { 1606 pw.println(prefix + "Message handler (watch for unhandled messages):"); 1607 mBrokerHandler.dump(new PrintWriterPrinter(pw), prefix + " "); 1608 } else { 1609 pw.println("Message handler is null"); 1610 } 1611 1612 mDeviceInventory.dump(pw, prefix); 1613 1614 pw.println("\n" + prefix + "Communication route clients:"); 1615 mCommunicationRouteClients.forEach((cl) -> { 1616 pw.println(" " + prefix + cl.toString()); }); 1617 1618 pw.println("\n" + prefix + "Computed Preferred communication device: " 1619 + preferredCommunicationDevice()); 1620 pw.println("\n" + prefix + "Applied Preferred communication device: " 1621 + mPreferredCommunicationDevice); 1622 pw.println(prefix + "Active communication device: " 1623 + ((mActiveCommunicationDevice == null) ? "None" 1624 : new AudioDeviceAttributes(mActiveCommunicationDevice))); 1625 1626 pw.println(prefix + "mCommunicationStrategyId: " 1627 + mCommunicationStrategyId); 1628 1629 pw.println(prefix + "mAccessibilityStrategyId: " 1630 + mAccessibilityStrategyId); 1631 1632 pw.println("\n" + prefix + "mAudioModeOwner: " + mAudioModeOwner); 1633 1634 mBtHelper.dump(pw, prefix); 1635 } 1636 1637 //--------------------------------------------------------------------- 1638 // Internal handling of messages 1639 // These methods are ALL synchronous, in response to message handling in BrokerHandler 1640 // Blocking in any of those will block the message queue 1641 onSetForceUse(int useCase, int config, boolean fromA2dp, String eventSource)1642 private void onSetForceUse(int useCase, int config, boolean fromA2dp, String eventSource) { 1643 if (useCase == AudioSystem.FOR_MEDIA) { 1644 postReportNewRoutes(fromA2dp); 1645 } 1646 AudioService.sForceUseLogger.enqueue( 1647 new AudioServiceEvents.ForceUseEvent(useCase, config, eventSource)); 1648 new MediaMetrics.Item(MediaMetrics.Name.AUDIO_FORCE_USE + MediaMetrics.SEPARATOR 1649 + AudioSystem.forceUseUsageToString(useCase)) 1650 .set(MediaMetrics.Property.EVENT, "onSetForceUse") 1651 .set(MediaMetrics.Property.FORCE_USE_DUE_TO, eventSource) 1652 .set(MediaMetrics.Property.FORCE_USE_MODE, 1653 AudioSystem.forceUseConfigToString(config)) 1654 .record(); 1655 1656 if (AudioService.DEBUG_COMM_RTE) { 1657 Log.v(TAG, "onSetForceUse(useCase<" + useCase + ">, config<" + config + ">, fromA2dp<" 1658 + fromA2dp + ">, eventSource<" + eventSource + ">)"); 1659 } 1660 mAudioSystem.setForceUse(useCase, config); 1661 } 1662 onSendBecomingNoisyIntent()1663 private void onSendBecomingNoisyIntent() { 1664 AudioService.sDeviceLogger.enqueue((new EventLogger.StringEvent( 1665 "broadcast ACTION_AUDIO_BECOMING_NOISY")).printLog(TAG)); 1666 mSystemServer.sendDeviceBecomingNoisyIntent(); 1667 } 1668 1669 //--------------------------------------------------------------------- 1670 // Message handling 1671 private BrokerHandler mBrokerHandler; 1672 private BrokerThread mBrokerThread; 1673 private PowerManager.WakeLock mBrokerEventWakeLock; 1674 setupMessaging(Context ctxt)1675 private void setupMessaging(Context ctxt) { 1676 final PowerManager pm = (PowerManager) ctxt.getSystemService(Context.POWER_SERVICE); 1677 mBrokerEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 1678 "handleAudioDeviceEvent"); 1679 mBrokerThread = new BrokerThread(); 1680 mBrokerThread.start(); 1681 waitForBrokerHandlerCreation(); 1682 } 1683 waitForBrokerHandlerCreation()1684 private void waitForBrokerHandlerCreation() { 1685 synchronized (this) { 1686 while (mBrokerHandler == null) { 1687 try { 1688 wait(); 1689 } catch (InterruptedException e) { 1690 Log.e(TAG, "Interruption while waiting on BrokerHandler"); 1691 } 1692 } 1693 } 1694 } 1695 1696 /** Class that handles the device broker's message queue */ 1697 private class BrokerThread extends Thread { BrokerThread()1698 BrokerThread() { 1699 super("AudioDeviceBroker"); 1700 } 1701 1702 @Override run()1703 public void run() { 1704 // Set this thread up so the handler will work on it 1705 Looper.prepare(); 1706 1707 synchronized (AudioDeviceBroker.this) { 1708 mBrokerHandler = new BrokerHandler(); 1709 1710 // Notify that the handler has been created 1711 AudioDeviceBroker.this.notify(); 1712 } 1713 1714 Looper.loop(); 1715 } 1716 } 1717 1718 /** Class that handles the message queue */ 1719 private class BrokerHandler extends Handler { 1720 1721 @Override handleMessage(Message msg)1722 public void handleMessage(Message msg) { 1723 switch (msg.what) { 1724 case MSG_RESTORE_DEVICES: 1725 synchronized (mSetModeLock) { 1726 synchronized (mDeviceStateLock) { 1727 initRoutingStrategyIds(); 1728 updateActiveCommunicationDevice(); 1729 mDeviceInventory.onRestoreDevices(); 1730 mBtHelper.onAudioServerDiedRestoreA2dp(); 1731 updateCommunicationRoute("MSG_RESTORE_DEVICES"); 1732 } 1733 } 1734 break; 1735 case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE: 1736 synchronized (mDeviceStateLock) { 1737 mDeviceInventory.onSetWiredDeviceConnectionState( 1738 (AudioDeviceInventory.WiredDeviceConnectionState) msg.obj); 1739 } 1740 break; 1741 case MSG_I_BROADCAST_BT_CONNECTION_STATE: 1742 synchronized (mDeviceStateLock) { 1743 mBtHelper.onBroadcastScoConnectionState(msg.arg1); 1744 } 1745 break; 1746 case MSG_IIL_SET_FORCE_USE: // intended fall-through 1747 case MSG_IIL_SET_FORCE_BT_A2DP_USE: 1748 onSetForceUse(msg.arg1, msg.arg2, 1749 (msg.what == MSG_IIL_SET_FORCE_BT_A2DP_USE), (String) msg.obj); 1750 break; 1751 case MSG_REPORT_NEW_ROUTES: 1752 case MSG_REPORT_NEW_ROUTES_A2DP: 1753 synchronized (mDeviceStateLock) { 1754 mDeviceInventory.onReportNewRoutes(); 1755 } 1756 break; 1757 case MSG_L_SET_BT_ACTIVE_DEVICE: 1758 synchronized (mSetModeLock) { 1759 synchronized (mDeviceStateLock) { 1760 final BtDeviceInfo btInfo = (BtDeviceInfo) msg.obj; 1761 @AudioSystem.AudioFormatNativeEnumForBtCodec final int codec = 1762 mBtHelper.getA2dpCodecWithFallbackToSBC( 1763 btInfo.mDevice, "MSG_L_SET_BT_ACTIVE_DEVICE"); 1764 mDeviceInventory.onSetBtActiveDevice(btInfo, codec, 1765 (btInfo.mProfile 1766 != BluetoothProfile.LE_AUDIO || btInfo.mIsLeOutput) 1767 ? mAudioService.getBluetoothContextualVolumeStream() 1768 : AudioSystem.STREAM_DEFAULT); 1769 if (btInfo.mProfile == BluetoothProfile.LE_AUDIO 1770 || btInfo.mProfile == BluetoothProfile.HEARING_AID) { 1771 onUpdateCommunicationRouteClient(isBluetoothScoRequested(), 1772 "setBluetoothActiveDevice"); 1773 } 1774 } 1775 } 1776 break; 1777 case MSG_BT_HEADSET_CNCT_FAILED: 1778 synchronized (mSetModeLock) { 1779 synchronized (mDeviceStateLock) { 1780 mBtHelper.resetBluetoothSco(); 1781 } 1782 } 1783 break; 1784 case MSG_IL_BTA2DP_TIMEOUT: 1785 // msg.obj == address of BTA2DP device 1786 synchronized (mDeviceStateLock) { 1787 mDeviceInventory.onMakeA2dpDeviceUnavailableNow((String) msg.obj, msg.arg1); 1788 } 1789 break; 1790 case MSG_IL_BTLEAUDIO_TIMEOUT: 1791 // msg.obj == address of LE Audio device 1792 synchronized (mDeviceStateLock) { 1793 mDeviceInventory.onMakeLeAudioDeviceUnavailableNow( 1794 (String) msg.obj, msg.arg1); 1795 } 1796 break; 1797 case MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE: { 1798 final BtDeviceInfo btInfo = (BtDeviceInfo) msg.obj; 1799 synchronized (mDeviceStateLock) { 1800 @AudioSystem.AudioFormatNativeEnumForBtCodec final int codec = 1801 mBtHelper.getA2dpCodecWithFallbackToSBC( 1802 btInfo.mDevice, "MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE"); 1803 mDeviceInventory.onBluetoothDeviceConfigChange( 1804 btInfo, codec, BtHelper.EVENT_DEVICE_CONFIG_CHANGE); 1805 } 1806 } break; 1807 case MSG_BROADCAST_AUDIO_BECOMING_NOISY: 1808 onSendBecomingNoisyIntent(); 1809 break; 1810 case MSG_II_SET_HEARING_AID_VOLUME: 1811 synchronized (mDeviceStateLock) { 1812 mBtHelper.setHearingAidVolume(msg.arg1, msg.arg2, 1813 mDeviceInventory.isHearingAidConnected()); 1814 } 1815 break; 1816 case MSG_II_SET_LE_AUDIO_OUT_VOLUME: { 1817 final BleVolumeInfo info = (BleVolumeInfo) msg.obj; 1818 synchronized (mDeviceStateLock) { 1819 mBtHelper.setLeAudioVolume(info.mIndex, info.mMaxIndex, info.mStreamType); 1820 } 1821 } break; 1822 case MSG_I_SET_AVRCP_ABSOLUTE_VOLUME: 1823 synchronized (mDeviceStateLock) { 1824 mBtHelper.setAvrcpAbsoluteVolumeIndex(msg.arg1); 1825 } 1826 break; 1827 case MSG_I_SET_MODE_OWNER: 1828 synchronized (mSetModeLock) { 1829 synchronized (mDeviceStateLock) { 1830 boolean wasBtScoRequested = isBluetoothScoRequested(); 1831 mAudioModeOwner = (AudioModeInfo) msg.obj; 1832 if (mAudioModeOwner.mMode != AudioSystem.MODE_RINGTONE) { 1833 onUpdateCommunicationRouteClient( 1834 wasBtScoRequested, "setNewModeOwner"); 1835 } 1836 } 1837 } 1838 break; 1839 1840 case MSG_L_SET_COMMUNICATION_DEVICE_FOR_CLIENT: 1841 CommunicationDeviceInfo deviceInfo = (CommunicationDeviceInfo) msg.obj; 1842 boolean status; 1843 synchronized (mSetModeLock) { 1844 synchronized (mDeviceStateLock) { 1845 status = onSetCommunicationDeviceForClient(deviceInfo); 1846 } 1847 } 1848 synchronized (deviceInfo) { 1849 if (deviceInfo.mWaitForStatus) { 1850 deviceInfo.mStatus = status; 1851 deviceInfo.mWaitForStatus = false; 1852 deviceInfo.notify(); 1853 } 1854 } 1855 break; 1856 1857 case MSG_IL_UPDATE_COMMUNICATION_ROUTE_CLIENT: 1858 synchronized (mSetModeLock) { 1859 synchronized (mDeviceStateLock) { 1860 onUpdateCommunicationRouteClient(msg.arg1 == 1, (String) msg.obj); 1861 } 1862 } 1863 break; 1864 1865 case MSG_L_COMMUNICATION_ROUTE_CLIENT_DIED: 1866 synchronized (mSetModeLock) { 1867 synchronized (mDeviceStateLock) { 1868 onCommunicationRouteClientDied((CommunicationRouteClient) msg.obj); 1869 } 1870 } 1871 break; 1872 1873 case MSG_L_RECEIVED_BT_EVENT: 1874 synchronized (mSetModeLock) { 1875 synchronized (mDeviceStateLock) { 1876 onReceiveBtEvent((Intent) msg.obj); 1877 } 1878 } 1879 break; 1880 1881 case MSG_TOGGLE_HDMI: 1882 synchronized (mDeviceStateLock) { 1883 mDeviceInventory.onToggleHdmi(); 1884 } 1885 break; 1886 case MSG_I_BT_SERVICE_DISCONNECTED_PROFILE: 1887 synchronized (mSetModeLock) { 1888 synchronized (mDeviceStateLock) { 1889 mBtHelper.onBtProfileDisconnected(msg.arg1); 1890 mDeviceInventory.onBtProfileDisconnected(msg.arg1); 1891 } 1892 } 1893 break; 1894 case MSG_IL_BT_SERVICE_CONNECTED_PROFILE: 1895 synchronized (mSetModeLock) { 1896 synchronized (mDeviceStateLock) { 1897 mBtHelper.onBtProfileConnected(msg.arg1, (BluetoothProfile) msg.obj); 1898 } 1899 } 1900 break; 1901 case MSG_L_BT_ACTIVE_DEVICE_CHANGE_EXT: { 1902 final BtDeviceInfo btInfo = (BtDeviceInfo) msg.obj; 1903 if (btInfo.mDevice == null) break; 1904 AudioService.sDeviceLogger.enqueue((new EventLogger.StringEvent( 1905 "msg: onBluetoothActiveDeviceChange " + btInfo)).printLog(TAG)); 1906 synchronized (mDeviceStateLock) { 1907 mDeviceInventory.setBluetoothActiveDevice(btInfo); 1908 } 1909 } break; 1910 case MSG_IL_SAVE_PREF_DEVICES_FOR_STRATEGY: { 1911 final int strategy = msg.arg1; 1912 final List<AudioDeviceAttributes> devices = 1913 (List<AudioDeviceAttributes>) msg.obj; 1914 mDeviceInventory.onSaveSetPreferredDevices(strategy, devices); 1915 } break; 1916 case MSG_I_SAVE_REMOVE_PREF_DEVICES_FOR_STRATEGY: { 1917 final int strategy = msg.arg1; 1918 mDeviceInventory.onSaveRemovePreferredDevices(strategy); 1919 } break; 1920 case MSG_IL_SAVE_NDEF_DEVICE_FOR_STRATEGY: { 1921 final int strategy = msg.arg1; 1922 final AudioDeviceAttributes device = (AudioDeviceAttributes) msg.obj; 1923 mDeviceInventory.onSaveSetDeviceAsNonDefault(strategy, device); 1924 } break; 1925 case MSG_IL_SAVE_REMOVE_NDEF_DEVICE_FOR_STRATEGY: { 1926 final int strategy = msg.arg1; 1927 final AudioDeviceAttributes device = (AudioDeviceAttributes) msg.obj; 1928 mDeviceInventory.onSaveRemoveDeviceAsNonDefault(strategy, device); 1929 } break; 1930 case MSG_CHECK_MUTE_MUSIC: 1931 checkMessagesMuteMusic(0); 1932 break; 1933 case MSG_IL_SAVE_PREF_DEVICES_FOR_CAPTURE_PRESET: { 1934 final int capturePreset = msg.arg1; 1935 final List<AudioDeviceAttributes> devices = 1936 (List<AudioDeviceAttributes>) msg.obj; 1937 mDeviceInventory.onSaveSetPreferredDevicesForCapturePreset( 1938 capturePreset, devices); 1939 } break; 1940 case MSG_I_SAVE_CLEAR_PREF_DEVICES_FOR_CAPTURE_PRESET: { 1941 final int capturePreset = msg.arg1; 1942 mDeviceInventory.onSaveClearPreferredDevicesForCapturePreset(capturePreset); 1943 } break; 1944 case MSG_L_NOTIFY_PREFERRED_AUDIOPROFILE_APPLIED: { 1945 final BluetoothDevice btDevice = (BluetoothDevice) msg.obj; 1946 BtHelper.onNotifyPreferredAudioProfileApplied(btDevice); 1947 } break; 1948 1949 case MSG_L_CHECK_COMMUNICATION_DEVICE_REMOVAL: { 1950 synchronized (mSetModeLock) { 1951 synchronized (mDeviceStateLock) { 1952 onCheckCommunicationDeviceRemoval((AudioDeviceAttributes) msg.obj); 1953 } 1954 } 1955 } break; 1956 1957 case MSG_PERSIST_AUDIO_DEVICE_SETTINGS: 1958 onPersistAudioDeviceSettings(); 1959 break; 1960 1961 case MSG_CHECK_COMMUNICATION_ROUTE_CLIENT_STATE: { 1962 synchronized (mDeviceStateLock) { 1963 onCheckCommunicationRouteClientState(msg.arg1, msg.arg2 == 1); 1964 } 1965 } break; 1966 default: 1967 Log.wtf(TAG, "Invalid message " + msg.what); 1968 } 1969 1970 // Give some time to Bluetooth service to post a connection message 1971 // in case of active device switch 1972 if (MESSAGES_MUTE_MUSIC.contains(msg.what)) { 1973 sendMsg(MSG_CHECK_MUTE_MUSIC, SENDMSG_REPLACE, BTA2DP_MUTE_CHECK_DELAY_MS); 1974 } 1975 1976 if (isMessageHandledUnderWakelock(msg.what)) { 1977 try { 1978 mBrokerEventWakeLock.release(); 1979 } catch (Exception e) { 1980 Log.e(TAG, "Exception releasing wakelock", e); 1981 } 1982 } 1983 } 1984 } 1985 1986 // List of all messages. If a message has be handled under wakelock, add it to 1987 // the isMessageHandledUnderWakelock(int) method 1988 // Naming of msg indicates arguments, using JNI argument grammar 1989 // (e.g. II indicates two int args, IL indicates int and Obj arg) 1990 private static final int MSG_RESTORE_DEVICES = 1; 1991 private static final int MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE = 2; 1992 private static final int MSG_I_BROADCAST_BT_CONNECTION_STATE = 3; 1993 private static final int MSG_IIL_SET_FORCE_USE = 4; 1994 private static final int MSG_IIL_SET_FORCE_BT_A2DP_USE = 5; 1995 private static final int MSG_TOGGLE_HDMI = 6; 1996 private static final int MSG_L_SET_BT_ACTIVE_DEVICE = 7; 1997 private static final int MSG_BT_HEADSET_CNCT_FAILED = 9; 1998 private static final int MSG_IL_BTA2DP_TIMEOUT = 10; 1999 2000 // process change of A2DP device configuration, obj is BluetoothDevice 2001 private static final int MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE = 11; 2002 2003 private static final int MSG_BROADCAST_AUDIO_BECOMING_NOISY = 12; 2004 private static final int MSG_REPORT_NEW_ROUTES = 13; 2005 private static final int MSG_II_SET_HEARING_AID_VOLUME = 14; 2006 private static final int MSG_I_SET_AVRCP_ABSOLUTE_VOLUME = 15; 2007 private static final int MSG_I_SET_MODE_OWNER = 16; 2008 2009 private static final int MSG_I_BT_SERVICE_DISCONNECTED_PROFILE = 22; 2010 private static final int MSG_IL_BT_SERVICE_CONNECTED_PROFILE = 23; 2011 2012 // process external command to (dis)connect an A2DP device, obj is BtDeviceConnectionInfo 2013 private static final int MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT = 29; 2014 2015 // process external command to (dis)connect a hearing aid device 2016 private static final int MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT = 31; 2017 2018 private static final int MSG_IL_SAVE_PREF_DEVICES_FOR_STRATEGY = 32; 2019 private static final int MSG_I_SAVE_REMOVE_PREF_DEVICES_FOR_STRATEGY = 33; 2020 2021 private static final int MSG_L_COMMUNICATION_ROUTE_CLIENT_DIED = 34; 2022 private static final int MSG_CHECK_MUTE_MUSIC = 35; 2023 private static final int MSG_REPORT_NEW_ROUTES_A2DP = 36; 2024 2025 private static final int MSG_IL_SAVE_PREF_DEVICES_FOR_CAPTURE_PRESET = 37; 2026 private static final int MSG_I_SAVE_CLEAR_PREF_DEVICES_FOR_CAPTURE_PRESET = 38; 2027 2028 private static final int MSG_L_SET_COMMUNICATION_DEVICE_FOR_CLIENT = 42; 2029 private static final int MSG_IL_UPDATE_COMMUNICATION_ROUTE_CLIENT = 43; 2030 2031 private static final int MSG_L_BT_ACTIVE_DEVICE_CHANGE_EXT = 45; 2032 // 2033 // process set volume for Le Audio, obj is BleVolumeInfo 2034 private static final int MSG_II_SET_LE_AUDIO_OUT_VOLUME = 46; 2035 2036 private static final int MSG_IL_SAVE_NDEF_DEVICE_FOR_STRATEGY = 47; 2037 private static final int MSG_IL_SAVE_REMOVE_NDEF_DEVICE_FOR_STRATEGY = 48; 2038 private static final int MSG_IL_BTLEAUDIO_TIMEOUT = 49; 2039 2040 private static final int MSG_L_NOTIFY_PREFERRED_AUDIOPROFILE_APPLIED = 52; 2041 private static final int MSG_L_CHECK_COMMUNICATION_DEVICE_REMOVAL = 53; 2042 2043 private static final int MSG_PERSIST_AUDIO_DEVICE_SETTINGS = 54; 2044 2045 private static final int MSG_L_RECEIVED_BT_EVENT = 55; 2046 2047 private static final int MSG_CHECK_COMMUNICATION_ROUTE_CLIENT_STATE = 56; 2048 isMessageHandledUnderWakelock(int msgId)2049 private static boolean isMessageHandledUnderWakelock(int msgId) { 2050 switch(msgId) { 2051 case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE: 2052 case MSG_L_SET_BT_ACTIVE_DEVICE: 2053 case MSG_IL_BTA2DP_TIMEOUT: 2054 case MSG_IL_BTLEAUDIO_TIMEOUT: 2055 case MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE: 2056 case MSG_TOGGLE_HDMI: 2057 case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT: 2058 case MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT: 2059 case MSG_CHECK_MUTE_MUSIC: 2060 return true; 2061 default: 2062 return false; 2063 } 2064 } 2065 2066 // Message helper methods 2067 2068 // sendMsg() flags 2069 /** If the msg is already queued, replace it with this one. */ 2070 private static final int SENDMSG_REPLACE = 0; 2071 /** If the msg is already queued, ignore this one and leave the old. */ 2072 private static final int SENDMSG_NOOP = 1; 2073 /** If the msg is already queued, queue this one and leave the old. */ 2074 private static final int SENDMSG_QUEUE = 2; 2075 sendMsg(int msg, int existingMsgPolicy, int delay)2076 private void sendMsg(int msg, int existingMsgPolicy, int delay) { 2077 sendIILMsg(msg, existingMsgPolicy, 0, 0, null, delay); 2078 } 2079 sendILMsg(int msg, int existingMsgPolicy, int arg, Object obj, int delay)2080 private void sendILMsg(int msg, int existingMsgPolicy, int arg, Object obj, int delay) { 2081 sendIILMsg(msg, existingMsgPolicy, arg, 0, obj, delay); 2082 } 2083 sendLMsg(int msg, int existingMsgPolicy, Object obj, int delay)2084 private void sendLMsg(int msg, int existingMsgPolicy, Object obj, int delay) { 2085 sendIILMsg(msg, existingMsgPolicy, 0, 0, obj, delay); 2086 } 2087 sendIMsg(int msg, int existingMsgPolicy, int arg, int delay)2088 private void sendIMsg(int msg, int existingMsgPolicy, int arg, int delay) { 2089 sendIILMsg(msg, existingMsgPolicy, arg, 0, null, delay); 2090 } 2091 sendMsgNoDelay(int msg, int existingMsgPolicy)2092 private void sendMsgNoDelay(int msg, int existingMsgPolicy) { 2093 sendIILMsg(msg, existingMsgPolicy, 0, 0, null, 0); 2094 } 2095 sendIMsgNoDelay(int msg, int existingMsgPolicy, int arg)2096 private void sendIMsgNoDelay(int msg, int existingMsgPolicy, int arg) { 2097 sendIILMsg(msg, existingMsgPolicy, arg, 0, null, 0); 2098 } 2099 sendIIMsgNoDelay(int msg, int existingMsgPolicy, int arg1, int arg2)2100 private void sendIIMsgNoDelay(int msg, int existingMsgPolicy, int arg1, int arg2) { 2101 sendIILMsg(msg, existingMsgPolicy, arg1, arg2, null, 0); 2102 } 2103 sendILMsgNoDelay(int msg, int existingMsgPolicy, int arg, Object obj)2104 private void sendILMsgNoDelay(int msg, int existingMsgPolicy, int arg, Object obj) { 2105 sendIILMsg(msg, existingMsgPolicy, arg, 0, obj, 0); 2106 } 2107 sendLMsgNoDelay(int msg, int existingMsgPolicy, Object obj)2108 private void sendLMsgNoDelay(int msg, int existingMsgPolicy, Object obj) { 2109 sendIILMsg(msg, existingMsgPolicy, 0, 0, obj, 0); 2110 } 2111 sendIILMsgNoDelay(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj)2112 private void sendIILMsgNoDelay(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj) { 2113 sendIILMsg(msg, existingMsgPolicy, arg1, arg2, obj, 0); 2114 } 2115 sendIILMsg(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj, int delay)2116 private void sendIILMsg(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj, 2117 int delay) { 2118 if (existingMsgPolicy == SENDMSG_REPLACE) { 2119 mBrokerHandler.removeMessages(msg); 2120 } else if (existingMsgPolicy == SENDMSG_NOOP && mBrokerHandler.hasMessages(msg)) { 2121 return; 2122 } 2123 2124 if (isMessageHandledUnderWakelock(msg)) { 2125 final long identity = Binder.clearCallingIdentity(); 2126 try { 2127 mBrokerEventWakeLock.acquire(BROKER_WAKELOCK_TIMEOUT_MS); 2128 } catch (Exception e) { 2129 Log.e(TAG, "Exception acquiring wakelock", e); 2130 } finally { 2131 Binder.restoreCallingIdentity(identity); 2132 } 2133 } 2134 2135 if (MESSAGES_MUTE_MUSIC.contains(msg)) { 2136 checkMessagesMuteMusic(msg); 2137 } 2138 2139 synchronized (sLastDeviceConnectionMsgTimeLock) { 2140 long time = SystemClock.uptimeMillis() + delay; 2141 2142 switch (msg) { 2143 case MSG_L_SET_BT_ACTIVE_DEVICE: 2144 case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE: 2145 case MSG_IL_BTA2DP_TIMEOUT: 2146 case MSG_IL_BTLEAUDIO_TIMEOUT: 2147 case MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE: 2148 if (sLastDeviceConnectMsgTime >= time) { 2149 // add a little delay to make sure messages are ordered as expected 2150 time = sLastDeviceConnectMsgTime + 30; 2151 } 2152 sLastDeviceConnectMsgTime = time; 2153 break; 2154 default: 2155 break; 2156 } 2157 mBrokerHandler.sendMessageAtTime(mBrokerHandler.obtainMessage(msg, arg1, arg2, obj), 2158 time); 2159 } 2160 } 2161 removeMsgForCheckClientState(int uid)2162 private void removeMsgForCheckClientState(int uid) { 2163 CommunicationRouteClient crc = getCommunicationRouteClientForUid(uid); 2164 if (crc != null) { 2165 mBrokerHandler.removeEqualMessages(MSG_CHECK_COMMUNICATION_ROUTE_CLIENT_STATE, crc); 2166 } 2167 } 2168 sendMsgForCheckClientState(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj, int delay)2169 private void sendMsgForCheckClientState(int msg, int existingMsgPolicy, 2170 int arg1, int arg2, Object obj, int delay) { 2171 if ((existingMsgPolicy == SENDMSG_REPLACE) && (obj != null)) { 2172 mBrokerHandler.removeEqualMessages(msg, obj); 2173 } 2174 2175 long time = SystemClock.uptimeMillis() + delay; 2176 mBrokerHandler.sendMessageAtTime(mBrokerHandler.obtainMessage(msg, arg1, arg2, obj), time); 2177 } 2178 2179 /** List of messages for which music is muted while processing is pending */ 2180 private static final Set<Integer> MESSAGES_MUTE_MUSIC; 2181 static { 2182 MESSAGES_MUTE_MUSIC = new HashSet<>(); 2183 MESSAGES_MUTE_MUSIC.add(MSG_L_SET_BT_ACTIVE_DEVICE); 2184 MESSAGES_MUTE_MUSIC.add(MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE); 2185 MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT); 2186 MESSAGES_MUTE_MUSIC.add(MSG_IIL_SET_FORCE_BT_A2DP_USE); 2187 } 2188 2189 private AtomicBoolean mMusicMuted = new AtomicBoolean(false); 2190 hasIntersection(Set<T> a, Set<T> b)2191 private static <T> boolean hasIntersection(Set<T> a, Set<T> b) { 2192 for (T e : a) { 2193 if (b.contains(e)) return true; 2194 } 2195 return false; 2196 } 2197 messageMutesMusic(int message)2198 boolean messageMutesMusic(int message) { 2199 if (message == 0) { 2200 return false; 2201 } 2202 // Do not mute on bluetooth event if music is playing on a wired headset. 2203 if ((message == MSG_L_SET_BT_ACTIVE_DEVICE 2204 || message == MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT 2205 || message == MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE) 2206 && AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0) 2207 && hasIntersection(mDeviceInventory.DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET, 2208 mAudioService.getDeviceSetForStream(AudioSystem.STREAM_MUSIC))) { 2209 return false; 2210 } 2211 return true; 2212 } 2213 2214 /** Mutes or unmutes music according to pending A2DP messages */ checkMessagesMuteMusic(int message)2215 private void checkMessagesMuteMusic(int message) { 2216 boolean mute = messageMutesMusic(message); 2217 if (!mute) { 2218 for (int msg : MESSAGES_MUTE_MUSIC) { 2219 if (mBrokerHandler.hasMessages(msg)) { 2220 if (messageMutesMusic(msg)) { 2221 mute = true; 2222 break; 2223 } 2224 } 2225 } 2226 } 2227 2228 if (mute != mMusicMuted.getAndSet(mute)) { 2229 mAudioService.setMusicMute(mute); 2230 } 2231 } 2232 2233 // List of applications requesting a specific route for communication. 2234 @GuardedBy("mDeviceStateLock") 2235 private final @NonNull LinkedList<CommunicationRouteClient> mCommunicationRouteClients = 2236 new LinkedList<CommunicationRouteClient>(); 2237 2238 private class CommunicationRouteClient implements IBinder.DeathRecipient { 2239 private final IBinder mCb; 2240 private final int mUid; 2241 private final boolean mIsPrivileged; 2242 private AudioDeviceAttributes mDevice; 2243 private boolean mPlaybackActive; 2244 private boolean mRecordingActive; 2245 CommunicationRouteClient(IBinder cb, int uid, AudioDeviceAttributes device, boolean isPrivileged)2246 CommunicationRouteClient(IBinder cb, int uid, AudioDeviceAttributes device, 2247 boolean isPrivileged) { 2248 mCb = cb; 2249 mUid = uid; 2250 mDevice = device; 2251 mIsPrivileged = isPrivileged; 2252 mPlaybackActive = mAudioService.isPlaybackActiveForUid(uid); 2253 mRecordingActive = mAudioService.isRecordingActiveForUid(uid); 2254 } 2255 registerDeathRecipient()2256 public boolean registerDeathRecipient() { 2257 boolean status = false; 2258 try { 2259 mCb.linkToDeath(this, 0); 2260 status = true; 2261 } catch (RemoteException e) { 2262 Log.w(TAG, "CommunicationRouteClient could not link to " + mCb + " binder death"); 2263 } 2264 return status; 2265 } 2266 unregisterDeathRecipient()2267 public void unregisterDeathRecipient() { 2268 try { 2269 mCb.unlinkToDeath(this, 0); 2270 } catch (NoSuchElementException e) { 2271 Log.w(TAG, "CommunicationRouteClient could not not unregistered to binder"); 2272 } 2273 } 2274 2275 @Override binderDied()2276 public void binderDied() { 2277 postCommunicationRouteClientDied(this); 2278 } 2279 getBinder()2280 IBinder getBinder() { 2281 return mCb; 2282 } 2283 getUid()2284 int getUid() { 2285 return mUid; 2286 } 2287 isPrivileged()2288 boolean isPrivileged() { 2289 return mIsPrivileged; 2290 } 2291 getDevice()2292 AudioDeviceAttributes getDevice() { 2293 return mDevice; 2294 } 2295 setPlaybackActive(boolean active)2296 public void setPlaybackActive(boolean active) { 2297 mPlaybackActive = active; 2298 } 2299 setRecordingActive(boolean active)2300 public void setRecordingActive(boolean active) { 2301 mRecordingActive = active; 2302 } 2303 isActive()2304 public boolean isActive() { 2305 return mIsPrivileged || mRecordingActive || mPlaybackActive; 2306 } 2307 2308 @Override toString()2309 public String toString() { 2310 return "[CommunicationRouteClient: mUid: " + mUid 2311 + " mDevice: " + mDevice.toString() 2312 + " mIsPrivileged: " + mIsPrivileged 2313 + " mPlaybackActive: " + mPlaybackActive 2314 + " mRecordingActive: " + mRecordingActive + "]"; 2315 } 2316 } 2317 2318 // @GuardedBy("mSetModeLock") 2319 @GuardedBy("mDeviceStateLock") onCommunicationRouteClientDied(CommunicationRouteClient client)2320 private void onCommunicationRouteClientDied(CommunicationRouteClient client) { 2321 if (client == null) { 2322 return; 2323 } 2324 Log.w(TAG, "Communication client died"); 2325 setCommunicationRouteForClient(client.getBinder(), client.getUid(), null, 2326 BtHelper.SCO_MODE_UNDEFINED, client.isPrivileged(), 2327 "onCommunicationRouteClientDied"); 2328 } 2329 2330 /** 2331 * Determines which preferred device for phone strategy should be sent to audio policy manager 2332 * as a function of current SCO audio activation state and active communication route requests. 2333 * SCO audio state has the highest priority as it can result from external activation by 2334 * telephony service. 2335 * @return selected forced usage for communication. 2336 */ 2337 @GuardedBy("mDeviceStateLock") preferredCommunicationDevice()2338 @Nullable private AudioDeviceAttributes preferredCommunicationDevice() { 2339 boolean btSCoOn = mBtHelper.isBluetoothScoOn(); 2340 synchronized (mBluetoothAudioStateLock) { 2341 btSCoOn = btSCoOn && mBluetoothScoOn; 2342 } 2343 2344 if (btSCoOn) { 2345 // Use the SCO device known to BtHelper so that it matches exactly 2346 // what has been communicated to audio policy manager. The device 2347 // returned by requestedCommunicationDevice() can be a dummy SCO device if legacy 2348 // APIs are used to start SCO audio. 2349 AudioDeviceAttributes device = mBtHelper.getHeadsetAudioDevice(); 2350 if (device != null) { 2351 return device; 2352 } 2353 } 2354 AudioDeviceAttributes device = requestedCommunicationDevice(); 2355 if (device == null || device.getType() == AudioDeviceInfo.TYPE_BLUETOOTH_SCO) { 2356 // Do not indicate BT SCO selection if SCO is requested but SCO is not ON 2357 return null; 2358 } 2359 return device; 2360 } 2361 2362 /** 2363 * Configures audio policy manager and audio HAL according to active communication route. 2364 * Always called from message Handler. 2365 */ 2366 // @GuardedBy("mSetModeLock") 2367 @GuardedBy("mDeviceStateLock") updateCommunicationRoute(String eventSource)2368 private void updateCommunicationRoute(String eventSource) { 2369 AudioDeviceAttributes preferredCommunicationDevice = preferredCommunicationDevice(); 2370 if (AudioService.DEBUG_COMM_RTE) { 2371 Log.v(TAG, "updateCommunicationRoute, preferredCommunicationDevice: " 2372 + preferredCommunicationDevice + " eventSource: " + eventSource); 2373 } 2374 AudioService.sDeviceLogger.enqueue((new EventLogger.StringEvent( 2375 "updateCommunicationRoute, preferredCommunicationDevice: " 2376 + preferredCommunicationDevice + " eventSource: " + eventSource))); 2377 2378 if (preferredCommunicationDevice == null) { 2379 AudioDeviceAttributes defaultDevice = getDefaultCommunicationDevice(); 2380 if (defaultDevice != null) { 2381 mDeviceInventory.setPreferredDevicesForStrategyInt( 2382 mCommunicationStrategyId, Arrays.asList(defaultDevice)); 2383 mDeviceInventory.setPreferredDevicesForStrategyInt( 2384 mAccessibilityStrategyId, Arrays.asList(defaultDevice)); 2385 } else { 2386 mDeviceInventory.removePreferredDevicesForStrategyInt(mCommunicationStrategyId); 2387 mDeviceInventory.removePreferredDevicesForStrategyInt(mAccessibilityStrategyId); 2388 } 2389 mDeviceInventory.applyConnectedDevicesRoles(); 2390 mDeviceInventory.reapplyExternalDevicesRoles(); 2391 } else { 2392 mDeviceInventory.setPreferredDevicesForStrategyInt( 2393 mCommunicationStrategyId, Arrays.asList(preferredCommunicationDevice)); 2394 mDeviceInventory.setPreferredDevicesForStrategyInt( 2395 mAccessibilityStrategyId, Arrays.asList(preferredCommunicationDevice)); 2396 } 2397 onUpdatePhoneStrategyDevice(preferredCommunicationDevice); 2398 } 2399 2400 /** 2401 * Select new communication device from communication route client at the top of the stack 2402 * and restore communication route including restarting SCO audio if needed. 2403 */ 2404 // @GuardedBy("mSetModeLock") 2405 @GuardedBy("mDeviceStateLock") onUpdateCommunicationRouteClient(boolean wasBtScoRequested, String eventSource)2406 private void onUpdateCommunicationRouteClient(boolean wasBtScoRequested, String eventSource) { 2407 CommunicationRouteClient crc = topCommunicationRouteClient(); 2408 if (AudioService.DEBUG_COMM_RTE) { 2409 Log.v(TAG, "onUpdateCommunicationRouteClient, crc: " + crc 2410 + " wasBtScoRequested: " + wasBtScoRequested + " eventSource: " + eventSource); 2411 } 2412 if (crc != null) { 2413 setCommunicationRouteForClient(crc.getBinder(), crc.getUid(), crc.getDevice(), 2414 BtHelper.SCO_MODE_UNDEFINED, crc.isPrivileged(), eventSource); 2415 } else { 2416 if (!isBluetoothScoRequested() && wasBtScoRequested) { 2417 mBtHelper.stopBluetoothSco(eventSource); 2418 } 2419 updateCommunicationRoute(eventSource); 2420 } 2421 } 2422 2423 // @GuardedBy("mSetModeLock") 2424 @GuardedBy("mDeviceStateLock") onUpdatePhoneStrategyDevice(AudioDeviceAttributes device)2425 private void onUpdatePhoneStrategyDevice(AudioDeviceAttributes device) { 2426 boolean wasSpeakerphoneActive = isSpeakerphoneActive(); 2427 mPreferredCommunicationDevice = device; 2428 updateActiveCommunicationDevice(); 2429 if (wasSpeakerphoneActive != isSpeakerphoneActive()) { 2430 try { 2431 mContext.sendBroadcastAsUser( 2432 new Intent(AudioManager.ACTION_SPEAKERPHONE_STATE_CHANGED) 2433 .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY), 2434 UserHandle.ALL); 2435 } catch (Exception e) { 2436 Log.w(TAG, "failed to broadcast ACTION_SPEAKERPHONE_STATE_CHANGED: " + e); 2437 } 2438 } 2439 mAudioService.postUpdateRingerModeServiceInt(); 2440 dispatchCommunicationDevice(); 2441 } 2442 2443 @GuardedBy("mDeviceStateLock") removeCommunicationRouteClient( IBinder cb, boolean unregister)2444 private CommunicationRouteClient removeCommunicationRouteClient( 2445 IBinder cb, boolean unregister) { 2446 for (CommunicationRouteClient cl : mCommunicationRouteClients) { 2447 if (cl.getBinder() == cb) { 2448 if (unregister) { 2449 cl.unregisterDeathRecipient(); 2450 } 2451 removeMsgForCheckClientState(cl.getUid()); 2452 mCommunicationRouteClients.remove(cl); 2453 return cl; 2454 } 2455 } 2456 return null; 2457 } 2458 2459 @GuardedBy("mDeviceStateLock") addCommunicationRouteClient(IBinder cb, int uid, AudioDeviceAttributes device, boolean isPrivileged)2460 private CommunicationRouteClient addCommunicationRouteClient(IBinder cb, int uid, 2461 AudioDeviceAttributes device, boolean isPrivileged) { 2462 // always insert new request at first position 2463 removeCommunicationRouteClient(cb, true); 2464 CommunicationRouteClient client = 2465 new CommunicationRouteClient(cb, uid, device, isPrivileged); 2466 if (client.registerDeathRecipient()) { 2467 mCommunicationRouteClients.add(0, client); 2468 if (!client.isActive()) { 2469 // initialize the inactive client's state as active and check it after 6 seconds 2470 setForceCommunicationClientStateAndDelayedCheck( 2471 client, 2472 !mAudioService.isPlaybackActiveForUid(client.getUid()), 2473 !mAudioService.isRecordingActiveForUid(client.getUid())); 2474 } 2475 return client; 2476 } 2477 return null; 2478 } 2479 2480 @GuardedBy("mDeviceStateLock") getCommunicationRouteClientForUid(int uid)2481 private CommunicationRouteClient getCommunicationRouteClientForUid(int uid) { 2482 for (CommunicationRouteClient cl : mCommunicationRouteClients) { 2483 if (cl.getUid() == uid) { 2484 return cl; 2485 } 2486 } 2487 return null; 2488 } 2489 2490 @GuardedBy("mDeviceStateLock") 2491 // LE Audio: For system server (Telecom) and APKs targeting S and above, we let the audio 2492 // policy routing rules select the default communication device. 2493 // For older APKs, we force LE Audio headset when connected as those APKs cannot select a LE 2494 // Audiodevice explicitly. communnicationDeviceLeAudioCompatOn()2495 private boolean communnicationDeviceLeAudioCompatOn() { 2496 return mAudioModeOwner.mMode == AudioSystem.MODE_IN_COMMUNICATION 2497 && !(CompatChanges.isChangeEnabled( 2498 USE_SET_COMMUNICATION_DEVICE, mAudioModeOwner.mUid) 2499 || mAudioModeOwner.mUid == android.os.Process.SYSTEM_UID); 2500 } 2501 2502 @GuardedBy("mDeviceStateLock") 2503 // Hearing Aid: For system server (Telecom) and IN_CALL mode we let the audio 2504 // policy routing rules select the default communication device. 2505 // For 3p apps and IN_COMMUNICATION mode we force Hearing aid when connected to maintain 2506 // backwards compatibility communnicationDeviceHaCompatOn()2507 private boolean communnicationDeviceHaCompatOn() { 2508 return mAudioModeOwner.mMode == AudioSystem.MODE_IN_COMMUNICATION 2509 && !(mAudioModeOwner.mUid == android.os.Process.SYSTEM_UID); 2510 } 2511 2512 @GuardedBy("mDeviceStateLock") getDefaultCommunicationDevice()2513 AudioDeviceAttributes getDefaultCommunicationDevice() { 2514 AudioDeviceAttributes device = null; 2515 // If both LE and Hearing Aid are active (thie should not happen), 2516 // priority to Hearing Aid. 2517 if (communnicationDeviceHaCompatOn()) { 2518 device = mDeviceInventory.getDeviceOfType(AudioSystem.DEVICE_OUT_HEARING_AID); 2519 } 2520 if (device == null && communnicationDeviceLeAudioCompatOn()) { 2521 device = mDeviceInventory.getDeviceOfType(AudioSystem.DEVICE_OUT_BLE_HEADSET); 2522 } 2523 return device; 2524 } 2525 updateCommunicationRouteClientsActivity( List<AudioPlaybackConfiguration> playbackConfigs, List<AudioRecordingConfiguration> recordConfigs)2526 void updateCommunicationRouteClientsActivity( 2527 List<AudioPlaybackConfiguration> playbackConfigs, 2528 List<AudioRecordingConfiguration> recordConfigs) { 2529 synchronized (mSetModeLock) { 2530 synchronized (mDeviceStateLock) { 2531 for (CommunicationRouteClient crc : mCommunicationRouteClients) { 2532 boolean wasActive = crc.isActive(); 2533 boolean updateClientState = false; 2534 if (playbackConfigs != null) { 2535 crc.setPlaybackActive(false); 2536 for (AudioPlaybackConfiguration config : playbackConfigs) { 2537 if (config.getClientUid() == crc.getUid() 2538 && config.isActive()) { 2539 crc.setPlaybackActive(true); 2540 updateClientState = true; 2541 break; 2542 } 2543 } 2544 } 2545 if (recordConfigs != null) { 2546 crc.setRecordingActive(false); 2547 for (AudioRecordingConfiguration config : recordConfigs) { 2548 if (config.getClientUid() == crc.getUid() 2549 && !config.isClientSilenced()) { 2550 crc.setRecordingActive(true); 2551 updateClientState = true; 2552 break; 2553 } 2554 } 2555 } 2556 if (updateClientState) { 2557 removeMsgForCheckClientState(crc.getUid()); 2558 updateCommunicationRouteClientState(crc, wasActive); 2559 } else { 2560 if (wasActive) { 2561 setForceCommunicationClientStateAndDelayedCheck( 2562 crc, 2563 playbackConfigs != null /* forcePlaybackActive */, 2564 recordConfigs != null /* forceRecordingActive */); 2565 } 2566 } 2567 } 2568 } 2569 } 2570 } 2571 getDeviceSensorUuid(AudioDeviceAttributes device)2572 @Nullable UUID getDeviceSensorUuid(AudioDeviceAttributes device) { 2573 synchronized (mDeviceStateLock) { 2574 return mDeviceInventory.getDeviceSensorUuid(device); 2575 } 2576 } 2577 dispatchPreferredMixerAttributesChangedCausedByDeviceRemoved(AudioDeviceInfo info)2578 void dispatchPreferredMixerAttributesChangedCausedByDeviceRemoved(AudioDeviceInfo info) { 2579 // Currently, only media usage will be allowed to set preferred mixer attributes 2580 mAudioService.dispatchPreferredMixerAttributesChanged( 2581 new AudioAttributes.Builder() 2582 .setUsage(AudioAttributes.USAGE_MEDIA).build(), 2583 info.getId(), 2584 null /*mixerAttributes*/); 2585 } 2586 2587 /** 2588 * post a message to persist the audio device settings. 2589 * Message is delayed by 1s on purpose in case of successive changes in quick succession (at 2590 * init time for instance) 2591 * Note this method is made public to work around a Mockito bug where it needs to be public 2592 * in order to be mocked by a test a the same package 2593 * (see https://code.google.com/archive/p/mockito/issues/127) 2594 */ persistAudioDeviceSettings()2595 public void persistAudioDeviceSettings() { 2596 sendMsg(MSG_PERSIST_AUDIO_DEVICE_SETTINGS, SENDMSG_REPLACE, /*delay*/ 1000); 2597 } 2598 onPersistAudioDeviceSettings()2599 void onPersistAudioDeviceSettings() { 2600 final String deviceSettings = mDeviceInventory.getDeviceSettings(); 2601 Log.v(TAG, "saving AdiDeviceState: " + deviceSettings); 2602 final SettingsAdapter settings = mAudioService.getSettings(); 2603 boolean res = settings.putSecureStringForUser(mAudioService.getContentResolver(), 2604 Settings.Secure.AUDIO_DEVICE_INVENTORY, 2605 deviceSettings, UserHandle.USER_CURRENT); 2606 if (!res) { 2607 Log.e(TAG, "error saving AdiDeviceState: " + deviceSettings); 2608 } 2609 } 2610 onReadAudioDeviceSettings()2611 void onReadAudioDeviceSettings() { 2612 final SettingsAdapter settingsAdapter = mAudioService.getSettings(); 2613 final ContentResolver contentResolver = mAudioService.getContentResolver(); 2614 String settings = settingsAdapter.getSecureStringForUser(contentResolver, 2615 Settings.Secure.AUDIO_DEVICE_INVENTORY, UserHandle.USER_CURRENT); 2616 if (settings == null) { 2617 Log.i(TAG, "reading AdiDeviceState from legacy key" 2618 + Settings.Secure.SPATIAL_AUDIO_ENABLED); 2619 // legacy string format for key SPATIAL_AUDIO_ENABLED has the same order of fields like 2620 // the strings for key AUDIO_DEVICE_INVENTORY. This will ensure to construct valid 2621 // device settings when calling {@link #setDeviceSettings()} 2622 settings = settingsAdapter.getSecureStringForUser(contentResolver, 2623 Settings.Secure.SPATIAL_AUDIO_ENABLED, UserHandle.USER_CURRENT); 2624 if (settings == null) { 2625 Log.i(TAG, "no AdiDeviceState stored with legacy key"); 2626 } else if (!settings.equals("")) { 2627 // Delete old key value and update the new key 2628 if (!settingsAdapter.putSecureStringForUser(contentResolver, 2629 Settings.Secure.SPATIAL_AUDIO_ENABLED, 2630 /*value=*/"", 2631 UserHandle.USER_CURRENT)) { 2632 Log.w(TAG, "cannot erase the legacy AdiDeviceState with key " 2633 + Settings.Secure.SPATIAL_AUDIO_ENABLED); 2634 } 2635 if (!settingsAdapter.putSecureStringForUser(contentResolver, 2636 Settings.Secure.AUDIO_DEVICE_INVENTORY, 2637 settings, 2638 UserHandle.USER_CURRENT)) { 2639 Log.e(TAG, "error updating the new AdiDeviceState with key " 2640 + Settings.Secure.AUDIO_DEVICE_INVENTORY); 2641 } 2642 } 2643 } 2644 2645 if (settings != null && !settings.equals("")) { 2646 setDeviceSettings(settings); 2647 } 2648 } 2649 setDeviceSettings(String settings)2650 void setDeviceSettings(String settings) { 2651 mDeviceInventory.setDeviceSettings(settings); 2652 } 2653 2654 /** Test only method. */ getDeviceSettings()2655 String getDeviceSettings() { 2656 return mDeviceInventory.getDeviceSettings(); 2657 } 2658 getImmutableDeviceInventory()2659 Collection<AdiDeviceState> getImmutableDeviceInventory() { 2660 return mDeviceInventory.getImmutableDeviceInventory(); 2661 } 2662 addOrUpdateDeviceSAStateInInventory(AdiDeviceState deviceState)2663 void addOrUpdateDeviceSAStateInInventory(AdiDeviceState deviceState) { 2664 mDeviceInventory.addOrUpdateDeviceSAStateInInventory(deviceState); 2665 } 2666 addOrUpdateBtAudioDeviceCategoryInInventory(AdiDeviceState deviceState)2667 void addOrUpdateBtAudioDeviceCategoryInInventory(AdiDeviceState deviceState) { 2668 mDeviceInventory.addOrUpdateAudioDeviceCategoryInInventory(deviceState); 2669 } 2670 2671 @Nullable findDeviceStateForAudioDeviceAttributes(AudioDeviceAttributes ada, int canonicalType)2672 AdiDeviceState findDeviceStateForAudioDeviceAttributes(AudioDeviceAttributes ada, 2673 int canonicalType) { 2674 return mDeviceInventory.findDeviceStateForAudioDeviceAttributes(ada, canonicalType); 2675 } 2676 2677 @Nullable findBtDeviceStateForAddress(String address, boolean isBle)2678 AdiDeviceState findBtDeviceStateForAddress(String address, boolean isBle) { 2679 return mDeviceInventory.findBtDeviceStateForAddress(address, isBle); 2680 } 2681 2682 //------------------------------------------------ 2683 // for testing purposes only clearDeviceInventory()2684 void clearDeviceInventory() { 2685 mDeviceInventory.clearDeviceInventory(); 2686 } 2687 } 2688