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.AudioRoutesInfo; 34 import android.media.AudioSystem; 35 import android.media.BluetoothProfileConnectionInfo; 36 import android.media.IAudioRoutesObserver; 37 import android.media.ICapturePresetDevicesRoleDispatcher; 38 import android.media.ICommunicationDeviceDispatcher; 39 import android.media.IStrategyPreferredDevicesDispatcher; 40 import android.media.MediaMetrics; 41 import android.media.audiopolicy.AudioProductStrategy; 42 import android.os.Binder; 43 import android.os.Handler; 44 import android.os.IBinder; 45 import android.os.Looper; 46 import android.os.Message; 47 import android.os.PowerManager; 48 import android.os.RemoteCallbackList; 49 import android.os.RemoteException; 50 import android.os.SystemClock; 51 import android.os.UserHandle; 52 import android.text.TextUtils; 53 import android.util.Log; 54 import android.util.PrintWriterPrinter; 55 56 import com.android.internal.annotations.GuardedBy; 57 58 import java.io.PrintWriter; 59 import java.util.ArrayList; 60 import java.util.Arrays; 61 import java.util.HashSet; 62 import java.util.LinkedList; 63 import java.util.List; 64 import java.util.NoSuchElementException; 65 import java.util.Set; 66 import java.util.UUID; 67 import java.util.concurrent.atomic.AtomicBoolean; 68 69 70 /** @hide */ 71 /*package*/ final class AudioDeviceBroker { 72 73 private static final String TAG = "AS.AudioDeviceBroker"; 74 75 private static final long BROKER_WAKELOCK_TIMEOUT_MS = 5000; //5s 76 77 /*package*/ static final int BTA2DP_DOCK_TIMEOUT_MS = 8000; 78 // Timeout for connection to bluetooth headset service 79 /*package*/ static final int BT_HEADSET_CNCT_TIMEOUT_MS = 3000; 80 81 // Delay before checking it music should be unmuted after processing an A2DP message 82 private static final int BTA2DP_MUTE_CHECK_DELAY_MS = 100; 83 84 private final @NonNull AudioService mAudioService; 85 private final @NonNull Context mContext; 86 private final @NonNull AudioSystemAdapter mAudioSystem; 87 88 /** ID for Communication strategy retrieved form audio policy manager */ 89 private int mCommunicationStrategyId = -1; 90 91 /** ID for Accessibility strategy retrieved form audio policy manager */ 92 private int mAccessibilityStrategyId = -1; 93 94 95 /** Active communication device reported by audio policy manager */ 96 private AudioDeviceInfo mActiveCommunicationDevice; 97 /** Last preferred device set for communication strategy */ 98 private AudioDeviceAttributes mPreferredCommunicationDevice; 99 100 // Manages all connected devices, only ever accessed on the message loop 101 private final AudioDeviceInventory mDeviceInventory; 102 // Manages notifications to BT service 103 private final BtHelper mBtHelper; 104 // Adapter for system_server-reserved operations 105 private final SystemServerAdapter mSystemServer; 106 107 108 //------------------------------------------------------------------- 109 // we use a different lock than mDeviceStateLock so as not to create 110 // lock contention between enqueueing a message and handling them 111 private static final Object sLastDeviceConnectionMsgTimeLock = new Object(); 112 @GuardedBy("sLastDeviceConnectionMsgTimeLock") 113 private static long sLastDeviceConnectMsgTime = 0; 114 115 // General lock to be taken whenever the state of the audio devices is to be checked or changed 116 private final Object mDeviceStateLock = new Object(); 117 118 // Request to override default use of A2DP for media. 119 @GuardedBy("mDeviceStateLock") 120 private boolean mBluetoothA2dpEnabled; 121 122 // lock always taken when accessing AudioService.mSetModeDeathHandlers 123 // TODO do not "share" the lock between AudioService and BtHelpr, see b/123769055 124 /*package*/ final Object mSetModeLock = new Object(); 125 126 /** AudioModeInfo contains information on current audio mode owner 127 * communicated by AudioService */ 128 /* package */ static final class AudioModeInfo { 129 /** Current audio mode */ 130 final int mMode; 131 /** PID of current audio mode owner */ 132 final int mPid; 133 /** UID of current audio mode owner */ 134 final int mUid; 135 AudioModeInfo(int mode, int pid, int uid)136 AudioModeInfo(int mode, int pid, int uid) { 137 mMode = mode; 138 mPid = pid; 139 mUid = uid; 140 } 141 142 @Override toString()143 public String toString() { 144 return "AudioModeInfo: mMode=" + AudioSystem.modeToString(mMode) 145 + ", mPid=" + mPid 146 + ", mUid=" + mUid; 147 } 148 }; 149 150 private AudioModeInfo mAudioModeOwner = new AudioModeInfo(AudioSystem.MODE_NORMAL, 0, 0); 151 152 /** 153 * Indicates that default communication device is chosen by routing rules in audio policy 154 * manager and not forced by AudioDeviceBroker. 155 */ 156 @ChangeId 157 @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.S_V2) 158 public static final long USE_SET_COMMUNICATION_DEVICE = 243827847L; 159 160 //------------------------------------------------------------------- AudioDeviceBroker(@onNull Context context, @NonNull AudioService service, @NonNull AudioSystemAdapter audioSystem)161 /*package*/ AudioDeviceBroker(@NonNull Context context, @NonNull AudioService service, 162 @NonNull AudioSystemAdapter audioSystem) { 163 mContext = context; 164 mAudioService = service; 165 mBtHelper = new BtHelper(this); 166 mDeviceInventory = new AudioDeviceInventory(this); 167 mSystemServer = SystemServerAdapter.getDefaultAdapter(mContext); 168 mAudioSystem = audioSystem; 169 170 init(); 171 } 172 173 /** for test purposes only, inject AudioDeviceInventory and adapter for operations running 174 * in system_server */ AudioDeviceBroker(@onNull Context context, @NonNull AudioService service, @NonNull AudioDeviceInventory mockDeviceInventory, @NonNull SystemServerAdapter mockSystemServer, @NonNull AudioSystemAdapter audioSystem)175 AudioDeviceBroker(@NonNull Context context, @NonNull AudioService service, 176 @NonNull AudioDeviceInventory mockDeviceInventory, 177 @NonNull SystemServerAdapter mockSystemServer, 178 @NonNull AudioSystemAdapter audioSystem) { 179 mContext = context; 180 mAudioService = service; 181 mBtHelper = new BtHelper(this); 182 mDeviceInventory = mockDeviceInventory; 183 mSystemServer = mockSystemServer; 184 mAudioSystem = audioSystem; 185 186 init(); 187 } 188 initRoutingStrategyIds()189 private void initRoutingStrategyIds() { 190 List<AudioProductStrategy> strategies = AudioProductStrategy.getAudioProductStrategies(); 191 mCommunicationStrategyId = -1; 192 mAccessibilityStrategyId = -1; 193 for (AudioProductStrategy strategy : strategies) { 194 if (mCommunicationStrategyId == -1 195 && strategy.getAudioAttributesForLegacyStreamType( 196 AudioSystem.STREAM_VOICE_CALL) != null) { 197 mCommunicationStrategyId = strategy.getId(); 198 } 199 if (mAccessibilityStrategyId == -1 200 && strategy.getAudioAttributesForLegacyStreamType( 201 AudioSystem.STREAM_ACCESSIBILITY) != null) { 202 mAccessibilityStrategyId = strategy.getId(); 203 } 204 } 205 } 206 init()207 private void init() { 208 setupMessaging(mContext); 209 210 initRoutingStrategyIds(); 211 mPreferredCommunicationDevice = null; 212 updateActiveCommunicationDevice(); 213 214 mSystemServer.registerUserStartedReceiver(mContext); 215 } 216 getContext()217 /*package*/ Context getContext() { 218 return mContext; 219 } 220 221 //--------------------------------------------------------------------- 222 // Communication from AudioService 223 // All methods are asynchronous and never block 224 // All permission checks are done in AudioService, all incoming calls are considered "safe" 225 // All post* methods are asynchronous 226 onSystemReady()227 /*package*/ void onSystemReady() { 228 synchronized (mSetModeLock) { 229 synchronized (mDeviceStateLock) { 230 mAudioModeOwner = mAudioService.getAudioModeOwner(); 231 mBtHelper.onSystemReady(); 232 } 233 } 234 } 235 onAudioServerDied()236 /*package*/ void onAudioServerDied() { 237 // restore devices 238 sendMsgNoDelay(MSG_RESTORE_DEVICES, SENDMSG_REPLACE); 239 } 240 setForceUse_Async(int useCase, int config, String eventSource)241 /*package*/ void setForceUse_Async(int useCase, int config, String eventSource) { 242 sendIILMsgNoDelay(MSG_IIL_SET_FORCE_USE, SENDMSG_QUEUE, 243 useCase, config, eventSource); 244 } 245 toggleHdmiIfConnected_Async()246 /*package*/ void toggleHdmiIfConnected_Async() { 247 sendMsgNoDelay(MSG_TOGGLE_HDMI, SENDMSG_QUEUE); 248 } 249 disconnectAllBluetoothProfiles()250 /*package*/ void disconnectAllBluetoothProfiles() { 251 synchronized (mDeviceStateLock) { 252 mBtHelper.disconnectAllBluetoothProfiles(); 253 } 254 } 255 256 /** 257 * Handle BluetoothHeadset intents where the action is one of 258 * {@link BluetoothHeadset#ACTION_ACTIVE_DEVICE_CHANGED} or 259 * {@link BluetoothHeadset#ACTION_AUDIO_STATE_CHANGED}. 260 * @param intent 261 */ receiveBtEvent(@onNull Intent intent)262 /*package*/ void receiveBtEvent(@NonNull Intent intent) { 263 synchronized (mSetModeLock) { 264 synchronized (mDeviceStateLock) { 265 mBtHelper.receiveBtEvent(intent); 266 } 267 } 268 } 269 setBluetoothA2dpOn_Async(boolean on, String source)270 /*package*/ void setBluetoothA2dpOn_Async(boolean on, String source) { 271 synchronized (mDeviceStateLock) { 272 if (mBluetoothA2dpEnabled == on) { 273 return; 274 } 275 mBluetoothA2dpEnabled = on; 276 mBrokerHandler.removeMessages(MSG_IIL_SET_FORCE_BT_A2DP_USE); 277 sendIILMsgNoDelay(MSG_IIL_SET_FORCE_BT_A2DP_USE, SENDMSG_QUEUE, 278 AudioSystem.FOR_MEDIA, 279 mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP, 280 source); 281 } 282 } 283 284 /** 285 * Turns speakerphone on/off 286 * @param on 287 * @param eventSource for logging purposes 288 */ setSpeakerphoneOn(IBinder cb, int pid, boolean on, String eventSource)289 /*package*/ void setSpeakerphoneOn(IBinder cb, int pid, boolean on, String eventSource) { 290 291 if (AudioService.DEBUG_COMM_RTE) { 292 Log.v(TAG, "setSpeakerphoneOn, on: " + on + " pid: " + pid); 293 } 294 295 synchronized (mSetModeLock) { 296 synchronized (mDeviceStateLock) { 297 AudioDeviceAttributes device = null; 298 if (on) { 299 device = new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_SPEAKER, ""); 300 } else { 301 CommunicationRouteClient client = getCommunicationRouteClientForPid(pid); 302 if (client == null || !client.requestsSpeakerphone()) { 303 return; 304 } 305 } 306 postSetCommunicationRouteForClient(new CommunicationClientInfo( 307 cb, pid, device, BtHelper.SCO_MODE_UNDEFINED, eventSource)); 308 } 309 } 310 } 311 312 /** 313 * Select device for use for communication use cases. 314 * @param cb Client binder for death detection 315 * @param pid Client pid 316 * @param device Device selected or null to unselect. 317 * @param eventSource for logging purposes 318 */ setCommunicationDevice( IBinder cb, int pid, AudioDeviceInfo device, String eventSource)319 /*package*/ boolean setCommunicationDevice( 320 IBinder cb, int pid, AudioDeviceInfo device, String eventSource) { 321 322 if (AudioService.DEBUG_COMM_RTE) { 323 Log.v(TAG, "setCommunicationDevice, device: " + device + ", pid: " + pid); 324 } 325 326 synchronized (mSetModeLock) { 327 synchronized (mDeviceStateLock) { 328 AudioDeviceAttributes deviceAttr = null; 329 if (device != null) { 330 deviceAttr = new AudioDeviceAttributes(device); 331 } else { 332 CommunicationRouteClient client = getCommunicationRouteClientForPid(pid); 333 if (client == null) { 334 return false; 335 } 336 } 337 postSetCommunicationRouteForClient(new CommunicationClientInfo( 338 cb, pid, deviceAttr, BtHelper.SCO_MODE_UNDEFINED, eventSource)); 339 } 340 } 341 return true; 342 } 343 344 @GuardedBy("mDeviceStateLock") setCommunicationRouteForClient( IBinder cb, int pid, AudioDeviceAttributes device, int scoAudioMode, String eventSource)345 /*package*/ void setCommunicationRouteForClient( 346 IBinder cb, int pid, AudioDeviceAttributes device, 347 int scoAudioMode, String eventSource) { 348 349 if (AudioService.DEBUG_COMM_RTE) { 350 Log.v(TAG, "setCommunicationRouteForClient: device: " + device); 351 } 352 AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent( 353 "setCommunicationRouteForClient for pid: " + pid 354 + " device: " + device 355 + " from API: " + eventSource)).printLog(TAG)); 356 357 final boolean wasBtScoRequested = isBluetoothScoRequested(); 358 CommunicationRouteClient client; 359 360 361 // Save previous client route in case of failure to start BT SCO audio 362 AudioDeviceAttributes prevClientDevice = null; 363 client = getCommunicationRouteClientForPid(pid); 364 if (client != null) { 365 prevClientDevice = client.getDevice(); 366 } 367 368 if (device != null) { 369 client = addCommunicationRouteClient(cb, pid, device); 370 if (client == null) { 371 Log.w(TAG, "setCommunicationRouteForClient: could not add client for pid: " 372 + pid + " and device: " + device); 373 } 374 } else { 375 client = removeCommunicationRouteClient(cb, true); 376 } 377 if (client == null) { 378 return; 379 } 380 381 boolean isBtScoRequested = isBluetoothScoRequested(); 382 if (isBtScoRequested && (!wasBtScoRequested || !isBluetoothScoActive())) { 383 if (!mBtHelper.startBluetoothSco(scoAudioMode, eventSource)) { 384 Log.w(TAG, "setCommunicationRouteForClient: failure to start BT SCO for pid: " 385 + pid); 386 // clean up or restore previous client selection 387 if (prevClientDevice != null) { 388 addCommunicationRouteClient(cb, pid, prevClientDevice); 389 } else { 390 removeCommunicationRouteClient(cb, true); 391 } 392 postBroadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 393 } 394 } else if (!isBtScoRequested && wasBtScoRequested) { 395 mBtHelper.stopBluetoothSco(eventSource); 396 } 397 398 sendLMsgNoDelay(MSG_L_UPDATE_COMMUNICATION_ROUTE, SENDMSG_QUEUE, eventSource); 399 } 400 401 /** 402 * Returns the communication client with the highest priority: 403 * - 1) the client which is currently also controlling the audio mode 404 * - 2) the first client in the stack if there is no audio mode owner 405 * - 3) no client otherwise 406 * @return CommunicationRouteClient the client driving the communication use case routing. 407 */ 408 @GuardedBy("mDeviceStateLock") topCommunicationRouteClient()409 private CommunicationRouteClient topCommunicationRouteClient() { 410 for (CommunicationRouteClient crc : mCommunicationRouteClients) { 411 if (crc.getPid() == mAudioModeOwner.mPid) { 412 return crc; 413 } 414 } 415 if (!mCommunicationRouteClients.isEmpty() && mAudioModeOwner.mPid == 0) { 416 return mCommunicationRouteClients.get(0); 417 } 418 return null; 419 } 420 421 /** 422 * Returns the device currently requested for communication use case. 423 * Use the device requested by the communication route client selected by 424 * {@link #topCommunicationRouteClient()} if any or none otherwise. 425 * @return AudioDeviceAttributes the requested device for communication. 426 */ 427 @GuardedBy("mDeviceStateLock") requestedCommunicationDevice()428 private AudioDeviceAttributes requestedCommunicationDevice() { 429 CommunicationRouteClient crc = topCommunicationRouteClient(); 430 AudioDeviceAttributes device = crc != null ? crc.getDevice() : null; 431 if (AudioService.DEBUG_COMM_RTE) { 432 Log.v(TAG, "requestedCommunicationDevice, device: " 433 + device + "mAudioModeOwner: " + mAudioModeOwner.toString()); 434 } 435 return device; 436 } 437 438 private static final int[] VALID_COMMUNICATION_DEVICE_TYPES = { 439 AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, 440 AudioDeviceInfo.TYPE_BLUETOOTH_SCO, 441 AudioDeviceInfo.TYPE_WIRED_HEADSET, 442 AudioDeviceInfo.TYPE_USB_HEADSET, 443 AudioDeviceInfo.TYPE_BUILTIN_EARPIECE, 444 AudioDeviceInfo.TYPE_WIRED_HEADPHONES, 445 AudioDeviceInfo.TYPE_HEARING_AID, 446 AudioDeviceInfo.TYPE_BLE_HEADSET, 447 AudioDeviceInfo.TYPE_USB_DEVICE, 448 AudioDeviceInfo.TYPE_BLE_SPEAKER, 449 AudioDeviceInfo.TYPE_LINE_ANALOG, 450 AudioDeviceInfo.TYPE_HDMI, 451 AudioDeviceInfo.TYPE_AUX_LINE 452 }; 453 isValidCommunicationDevice(AudioDeviceInfo device)454 /*package */ static boolean isValidCommunicationDevice(AudioDeviceInfo device) { 455 for (int type : VALID_COMMUNICATION_DEVICE_TYPES) { 456 if (device.getType() == type) { 457 return true; 458 } 459 } 460 return false; 461 } 462 getAvailableCommunicationDevices()463 /* package */ static List<AudioDeviceInfo> getAvailableCommunicationDevices() { 464 ArrayList<AudioDeviceInfo> commDevices = new ArrayList<>(); 465 AudioDeviceInfo[] allDevices = 466 AudioManager.getDevicesStatic(AudioManager.GET_DEVICES_OUTPUTS); 467 for (AudioDeviceInfo device : allDevices) { 468 if (isValidCommunicationDevice(device)) { 469 commDevices.add(device); 470 } 471 } 472 return commDevices; 473 } 474 getCommunicationDeviceOfType(int type)475 private @Nullable AudioDeviceInfo getCommunicationDeviceOfType(int type) { 476 return getAvailableCommunicationDevices().stream().filter(d -> d.getType() == type) 477 .findFirst().orElse(null); 478 } 479 480 /** 481 * Returns the device currently requested for communication use case. 482 * @return AudioDeviceInfo the requested device for communication. 483 */ getCommunicationDevice()484 /* package */ AudioDeviceInfo getCommunicationDevice() { 485 synchronized (mDeviceStateLock) { 486 updateActiveCommunicationDevice(); 487 AudioDeviceInfo device = mActiveCommunicationDevice; 488 // make sure we return a valid communication device (i.e. a device that is allowed by 489 // setCommunicationDevice()) for consistency. 490 if (device != null) { 491 // a digital dock is used instead of the speaker in speakerphone mode and should 492 // be reflected as such 493 if (device.getType() == AudioDeviceInfo.TYPE_DOCK) { 494 device = getCommunicationDeviceOfType(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER); 495 } 496 } 497 // Try to default to earpiece when current communication device is not valid. This can 498 // happen for instance if no call is active. If no earpiece device is available take the 499 // first valid communication device 500 if (device == null || !AudioDeviceBroker.isValidCommunicationDevice(device)) { 501 device = getCommunicationDeviceOfType(AudioDeviceInfo.TYPE_BUILTIN_EARPIECE); 502 if (device == null) { 503 List<AudioDeviceInfo> commDevices = getAvailableCommunicationDevices(); 504 if (!commDevices.isEmpty()) { 505 device = commDevices.get(0); 506 } 507 } 508 } 509 return device; 510 } 511 } 512 513 /** 514 * Updates currently active communication device (mActiveCommunicationDevice). 515 */ 516 @GuardedBy("mDeviceStateLock") updateActiveCommunicationDevice()517 void updateActiveCommunicationDevice() { 518 AudioDeviceAttributes device = preferredCommunicationDevice(); 519 if (device == null) { 520 AudioAttributes attr = 521 AudioProductStrategy.getAudioAttributesForStrategyWithLegacyStreamType( 522 AudioSystem.STREAM_VOICE_CALL); 523 List<AudioDeviceAttributes> devices = mAudioSystem.getDevicesForAttributes( 524 attr, false /* forVolume */); 525 if (devices.isEmpty()) { 526 if (mAudioService.isPlatformVoice()) { 527 Log.w(TAG, 528 "updateActiveCommunicationDevice(): no device for phone strategy"); 529 } 530 mActiveCommunicationDevice = null; 531 return; 532 } 533 device = devices.get(0); 534 } 535 mActiveCommunicationDevice = AudioManager.getDeviceInfoFromTypeAndAddress( 536 device.getType(), device.getAddress()); 537 } 538 539 /** 540 * Indicates if the device which type is passed as argument is currently resquested to be used 541 * for communication. 542 * @param deviceType the device type the query applies to. 543 * @return true if this device type is requested for communication. 544 */ isDeviceRequestedForCommunication(int deviceType)545 private boolean isDeviceRequestedForCommunication(int deviceType) { 546 synchronized (mDeviceStateLock) { 547 AudioDeviceAttributes device = requestedCommunicationDevice(); 548 return device != null && device.getType() == deviceType; 549 } 550 } 551 552 /** 553 * Indicates if the device which type is passed as argument is currently either resquested 554 * to be used for communication or selected for an other reason (e.g bluetooth SCO audio 555 * is active for SCO device). 556 * @param deviceType the device type the query applies to. 557 * @return true if this device type is requested for communication. 558 */ isDeviceOnForCommunication(int deviceType)559 private boolean isDeviceOnForCommunication(int deviceType) { 560 synchronized (mDeviceStateLock) { 561 AudioDeviceAttributes device = preferredCommunicationDevice(); 562 return device != null && device.getType() == deviceType; 563 } 564 } 565 566 /** 567 * Indicates if the device which type is passed as argument is active for communication. 568 * Active means not only currently used by audio policy manager for communication strategy 569 * but also explicitly requested for use by communication strategy. 570 * @param deviceType the device type the query applies to. 571 * @return true if this device type is requested for communication. 572 */ isDeviceActiveForCommunication(int deviceType)573 private boolean isDeviceActiveForCommunication(int deviceType) { 574 return mActiveCommunicationDevice != null 575 && mActiveCommunicationDevice.getType() == deviceType 576 && mPreferredCommunicationDevice != null 577 && mPreferredCommunicationDevice.getType() == deviceType; 578 } 579 580 /** 581 * Helper method on top of isDeviceRequestedForCommunication() indicating if 582 * speakerphone ON is currently requested or not. 583 * @return true if speakerphone ON requested, false otherwise. 584 */ isSpeakerphoneRequested()585 private boolean isSpeakerphoneRequested() { 586 return isDeviceRequestedForCommunication(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER); 587 } 588 589 /** 590 * Indicates if preferred route selection for communication is speakerphone. 591 * @return true if speakerphone is active, false otherwise. 592 */ isSpeakerphoneOn()593 /*package*/ boolean isSpeakerphoneOn() { 594 return isDeviceOnForCommunication(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER); 595 } 596 isSpeakerphoneActive()597 private boolean isSpeakerphoneActive() { 598 return isDeviceActiveForCommunication(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER); 599 } 600 601 /** 602 * Helper method on top of isDeviceRequestedForCommunication() indicating if 603 * Bluetooth SCO ON is currently requested or not. 604 * @return true if Bluetooth SCO ON is requested, false otherwise. 605 */ isBluetoothScoRequested()606 /*package*/ boolean isBluetoothScoRequested() { 607 return isDeviceRequestedForCommunication(AudioDeviceInfo.TYPE_BLUETOOTH_SCO); 608 } 609 610 /** 611 * Indicates if preferred route selection for communication is Bluetooth SCO. 612 * @return true if Bluetooth SCO is preferred , false otherwise. 613 */ isBluetoothScoOn()614 /*package*/ boolean isBluetoothScoOn() { 615 return isDeviceOnForCommunication(AudioDeviceInfo.TYPE_BLUETOOTH_SCO); 616 } 617 isBluetoothScoActive()618 /*package*/ boolean isBluetoothScoActive() { 619 return isDeviceActiveForCommunication(AudioDeviceInfo.TYPE_BLUETOOTH_SCO); 620 } 621 isDeviceConnected(@onNull AudioDeviceAttributes device)622 /*package*/ boolean isDeviceConnected(@NonNull AudioDeviceAttributes device) { 623 synchronized (mDeviceStateLock) { 624 return mDeviceInventory.isDeviceConnected(device); 625 } 626 } 627 setWiredDeviceConnectionState(AudioDeviceAttributes attributes, @AudioService.ConnectionState int state, String caller)628 /*package*/ void setWiredDeviceConnectionState(AudioDeviceAttributes attributes, 629 @AudioService.ConnectionState int state, String caller) { 630 //TODO move logging here just like in setBluetooth* methods 631 synchronized (mDeviceStateLock) { 632 mDeviceInventory.setWiredDeviceConnectionState(attributes, state, caller); 633 } 634 } 635 setTestDeviceConnectionState(@onNull AudioDeviceAttributes device, @AudioService.ConnectionState int state)636 /*package*/ void setTestDeviceConnectionState(@NonNull AudioDeviceAttributes device, 637 @AudioService.ConnectionState int state) { 638 synchronized (mDeviceStateLock) { 639 mDeviceInventory.setTestDeviceConnectionState(device, state); 640 } 641 } 642 643 /*package*/ static final class BleVolumeInfo { 644 final int mIndex; 645 final int mMaxIndex; 646 final int mStreamType; 647 BleVolumeInfo(int index, int maxIndex, int streamType)648 BleVolumeInfo(int index, int maxIndex, int streamType) { 649 mIndex = index; 650 mMaxIndex = maxIndex; 651 mStreamType = streamType; 652 } 653 }; 654 655 /*package*/ static final class BtDeviceChangedData { 656 final @Nullable BluetoothDevice mNewDevice; 657 final @Nullable BluetoothDevice mPreviousDevice; 658 final @NonNull BluetoothProfileConnectionInfo mInfo; 659 final @NonNull String mEventSource; 660 BtDeviceChangedData(@ullable BluetoothDevice newDevice, @Nullable BluetoothDevice previousDevice, @NonNull BluetoothProfileConnectionInfo info, @NonNull String eventSource)661 BtDeviceChangedData(@Nullable BluetoothDevice newDevice, 662 @Nullable BluetoothDevice previousDevice, 663 @NonNull BluetoothProfileConnectionInfo info, @NonNull String eventSource) { 664 mNewDevice = newDevice; 665 mPreviousDevice = previousDevice; 666 mInfo = info; 667 mEventSource = eventSource; 668 } 669 670 @Override toString()671 public String toString() { 672 return "BtDeviceChangedData profile=" + BluetoothProfile.getProfileName( 673 mInfo.getProfile()) 674 + ", switch device: [" + mPreviousDevice + "] -> [" + mNewDevice + "]"; 675 } 676 } 677 678 /*package*/ static final class BtDeviceInfo { 679 final @NonNull BluetoothDevice mDevice; 680 final @AudioService.BtProfileConnectionState int mState; 681 final @AudioService.BtProfile int mProfile; 682 final boolean mSupprNoisy; 683 final int mVolume; 684 final boolean mIsLeOutput; 685 final @NonNull String mEventSource; 686 final @AudioSystem.AudioFormatNativeEnumForBtCodec int mCodec; 687 final int mAudioSystemDevice; 688 final int mMusicDevice; 689 BtDeviceInfo(@onNull BtDeviceChangedData d, @NonNull BluetoothDevice device, int state, int audioDevice, @AudioSystem.AudioFormatNativeEnumForBtCodec int codec)690 BtDeviceInfo(@NonNull BtDeviceChangedData d, @NonNull BluetoothDevice device, int state, 691 int audioDevice, @AudioSystem.AudioFormatNativeEnumForBtCodec int codec) { 692 mDevice = device; 693 mState = state; 694 mProfile = d.mInfo.getProfile(); 695 mSupprNoisy = d.mInfo.isSuppressNoisyIntent(); 696 mVolume = d.mInfo.getVolume(); 697 mIsLeOutput = d.mInfo.isLeOutput(); 698 mEventSource = d.mEventSource; 699 mAudioSystemDevice = audioDevice; 700 mMusicDevice = AudioSystem.DEVICE_NONE; 701 mCodec = codec; 702 } 703 704 // constructor used by AudioDeviceBroker to search similar message BtDeviceInfo(@onNull BluetoothDevice device, int profile)705 BtDeviceInfo(@NonNull BluetoothDevice device, int profile) { 706 mDevice = device; 707 mProfile = profile; 708 mEventSource = ""; 709 mMusicDevice = AudioSystem.DEVICE_NONE; 710 mCodec = AudioSystem.AUDIO_FORMAT_DEFAULT; 711 mAudioSystemDevice = 0; 712 mState = 0; 713 mSupprNoisy = false; 714 mVolume = -1; 715 mIsLeOutput = false; 716 } 717 718 // constructor used by AudioDeviceInventory when config change failed BtDeviceInfo(@onNull BluetoothDevice device, int profile, int state, int musicDevice, int audioSystemDevice)719 BtDeviceInfo(@NonNull BluetoothDevice device, int profile, int state, int musicDevice, 720 int audioSystemDevice) { 721 mDevice = device; 722 mProfile = profile; 723 mEventSource = ""; 724 mMusicDevice = musicDevice; 725 mCodec = AudioSystem.AUDIO_FORMAT_DEFAULT; 726 mAudioSystemDevice = audioSystemDevice; 727 mState = state; 728 mSupprNoisy = false; 729 mVolume = -1; 730 mIsLeOutput = false; 731 } 732 733 // redefine equality op so we can match messages intended for this device 734 @Override equals(Object o)735 public boolean equals(Object o) { 736 if (o == null) { 737 return false; 738 } 739 if (this == o) { 740 return true; 741 } 742 if (o instanceof BtDeviceInfo) { 743 return mProfile == ((BtDeviceInfo) o).mProfile 744 && mDevice.equals(((BtDeviceInfo) o).mDevice); 745 } 746 return false; 747 } 748 } 749 createBtDeviceInfo(@onNull BtDeviceChangedData d, @NonNull BluetoothDevice device, int state)750 BtDeviceInfo createBtDeviceInfo(@NonNull BtDeviceChangedData d, @NonNull BluetoothDevice device, 751 int state) { 752 int audioDevice; 753 int codec = AudioSystem.AUDIO_FORMAT_DEFAULT; 754 switch (d.mInfo.getProfile()) { 755 case BluetoothProfile.A2DP_SINK: 756 audioDevice = AudioSystem.DEVICE_IN_BLUETOOTH_A2DP; 757 break; 758 case BluetoothProfile.A2DP: 759 audioDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP; 760 synchronized (mDeviceStateLock) { 761 codec = mBtHelper.getA2dpCodec(device); 762 } 763 break; 764 case BluetoothProfile.HEARING_AID: 765 audioDevice = AudioSystem.DEVICE_OUT_HEARING_AID; 766 break; 767 case BluetoothProfile.LE_AUDIO: 768 if (d.mInfo.isLeOutput()) { 769 audioDevice = AudioSystem.DEVICE_OUT_BLE_HEADSET; 770 } else { 771 audioDevice = AudioSystem.DEVICE_IN_BLE_HEADSET; 772 } 773 break; 774 case BluetoothProfile.LE_AUDIO_BROADCAST: 775 audioDevice = AudioSystem.DEVICE_OUT_BLE_BROADCAST; 776 break; 777 default: throw new IllegalArgumentException("Invalid profile " + d.mInfo.getProfile()); 778 } 779 return new BtDeviceInfo(d, device, state, audioDevice, codec); 780 } 781 btMediaMetricRecord(@onNull BluetoothDevice device, String state, @NonNull BtDeviceChangedData data)782 private void btMediaMetricRecord(@NonNull BluetoothDevice device, String state, 783 @NonNull BtDeviceChangedData data) { 784 final String name = TextUtils.emptyIfNull(device.getName()); 785 new MediaMetrics.Item(MediaMetrics.Name.AUDIO_DEVICE + MediaMetrics.SEPARATOR 786 + "queueOnBluetoothActiveDeviceChanged") 787 .set(MediaMetrics.Property.STATE, state) 788 .set(MediaMetrics.Property.STATUS, data.mInfo.getProfile()) 789 .set(MediaMetrics.Property.NAME, name) 790 .record(); 791 } 792 793 /** 794 * will block on mDeviceStateLock, which is held during an A2DP (dis) connection 795 * not just a simple message post 796 * @param info struct with the (dis)connection information 797 */ queueOnBluetoothActiveDeviceChanged(@onNull BtDeviceChangedData data)798 /*package*/ void queueOnBluetoothActiveDeviceChanged(@NonNull BtDeviceChangedData data) { 799 if (data.mInfo.getProfile() == BluetoothProfile.A2DP && data.mPreviousDevice != null 800 && data.mPreviousDevice.equals(data.mNewDevice)) { 801 final String name = TextUtils.emptyIfNull(data.mNewDevice.getName()); 802 new MediaMetrics.Item(MediaMetrics.Name.AUDIO_DEVICE + MediaMetrics.SEPARATOR 803 + "queueOnBluetoothActiveDeviceChanged_update") 804 .set(MediaMetrics.Property.NAME, name) 805 .set(MediaMetrics.Property.STATUS, data.mInfo.getProfile()) 806 .record(); 807 synchronized (mDeviceStateLock) { 808 postBluetoothA2dpDeviceConfigChange(data.mNewDevice); 809 } 810 } else { 811 synchronized (mDeviceStateLock) { 812 if (data.mPreviousDevice != null) { 813 btMediaMetricRecord(data.mPreviousDevice, MediaMetrics.Value.DISCONNECTED, 814 data); 815 sendLMsgNoDelay(MSG_L_BT_ACTIVE_DEVICE_CHANGE_EXT, SENDMSG_QUEUE, 816 createBtDeviceInfo(data, data.mPreviousDevice, 817 BluetoothProfile.STATE_DISCONNECTED)); 818 } 819 if (data.mNewDevice != null) { 820 btMediaMetricRecord(data.mNewDevice, MediaMetrics.Value.CONNECTED, data); 821 sendLMsgNoDelay(MSG_L_BT_ACTIVE_DEVICE_CHANGE_EXT, SENDMSG_QUEUE, 822 createBtDeviceInfo(data, data.mNewDevice, 823 BluetoothProfile.STATE_CONNECTED)); 824 } 825 } 826 } 827 } 828 829 /** 830 * Current Bluetooth SCO audio active state indicated by BtHelper via setBluetoothScoOn(). 831 */ 832 private boolean mBluetoothScoOn; 833 setBluetoothScoOn(boolean on, String eventSource)834 /*package*/ void setBluetoothScoOn(boolean on, String eventSource) { 835 if (AudioService.DEBUG_COMM_RTE) { 836 Log.v(TAG, "setBluetoothScoOn: " + on + " " + eventSource); 837 } 838 synchronized (mDeviceStateLock) { 839 mBluetoothScoOn = on; 840 postUpdateCommunicationRouteClient(eventSource); 841 } 842 } 843 startWatchingRoutes(IAudioRoutesObserver observer)844 /*package*/ AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) { 845 synchronized (mDeviceStateLock) { 846 return mDeviceInventory.startWatchingRoutes(observer); 847 } 848 } 849 getCurAudioRoutes()850 /*package*/ AudioRoutesInfo getCurAudioRoutes() { 851 synchronized (mDeviceStateLock) { 852 return mDeviceInventory.getCurAudioRoutes(); 853 } 854 } 855 isAvrcpAbsoluteVolumeSupported()856 /*package*/ boolean isAvrcpAbsoluteVolumeSupported() { 857 synchronized (mDeviceStateLock) { 858 return mBtHelper.isAvrcpAbsoluteVolumeSupported(); 859 } 860 } 861 isBluetoothA2dpOn()862 /*package*/ boolean isBluetoothA2dpOn() { 863 synchronized (mDeviceStateLock) { 864 return mBluetoothA2dpEnabled; 865 } 866 } 867 postSetAvrcpAbsoluteVolumeIndex(int index)868 /*package*/ void postSetAvrcpAbsoluteVolumeIndex(int index) { 869 sendIMsgNoDelay(MSG_I_SET_AVRCP_ABSOLUTE_VOLUME, SENDMSG_REPLACE, index); 870 } 871 postSetHearingAidVolumeIndex(int index, int streamType)872 /*package*/ void postSetHearingAidVolumeIndex(int index, int streamType) { 873 sendIIMsgNoDelay(MSG_II_SET_HEARING_AID_VOLUME, SENDMSG_REPLACE, index, streamType); 874 } 875 postSetLeAudioVolumeIndex(int index, int maxIndex, int streamType)876 /*package*/ void postSetLeAudioVolumeIndex(int index, int maxIndex, int streamType) { 877 BleVolumeInfo info = new BleVolumeInfo(index, maxIndex, streamType); 878 sendLMsgNoDelay(MSG_II_SET_LE_AUDIO_OUT_VOLUME, SENDMSG_REPLACE, info); 879 } 880 postSetModeOwner(int mode, int pid, int uid)881 /*package*/ void postSetModeOwner(int mode, int pid, int uid) { 882 sendLMsgNoDelay(MSG_I_SET_MODE_OWNER, SENDMSG_REPLACE, 883 new AudioModeInfo(mode, pid, uid)); 884 } 885 postBluetoothA2dpDeviceConfigChange(@onNull BluetoothDevice device)886 /*package*/ void postBluetoothA2dpDeviceConfigChange(@NonNull BluetoothDevice device) { 887 sendLMsgNoDelay(MSG_L_A2DP_DEVICE_CONFIG_CHANGE, SENDMSG_QUEUE, device); 888 } 889 startBluetoothScoForClient(IBinder cb, int pid, int scoAudioMode, @NonNull String eventSource)890 /*package*/ void startBluetoothScoForClient(IBinder cb, int pid, int scoAudioMode, 891 @NonNull String eventSource) { 892 893 if (AudioService.DEBUG_COMM_RTE) { 894 Log.v(TAG, "startBluetoothScoForClient_Sync, pid: " + pid); 895 } 896 897 synchronized (mSetModeLock) { 898 synchronized (mDeviceStateLock) { 899 AudioDeviceAttributes device = 900 new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO, ""); 901 902 postSetCommunicationRouteForClient(new CommunicationClientInfo( 903 cb, pid, device, scoAudioMode, eventSource)); 904 } 905 } 906 } 907 stopBluetoothScoForClient( IBinder cb, int pid, @NonNull String eventSource)908 /*package*/ void stopBluetoothScoForClient( 909 IBinder cb, int pid, @NonNull String eventSource) { 910 911 if (AudioService.DEBUG_COMM_RTE) { 912 Log.v(TAG, "stopBluetoothScoForClient_Sync, pid: " + pid); 913 } 914 915 synchronized (mSetModeLock) { 916 synchronized (mDeviceStateLock) { 917 CommunicationRouteClient client = getCommunicationRouteClientForPid(pid); 918 if (client == null || !client.requestsBluetoothSco()) { 919 return; 920 } 921 postSetCommunicationRouteForClient(new CommunicationClientInfo( 922 cb, pid, null, BtHelper.SCO_MODE_UNDEFINED, eventSource)); 923 } 924 } 925 } 926 setPreferredDevicesForStrategySync(int strategy, @NonNull List<AudioDeviceAttributes> devices)927 /*package*/ int setPreferredDevicesForStrategySync(int strategy, 928 @NonNull List<AudioDeviceAttributes> devices) { 929 return mDeviceInventory.setPreferredDevicesForStrategySync(strategy, devices); 930 } 931 removePreferredDevicesForStrategySync(int strategy)932 /*package*/ int removePreferredDevicesForStrategySync(int strategy) { 933 return mDeviceInventory.removePreferredDevicesForStrategySync(strategy); 934 } 935 registerStrategyPreferredDevicesDispatcher( @onNull IStrategyPreferredDevicesDispatcher dispatcher)936 /*package*/ void registerStrategyPreferredDevicesDispatcher( 937 @NonNull IStrategyPreferredDevicesDispatcher dispatcher) { 938 mDeviceInventory.registerStrategyPreferredDevicesDispatcher(dispatcher); 939 } 940 unregisterStrategyPreferredDevicesDispatcher( @onNull IStrategyPreferredDevicesDispatcher dispatcher)941 /*package*/ void unregisterStrategyPreferredDevicesDispatcher( 942 @NonNull IStrategyPreferredDevicesDispatcher dispatcher) { 943 mDeviceInventory.unregisterStrategyPreferredDevicesDispatcher(dispatcher); 944 } 945 setPreferredDevicesForCapturePresetSync(int capturePreset, @NonNull List<AudioDeviceAttributes> devices)946 /*package*/ int setPreferredDevicesForCapturePresetSync(int capturePreset, 947 @NonNull List<AudioDeviceAttributes> devices) { 948 return mDeviceInventory.setPreferredDevicesForCapturePresetSync(capturePreset, devices); 949 } 950 clearPreferredDevicesForCapturePresetSync(int capturePreset)951 /*package*/ int clearPreferredDevicesForCapturePresetSync(int capturePreset) { 952 return mDeviceInventory.clearPreferredDevicesForCapturePresetSync(capturePreset); 953 } 954 registerCapturePresetDevicesRoleDispatcher( @onNull ICapturePresetDevicesRoleDispatcher dispatcher)955 /*package*/ void registerCapturePresetDevicesRoleDispatcher( 956 @NonNull ICapturePresetDevicesRoleDispatcher dispatcher) { 957 mDeviceInventory.registerCapturePresetDevicesRoleDispatcher(dispatcher); 958 } 959 unregisterCapturePresetDevicesRoleDispatcher( @onNull ICapturePresetDevicesRoleDispatcher dispatcher)960 /*package*/ void unregisterCapturePresetDevicesRoleDispatcher( 961 @NonNull ICapturePresetDevicesRoleDispatcher dispatcher) { 962 mDeviceInventory.unregisterCapturePresetDevicesRoleDispatcher(dispatcher); 963 } 964 registerCommunicationDeviceDispatcher( @onNull ICommunicationDeviceDispatcher dispatcher)965 /*package*/ void registerCommunicationDeviceDispatcher( 966 @NonNull ICommunicationDeviceDispatcher dispatcher) { 967 mCommDevDispatchers.register(dispatcher); 968 } 969 unregisterCommunicationDeviceDispatcher( @onNull ICommunicationDeviceDispatcher dispatcher)970 /*package*/ void unregisterCommunicationDeviceDispatcher( 971 @NonNull ICommunicationDeviceDispatcher dispatcher) { 972 mCommDevDispatchers.unregister(dispatcher); 973 } 974 975 // Monitoring of communication device 976 final RemoteCallbackList<ICommunicationDeviceDispatcher> mCommDevDispatchers = 977 new RemoteCallbackList<ICommunicationDeviceDispatcher>(); 978 979 // portId of the device currently selected for communication: avoids broadcasting changes 980 // when same communication route is applied 981 @GuardedBy("mDeviceStateLock") 982 int mCurCommunicationPortId = -1; 983 984 @GuardedBy("mDeviceStateLock") dispatchCommunicationDevice()985 private void dispatchCommunicationDevice() { 986 AudioDeviceInfo device = getCommunicationDevice(); 987 int portId = device != null ? device.getId() : 0; 988 if (portId == mCurCommunicationPortId) { 989 return; 990 } 991 mCurCommunicationPortId = portId; 992 993 final int nbDispatchers = mCommDevDispatchers.beginBroadcast(); 994 for (int i = 0; i < nbDispatchers; i++) { 995 try { 996 mCommDevDispatchers.getBroadcastItem(i) 997 .dispatchCommunicationDeviceChanged(portId); 998 } catch (RemoteException e) { 999 } 1000 } 1001 mCommDevDispatchers.finishBroadcast(); 1002 } 1003 1004 1005 //--------------------------------------------------------------------- 1006 // Communication with (to) AudioService 1007 //TODO check whether the AudioService methods are candidates to move here postAccessoryPlugMediaUnmute(int device)1008 /*package*/ void postAccessoryPlugMediaUnmute(int device) { 1009 mAudioService.postAccessoryPlugMediaUnmute(device); 1010 } 1011 getVssVolumeForDevice(int streamType, int device)1012 /*package*/ int getVssVolumeForDevice(int streamType, int device) { 1013 return mAudioService.getVssVolumeForDevice(streamType, device); 1014 } 1015 getMaxVssVolumeForStream(int streamType)1016 /*package*/ int getMaxVssVolumeForStream(int streamType) { 1017 return mAudioService.getMaxVssVolumeForStream(streamType); 1018 } 1019 getDeviceForStream(int streamType)1020 /*package*/ int getDeviceForStream(int streamType) { 1021 return mAudioService.getDeviceForStream(streamType); 1022 } 1023 postApplyVolumeOnDevice(int streamType, int device, String caller)1024 /*package*/ void postApplyVolumeOnDevice(int streamType, int device, String caller) { 1025 mAudioService.postApplyVolumeOnDevice(streamType, device, caller); 1026 } 1027 postSetVolumeIndexOnDevice(int streamType, int vssVolIndex, int device, String caller)1028 /*package*/ void postSetVolumeIndexOnDevice(int streamType, int vssVolIndex, int device, 1029 String caller) { 1030 mAudioService.postSetVolumeIndexOnDevice(streamType, vssVolIndex, device, caller); 1031 } 1032 postObserveDevicesForAllStreams()1033 /*packages*/ void postObserveDevicesForAllStreams() { 1034 mAudioService.postObserveDevicesForAllStreams(); 1035 } 1036 isInCommunication()1037 /*package*/ boolean isInCommunication() { 1038 return mAudioService.isInCommunication(); 1039 } 1040 hasMediaDynamicPolicy()1041 /*package*/ boolean hasMediaDynamicPolicy() { 1042 return mAudioService.hasMediaDynamicPolicy(); 1043 } 1044 getContentResolver()1045 /*package*/ ContentResolver getContentResolver() { 1046 return mAudioService.getContentResolver(); 1047 } 1048 checkMusicActive(int deviceType, String caller)1049 /*package*/ void checkMusicActive(int deviceType, String caller) { 1050 mAudioService.checkMusicActive(deviceType, caller); 1051 } 1052 checkVolumeCecOnHdmiConnection( @udioService.ConnectionState int state, String caller)1053 /*package*/ void checkVolumeCecOnHdmiConnection( 1054 @AudioService.ConnectionState int state, String caller) { 1055 mAudioService.postCheckVolumeCecOnHdmiConnection(state, caller); 1056 } 1057 hasAudioFocusUsers()1058 /*package*/ boolean hasAudioFocusUsers() { 1059 return mAudioService.hasAudioFocusUsers(); 1060 } 1061 1062 //--------------------------------------------------------------------- 1063 // Message handling on behalf of helper classes postBroadcastScoConnectionState(int state)1064 /*package*/ void postBroadcastScoConnectionState(int state) { 1065 sendIMsgNoDelay(MSG_I_BROADCAST_BT_CONNECTION_STATE, SENDMSG_QUEUE, state); 1066 } 1067 postBroadcastBecomingNoisy()1068 /*package*/ void postBroadcastBecomingNoisy() { 1069 sendMsgNoDelay(MSG_BROADCAST_AUDIO_BECOMING_NOISY, SENDMSG_REPLACE); 1070 } 1071 1072 @GuardedBy("mDeviceStateLock") postBluetoothActiveDevice(BtDeviceInfo info, int delay)1073 /*package*/ void postBluetoothActiveDevice(BtDeviceInfo info, int delay) { 1074 sendLMsg(MSG_L_SET_BT_ACTIVE_DEVICE, SENDMSG_QUEUE, info, delay); 1075 } 1076 postSetWiredDeviceConnectionState( AudioDeviceInventory.WiredDeviceConnectionState connectionState, int delay)1077 /*package*/ void postSetWiredDeviceConnectionState( 1078 AudioDeviceInventory.WiredDeviceConnectionState connectionState, int delay) { 1079 sendLMsg(MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE, SENDMSG_QUEUE, connectionState, delay); 1080 } 1081 postBtProfileDisconnected(int profile)1082 /*package*/ void postBtProfileDisconnected(int profile) { 1083 sendIMsgNoDelay(MSG_I_BT_SERVICE_DISCONNECTED_PROFILE, SENDMSG_QUEUE, profile); 1084 } 1085 postBtProfileConnected(int profile, BluetoothProfile proxy)1086 /*package*/ void postBtProfileConnected(int profile, BluetoothProfile proxy) { 1087 sendILMsgNoDelay(MSG_IL_BT_SERVICE_CONNECTED_PROFILE, SENDMSG_QUEUE, profile, proxy); 1088 } 1089 postCommunicationRouteClientDied(CommunicationRouteClient client)1090 /*package*/ void postCommunicationRouteClientDied(CommunicationRouteClient client) { 1091 sendLMsgNoDelay(MSG_L_COMMUNICATION_ROUTE_CLIENT_DIED, SENDMSG_QUEUE, client); 1092 } 1093 postSaveSetPreferredDevicesForStrategy(int strategy, List<AudioDeviceAttributes> devices)1094 /*package*/ void postSaveSetPreferredDevicesForStrategy(int strategy, 1095 List<AudioDeviceAttributes> devices) 1096 { 1097 sendILMsgNoDelay(MSG_IL_SAVE_PREF_DEVICES_FOR_STRATEGY, SENDMSG_QUEUE, strategy, devices); 1098 } 1099 postSaveRemovePreferredDevicesForStrategy(int strategy)1100 /*package*/ void postSaveRemovePreferredDevicesForStrategy(int strategy) { 1101 sendIMsgNoDelay(MSG_I_SAVE_REMOVE_PREF_DEVICES_FOR_STRATEGY, SENDMSG_QUEUE, strategy); 1102 } 1103 postSaveSetPreferredDevicesForCapturePreset( int capturePreset, List<AudioDeviceAttributes> devices)1104 /*package*/ void postSaveSetPreferredDevicesForCapturePreset( 1105 int capturePreset, List<AudioDeviceAttributes> devices) { 1106 sendILMsgNoDelay( 1107 MSG_IL_SAVE_PREF_DEVICES_FOR_CAPTURE_PRESET, SENDMSG_QUEUE, capturePreset, devices); 1108 } 1109 postSaveClearPreferredDevicesForCapturePreset(int capturePreset)1110 /*package*/ void postSaveClearPreferredDevicesForCapturePreset(int capturePreset) { 1111 sendIMsgNoDelay( 1112 MSG_I_SAVE_CLEAR_PREF_DEVICES_FOR_CAPTURE_PRESET, SENDMSG_QUEUE, capturePreset); 1113 } 1114 postUpdateCommunicationRouteClient(String eventSource)1115 /*package*/ void postUpdateCommunicationRouteClient(String eventSource) { 1116 sendLMsgNoDelay(MSG_L_UPDATE_COMMUNICATION_ROUTE_CLIENT, SENDMSG_QUEUE, eventSource); 1117 } 1118 postSetCommunicationRouteForClient(CommunicationClientInfo info)1119 /*package*/ void postSetCommunicationRouteForClient(CommunicationClientInfo info) { 1120 sendLMsgNoDelay(MSG_L_SET_COMMUNICATION_ROUTE_FOR_CLIENT, SENDMSG_QUEUE, info); 1121 } 1122 postScoAudioStateChanged(int state)1123 /*package*/ void postScoAudioStateChanged(int state) { 1124 sendIMsgNoDelay(MSG_I_SCO_AUDIO_STATE_CHANGED, SENDMSG_QUEUE, state); 1125 } 1126 1127 /*package*/ static final class CommunicationClientInfo { 1128 final @NonNull IBinder mCb; 1129 final int mPid; 1130 final @NonNull AudioDeviceAttributes mDevice; 1131 final int mScoAudioMode; 1132 final @NonNull String mEventSource; 1133 CommunicationClientInfo(@onNull IBinder cb, int pid, @NonNull AudioDeviceAttributes device, int scoAudioMode, @NonNull String eventSource)1134 CommunicationClientInfo(@NonNull IBinder cb, int pid, @NonNull AudioDeviceAttributes device, 1135 int scoAudioMode, @NonNull String eventSource) { 1136 mCb = cb; 1137 mPid = pid; 1138 mDevice = device; 1139 mScoAudioMode = scoAudioMode; 1140 mEventSource = eventSource; 1141 } 1142 1143 // redefine equality op so we can match messages intended for this client 1144 @Override equals(Object o)1145 public boolean equals(Object o) { 1146 if (o == null) { 1147 return false; 1148 } 1149 if (this == o) { 1150 return true; 1151 } 1152 if (!(o instanceof CommunicationClientInfo)) { 1153 return false; 1154 } 1155 1156 return mCb.equals(((CommunicationClientInfo) o).mCb) 1157 && mPid == ((CommunicationClientInfo) o).mPid; 1158 } 1159 1160 @Override toString()1161 public String toString() { 1162 return "CommunicationClientInfo mCb=" + mCb.toString() 1163 +"mPid=" + mPid 1164 +"mDevice=" + mDevice.toString() 1165 +"mScoAudioMode=" + mScoAudioMode 1166 +"mEventSource=" + mEventSource; 1167 } 1168 } 1169 1170 //--------------------------------------------------------------------- 1171 // Method forwarding between the helper classes (BtHelper, AudioDeviceInventory) 1172 // only call from a "handle"* method or "on"* method 1173 1174 // Handles request to override default use of A2DP for media. 1175 //@GuardedBy("mConnectedDevices") setBluetoothA2dpOnInt(boolean on, boolean fromA2dp, String source)1176 /*package*/ void setBluetoothA2dpOnInt(boolean on, boolean fromA2dp, String source) { 1177 // for logging only 1178 final String eventSource = new StringBuilder("setBluetoothA2dpOn(").append(on) 1179 .append(") from u/pid:").append(Binder.getCallingUid()).append("/") 1180 .append(Binder.getCallingPid()).append(" src:").append(source).toString(); 1181 1182 synchronized (mDeviceStateLock) { 1183 mBluetoothA2dpEnabled = on; 1184 mBrokerHandler.removeMessages(MSG_IIL_SET_FORCE_BT_A2DP_USE); 1185 onSetForceUse( 1186 AudioSystem.FOR_MEDIA, 1187 mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP, 1188 fromA2dp, 1189 eventSource); 1190 } 1191 } 1192 handleDeviceConnection(AudioDeviceAttributes attributes, boolean connect)1193 /*package*/ boolean handleDeviceConnection(AudioDeviceAttributes attributes, boolean connect) { 1194 synchronized (mDeviceStateLock) { 1195 return mDeviceInventory.handleDeviceConnection(attributes, connect, false /*for test*/); 1196 } 1197 } 1198 handleFailureToConnectToBtHeadsetService(int delay)1199 /*package*/ void handleFailureToConnectToBtHeadsetService(int delay) { 1200 sendMsg(MSG_BT_HEADSET_CNCT_FAILED, SENDMSG_REPLACE, delay); 1201 } 1202 handleCancelFailureToConnectToBtHeadsetService()1203 /*package*/ void handleCancelFailureToConnectToBtHeadsetService() { 1204 mBrokerHandler.removeMessages(MSG_BT_HEADSET_CNCT_FAILED); 1205 } 1206 postReportNewRoutes(boolean fromA2dp)1207 /*package*/ void postReportNewRoutes(boolean fromA2dp) { 1208 sendMsgNoDelay(fromA2dp ? MSG_REPORT_NEW_ROUTES_A2DP : MSG_REPORT_NEW_ROUTES, SENDMSG_NOOP); 1209 } 1210 1211 // must be called synchronized on mConnectedDevices hasScheduledA2dpConnection(BluetoothDevice btDevice)1212 /*package*/ boolean hasScheduledA2dpConnection(BluetoothDevice btDevice) { 1213 final BtDeviceInfo devInfoToCheck = new BtDeviceInfo(btDevice, BluetoothProfile.A2DP); 1214 return mBrokerHandler.hasEqualMessages(MSG_L_SET_BT_ACTIVE_DEVICE, devInfoToCheck); 1215 } 1216 setA2dpTimeout(String address, int a2dpCodec, int delayMs)1217 /*package*/ void setA2dpTimeout(String address, int a2dpCodec, int delayMs) { 1218 sendILMsg(MSG_IL_BTA2DP_TIMEOUT, SENDMSG_QUEUE, a2dpCodec, address, delayMs); 1219 } 1220 setLeAudioTimeout(String address, int device, int delayMs)1221 /*package*/ void setLeAudioTimeout(String address, int device, int delayMs) { 1222 sendILMsg(MSG_IL_BTLEAUDIO_TIMEOUT, SENDMSG_QUEUE, device, address, delayMs); 1223 } 1224 setAvrcpAbsoluteVolumeSupported(boolean supported)1225 /*package*/ void setAvrcpAbsoluteVolumeSupported(boolean supported) { 1226 synchronized (mDeviceStateLock) { 1227 mBtHelper.setAvrcpAbsoluteVolumeSupported(supported); 1228 } 1229 } 1230 clearAvrcpAbsoluteVolumeSupported()1231 /*package*/ void clearAvrcpAbsoluteVolumeSupported() { 1232 setAvrcpAbsoluteVolumeSupported(false); 1233 mAudioService.setAvrcpAbsoluteVolumeSupported(false); 1234 } 1235 getBluetoothA2dpEnabled()1236 /*package*/ boolean getBluetoothA2dpEnabled() { 1237 synchronized (mDeviceStateLock) { 1238 return mBluetoothA2dpEnabled; 1239 } 1240 } 1241 broadcastStickyIntentToCurrentProfileGroup(Intent intent)1242 /*package*/ void broadcastStickyIntentToCurrentProfileGroup(Intent intent) { 1243 mSystemServer.broadcastStickyIntentToCurrentProfileGroup(intent); 1244 } 1245 dump(PrintWriter pw, String prefix)1246 /*package*/ void dump(PrintWriter pw, String prefix) { 1247 if (mBrokerHandler != null) { 1248 pw.println(prefix + "Message handler (watch for unhandled messages):"); 1249 mBrokerHandler.dump(new PrintWriterPrinter(pw), prefix + " "); 1250 } else { 1251 pw.println("Message handler is null"); 1252 } 1253 1254 mDeviceInventory.dump(pw, prefix); 1255 1256 pw.println("\n" + prefix + "Communication route clients:"); 1257 mCommunicationRouteClients.forEach((cl) -> { 1258 pw.println(" " + prefix + "pid: " + cl.getPid() + " device: " 1259 + cl.getDevice() + " cb: " + cl.getBinder()); }); 1260 1261 pw.println("\n" + prefix + "Computed Preferred communication device: " 1262 + preferredCommunicationDevice()); 1263 pw.println("\n" + prefix + "Applied Preferred communication device: " 1264 + mPreferredCommunicationDevice); 1265 pw.println(prefix + "Active communication device: " 1266 + ((mActiveCommunicationDevice == null) ? "None" 1267 : new AudioDeviceAttributes(mActiveCommunicationDevice))); 1268 1269 pw.println(prefix + "mCommunicationStrategyId: " 1270 + mCommunicationStrategyId); 1271 1272 pw.println(prefix + "mAccessibilityStrategyId: " 1273 + mAccessibilityStrategyId); 1274 1275 pw.println("\n" + prefix + "mAudioModeOwner: " + mAudioModeOwner); 1276 1277 mBtHelper.dump(pw, prefix); 1278 } 1279 1280 //--------------------------------------------------------------------- 1281 // Internal handling of messages 1282 // These methods are ALL synchronous, in response to message handling in BrokerHandler 1283 // Blocking in any of those will block the message queue 1284 onSetForceUse(int useCase, int config, boolean fromA2dp, String eventSource)1285 private void onSetForceUse(int useCase, int config, boolean fromA2dp, String eventSource) { 1286 if (useCase == AudioSystem.FOR_MEDIA) { 1287 postReportNewRoutes(fromA2dp); 1288 } 1289 AudioService.sForceUseLogger.log( 1290 new AudioServiceEvents.ForceUseEvent(useCase, config, eventSource)); 1291 new MediaMetrics.Item(MediaMetrics.Name.AUDIO_FORCE_USE + MediaMetrics.SEPARATOR 1292 + AudioSystem.forceUseUsageToString(useCase)) 1293 .set(MediaMetrics.Property.EVENT, "onSetForceUse") 1294 .set(MediaMetrics.Property.FORCE_USE_DUE_TO, eventSource) 1295 .set(MediaMetrics.Property.FORCE_USE_MODE, 1296 AudioSystem.forceUseConfigToString(config)) 1297 .record(); 1298 1299 if (AudioService.DEBUG_COMM_RTE) { 1300 Log.v(TAG, "onSetForceUse(useCase<" + useCase + ">, config<" + config + ">, fromA2dp<" 1301 + fromA2dp + ">, eventSource<" + eventSource + ">)"); 1302 } 1303 mAudioSystem.setForceUse(useCase, config); 1304 } 1305 onSendBecomingNoisyIntent()1306 private void onSendBecomingNoisyIntent() { 1307 AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent( 1308 "broadcast ACTION_AUDIO_BECOMING_NOISY")).printLog(TAG)); 1309 mSystemServer.sendDeviceBecomingNoisyIntent(); 1310 } 1311 1312 //--------------------------------------------------------------------- 1313 // Message handling 1314 private BrokerHandler mBrokerHandler; 1315 private BrokerThread mBrokerThread; 1316 private PowerManager.WakeLock mBrokerEventWakeLock; 1317 setupMessaging(Context ctxt)1318 private void setupMessaging(Context ctxt) { 1319 final PowerManager pm = (PowerManager) ctxt.getSystemService(Context.POWER_SERVICE); 1320 mBrokerEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 1321 "handleAudioDeviceEvent"); 1322 mBrokerThread = new BrokerThread(); 1323 mBrokerThread.start(); 1324 waitForBrokerHandlerCreation(); 1325 } 1326 waitForBrokerHandlerCreation()1327 private void waitForBrokerHandlerCreation() { 1328 synchronized (this) { 1329 while (mBrokerHandler == null) { 1330 try { 1331 wait(); 1332 } catch (InterruptedException e) { 1333 Log.e(TAG, "Interruption while waiting on BrokerHandler"); 1334 } 1335 } 1336 } 1337 } 1338 1339 /** Class that handles the device broker's message queue */ 1340 private class BrokerThread extends Thread { BrokerThread()1341 BrokerThread() { 1342 super("AudioDeviceBroker"); 1343 } 1344 1345 @Override run()1346 public void run() { 1347 // Set this thread up so the handler will work on it 1348 Looper.prepare(); 1349 1350 synchronized (AudioDeviceBroker.this) { 1351 mBrokerHandler = new BrokerHandler(); 1352 1353 // Notify that the handler has been created 1354 AudioDeviceBroker.this.notify(); 1355 } 1356 1357 Looper.loop(); 1358 } 1359 } 1360 1361 /** Class that handles the message queue */ 1362 private class BrokerHandler extends Handler { 1363 1364 @Override handleMessage(Message msg)1365 public void handleMessage(Message msg) { 1366 switch (msg.what) { 1367 case MSG_RESTORE_DEVICES: 1368 synchronized (mSetModeLock) { 1369 synchronized (mDeviceStateLock) { 1370 initRoutingStrategyIds(); 1371 updateActiveCommunicationDevice(); 1372 mDeviceInventory.onRestoreDevices(); 1373 mBtHelper.onAudioServerDiedRestoreA2dp(); 1374 onUpdateCommunicationRoute("MSG_RESTORE_DEVICES"); 1375 } 1376 } 1377 break; 1378 case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE: 1379 synchronized (mDeviceStateLock) { 1380 mDeviceInventory.onSetWiredDeviceConnectionState( 1381 (AudioDeviceInventory.WiredDeviceConnectionState) msg.obj); 1382 } 1383 break; 1384 case MSG_I_BROADCAST_BT_CONNECTION_STATE: 1385 synchronized (mDeviceStateLock) { 1386 mBtHelper.onBroadcastScoConnectionState(msg.arg1); 1387 } 1388 break; 1389 case MSG_IIL_SET_FORCE_USE: // intended fall-through 1390 case MSG_IIL_SET_FORCE_BT_A2DP_USE: 1391 onSetForceUse(msg.arg1, msg.arg2, 1392 (msg.what == MSG_IIL_SET_FORCE_BT_A2DP_USE), (String) msg.obj); 1393 break; 1394 case MSG_REPORT_NEW_ROUTES: 1395 case MSG_REPORT_NEW_ROUTES_A2DP: 1396 synchronized (mDeviceStateLock) { 1397 mDeviceInventory.onReportNewRoutes(); 1398 } 1399 break; 1400 case MSG_L_SET_BT_ACTIVE_DEVICE: 1401 synchronized (mSetModeLock) { 1402 synchronized (mDeviceStateLock) { 1403 BtDeviceInfo btInfo = (BtDeviceInfo) msg.obj; 1404 mDeviceInventory.onSetBtActiveDevice(btInfo, 1405 (btInfo.mProfile 1406 != BluetoothProfile.LE_AUDIO || btInfo.mIsLeOutput) 1407 ? mAudioService.getBluetoothContextualVolumeStream() 1408 : AudioSystem.STREAM_DEFAULT); 1409 if (btInfo.mProfile == BluetoothProfile.LE_AUDIO 1410 || btInfo.mProfile == BluetoothProfile.HEARING_AID) { 1411 onUpdateCommunicationRouteClient("setBluetoothActiveDevice"); 1412 } 1413 } 1414 } 1415 break; 1416 case MSG_BT_HEADSET_CNCT_FAILED: 1417 synchronized (mSetModeLock) { 1418 synchronized (mDeviceStateLock) { 1419 mBtHelper.resetBluetoothSco(); 1420 } 1421 } 1422 break; 1423 case MSG_IL_BTA2DP_TIMEOUT: 1424 // msg.obj == address of BTA2DP device 1425 synchronized (mDeviceStateLock) { 1426 mDeviceInventory.onMakeA2dpDeviceUnavailableNow((String) msg.obj, msg.arg1); 1427 } 1428 break; 1429 case MSG_IL_BTLEAUDIO_TIMEOUT: 1430 // msg.obj == address of LE Audio device 1431 synchronized (mDeviceStateLock) { 1432 mDeviceInventory.onMakeLeAudioDeviceUnavailableNow( 1433 (String) msg.obj, msg.arg1); 1434 } 1435 break; 1436 case MSG_L_A2DP_DEVICE_CONFIG_CHANGE: 1437 final BluetoothDevice btDevice = (BluetoothDevice) msg.obj; 1438 synchronized (mDeviceStateLock) { 1439 final int a2dpCodec = mBtHelper.getA2dpCodec(btDevice); 1440 mDeviceInventory.onBluetoothA2dpDeviceConfigChange( 1441 new BtHelper.BluetoothA2dpDeviceInfo(btDevice, -1, a2dpCodec), 1442 BtHelper.EVENT_DEVICE_CONFIG_CHANGE); 1443 } 1444 break; 1445 case MSG_BROADCAST_AUDIO_BECOMING_NOISY: 1446 onSendBecomingNoisyIntent(); 1447 break; 1448 case MSG_II_SET_HEARING_AID_VOLUME: 1449 synchronized (mDeviceStateLock) { 1450 mBtHelper.setHearingAidVolume(msg.arg1, msg.arg2, 1451 mDeviceInventory.isHearingAidConnected()); 1452 } 1453 break; 1454 case MSG_II_SET_LE_AUDIO_OUT_VOLUME: { 1455 final BleVolumeInfo info = (BleVolumeInfo) msg.obj; 1456 synchronized (mDeviceStateLock) { 1457 mBtHelper.setLeAudioVolume(info.mIndex, info.mMaxIndex, info.mStreamType); 1458 } 1459 } break; 1460 case MSG_I_SET_AVRCP_ABSOLUTE_VOLUME: 1461 synchronized (mDeviceStateLock) { 1462 mBtHelper.setAvrcpAbsoluteVolumeIndex(msg.arg1); 1463 } 1464 break; 1465 case MSG_I_SET_MODE_OWNER: 1466 synchronized (mSetModeLock) { 1467 synchronized (mDeviceStateLock) { 1468 mAudioModeOwner = (AudioModeInfo) msg.obj; 1469 if (mAudioModeOwner.mMode != AudioSystem.MODE_RINGTONE) { 1470 onUpdateCommunicationRouteClient("setNewModeOwner"); 1471 } 1472 } 1473 } 1474 break; 1475 1476 case MSG_L_SET_COMMUNICATION_ROUTE_FOR_CLIENT: 1477 synchronized (mSetModeLock) { 1478 synchronized (mDeviceStateLock) { 1479 CommunicationClientInfo info = (CommunicationClientInfo) msg.obj; 1480 setCommunicationRouteForClient(info.mCb, info.mPid, info.mDevice, 1481 info.mScoAudioMode, info.mEventSource); 1482 } 1483 } 1484 break; 1485 1486 case MSG_L_UPDATE_COMMUNICATION_ROUTE_CLIENT: 1487 synchronized (mSetModeLock) { 1488 synchronized (mDeviceStateLock) { 1489 onUpdateCommunicationRouteClient((String) msg.obj); 1490 } 1491 } 1492 break; 1493 1494 case MSG_L_UPDATE_COMMUNICATION_ROUTE: 1495 synchronized (mSetModeLock) { 1496 synchronized (mDeviceStateLock) { 1497 onUpdateCommunicationRoute((String) msg.obj); 1498 } 1499 } 1500 break; 1501 1502 case MSG_L_COMMUNICATION_ROUTE_CLIENT_DIED: 1503 synchronized (mSetModeLock) { 1504 synchronized (mDeviceStateLock) { 1505 onCommunicationRouteClientDied((CommunicationRouteClient) msg.obj); 1506 } 1507 } 1508 break; 1509 1510 case MSG_I_SCO_AUDIO_STATE_CHANGED: 1511 synchronized (mSetModeLock) { 1512 synchronized (mDeviceStateLock) { 1513 mBtHelper.onScoAudioStateChanged(msg.arg1); 1514 } 1515 } 1516 break; 1517 1518 case MSG_TOGGLE_HDMI: 1519 synchronized (mDeviceStateLock) { 1520 mDeviceInventory.onToggleHdmi(); 1521 } 1522 break; 1523 case MSG_I_BT_SERVICE_DISCONNECTED_PROFILE: 1524 if (msg.arg1 != BluetoothProfile.HEADSET) { 1525 synchronized (mDeviceStateLock) { 1526 mBtHelper.onBtProfileDisconnected(msg.arg1); 1527 mDeviceInventory.onBtProfileDisconnected(msg.arg1); 1528 } 1529 } else { 1530 synchronized (mSetModeLock) { 1531 synchronized (mDeviceStateLock) { 1532 mBtHelper.disconnectHeadset(); 1533 } 1534 } 1535 } 1536 break; 1537 case MSG_IL_BT_SERVICE_CONNECTED_PROFILE: 1538 if (msg.arg1 != BluetoothProfile.HEADSET) { 1539 synchronized (mDeviceStateLock) { 1540 mBtHelper.onBtProfileConnected(msg.arg1, (BluetoothProfile) msg.obj); 1541 } 1542 } else { 1543 synchronized (mSetModeLock) { 1544 synchronized (mDeviceStateLock) { 1545 mBtHelper.onHeadsetProfileConnected((BluetoothHeadset) msg.obj); 1546 } 1547 } 1548 } 1549 break; 1550 case MSG_L_BT_ACTIVE_DEVICE_CHANGE_EXT: { 1551 final BtDeviceInfo info = (BtDeviceInfo) msg.obj; 1552 if (info.mDevice == null) break; 1553 AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent( 1554 "msg: onBluetoothActiveDeviceChange " 1555 + " state=" + info.mState 1556 // only querying address as this is the only readily available 1557 // field on the device 1558 + " addr=" + info.mDevice.getAddress() 1559 + " prof=" + info.mProfile 1560 + " supprNoisy=" + info.mSupprNoisy 1561 + " src=" + info.mEventSource 1562 )).printLog(TAG)); 1563 synchronized (mDeviceStateLock) { 1564 mDeviceInventory.setBluetoothActiveDevice(info); 1565 } 1566 } break; 1567 case MSG_IL_SAVE_PREF_DEVICES_FOR_STRATEGY: { 1568 final int strategy = msg.arg1; 1569 final List<AudioDeviceAttributes> devices = 1570 (List<AudioDeviceAttributes>) msg.obj; 1571 mDeviceInventory.onSaveSetPreferredDevices(strategy, devices); 1572 } break; 1573 case MSG_I_SAVE_REMOVE_PREF_DEVICES_FOR_STRATEGY: { 1574 final int strategy = msg.arg1; 1575 mDeviceInventory.onSaveRemovePreferredDevices(strategy); 1576 } break; 1577 case MSG_CHECK_MUTE_MUSIC: 1578 checkMessagesMuteMusic(0); 1579 break; 1580 case MSG_IL_SAVE_PREF_DEVICES_FOR_CAPTURE_PRESET: { 1581 final int capturePreset = msg.arg1; 1582 final List<AudioDeviceAttributes> devices = 1583 (List<AudioDeviceAttributes>) msg.obj; 1584 mDeviceInventory.onSaveSetPreferredDevicesForCapturePreset( 1585 capturePreset, devices); 1586 } break; 1587 case MSG_I_SAVE_CLEAR_PREF_DEVICES_FOR_CAPTURE_PRESET: { 1588 final int capturePreset = msg.arg1; 1589 mDeviceInventory.onSaveClearPreferredDevicesForCapturePreset(capturePreset); 1590 } break; 1591 default: 1592 Log.wtf(TAG, "Invalid message " + msg.what); 1593 } 1594 1595 // Give some time to Bluetooth service to post a connection message 1596 // in case of active device switch 1597 if (MESSAGES_MUTE_MUSIC.contains(msg.what)) { 1598 sendMsg(MSG_CHECK_MUTE_MUSIC, SENDMSG_REPLACE, BTA2DP_MUTE_CHECK_DELAY_MS); 1599 } 1600 1601 if (isMessageHandledUnderWakelock(msg.what)) { 1602 try { 1603 mBrokerEventWakeLock.release(); 1604 } catch (Exception e) { 1605 Log.e(TAG, "Exception releasing wakelock", e); 1606 } 1607 } 1608 } 1609 } 1610 1611 // List of all messages. If a message has be handled under wakelock, add it to 1612 // the isMessageHandledUnderWakelock(int) method 1613 // Naming of msg indicates arguments, using JNI argument grammar 1614 // (e.g. II indicates two int args, IL indicates int and Obj arg) 1615 private static final int MSG_RESTORE_DEVICES = 1; 1616 private static final int MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE = 2; 1617 private static final int MSG_I_BROADCAST_BT_CONNECTION_STATE = 3; 1618 private static final int MSG_IIL_SET_FORCE_USE = 4; 1619 private static final int MSG_IIL_SET_FORCE_BT_A2DP_USE = 5; 1620 private static final int MSG_TOGGLE_HDMI = 6; 1621 private static final int MSG_L_SET_BT_ACTIVE_DEVICE = 7; 1622 private static final int MSG_BT_HEADSET_CNCT_FAILED = 9; 1623 private static final int MSG_IL_BTA2DP_TIMEOUT = 10; 1624 1625 // process change of A2DP device configuration, obj is BluetoothDevice 1626 private static final int MSG_L_A2DP_DEVICE_CONFIG_CHANGE = 11; 1627 1628 private static final int MSG_BROADCAST_AUDIO_BECOMING_NOISY = 12; 1629 private static final int MSG_REPORT_NEW_ROUTES = 13; 1630 private static final int MSG_II_SET_HEARING_AID_VOLUME = 14; 1631 private static final int MSG_I_SET_AVRCP_ABSOLUTE_VOLUME = 15; 1632 private static final int MSG_I_SET_MODE_OWNER = 16; 1633 1634 private static final int MSG_I_BT_SERVICE_DISCONNECTED_PROFILE = 22; 1635 private static final int MSG_IL_BT_SERVICE_CONNECTED_PROFILE = 23; 1636 1637 // process external command to (dis)connect an A2DP device, obj is BtDeviceConnectionInfo 1638 private static final int MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT = 29; 1639 1640 // process external command to (dis)connect a hearing aid device 1641 private static final int MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT = 31; 1642 1643 private static final int MSG_IL_SAVE_PREF_DEVICES_FOR_STRATEGY = 32; 1644 private static final int MSG_I_SAVE_REMOVE_PREF_DEVICES_FOR_STRATEGY = 33; 1645 1646 private static final int MSG_L_COMMUNICATION_ROUTE_CLIENT_DIED = 34; 1647 private static final int MSG_CHECK_MUTE_MUSIC = 35; 1648 private static final int MSG_REPORT_NEW_ROUTES_A2DP = 36; 1649 1650 private static final int MSG_IL_SAVE_PREF_DEVICES_FOR_CAPTURE_PRESET = 37; 1651 private static final int MSG_I_SAVE_CLEAR_PREF_DEVICES_FOR_CAPTURE_PRESET = 38; 1652 1653 private static final int MSG_L_UPDATE_COMMUNICATION_ROUTE = 39; 1654 private static final int MSG_L_SET_COMMUNICATION_ROUTE_FOR_CLIENT = 42; 1655 private static final int MSG_L_UPDATE_COMMUNICATION_ROUTE_CLIENT = 43; 1656 private static final int MSG_I_SCO_AUDIO_STATE_CHANGED = 44; 1657 1658 private static final int MSG_L_BT_ACTIVE_DEVICE_CHANGE_EXT = 45; 1659 // 1660 // process set volume for Le Audio, obj is BleVolumeInfo 1661 private static final int MSG_II_SET_LE_AUDIO_OUT_VOLUME = 46; 1662 1663 private static final int MSG_IL_BTLEAUDIO_TIMEOUT = 49; 1664 isMessageHandledUnderWakelock(int msgId)1665 private static boolean isMessageHandledUnderWakelock(int msgId) { 1666 switch(msgId) { 1667 case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE: 1668 case MSG_L_SET_BT_ACTIVE_DEVICE: 1669 case MSG_IL_BTA2DP_TIMEOUT: 1670 case MSG_IL_BTLEAUDIO_TIMEOUT: 1671 case MSG_L_A2DP_DEVICE_CONFIG_CHANGE: 1672 case MSG_TOGGLE_HDMI: 1673 case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT: 1674 case MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT: 1675 case MSG_CHECK_MUTE_MUSIC: 1676 return true; 1677 default: 1678 return false; 1679 } 1680 } 1681 1682 // Message helper methods 1683 1684 // sendMsg() flags 1685 /** If the msg is already queued, replace it with this one. */ 1686 private static final int SENDMSG_REPLACE = 0; 1687 /** If the msg is already queued, ignore this one and leave the old. */ 1688 private static final int SENDMSG_NOOP = 1; 1689 /** If the msg is already queued, queue this one and leave the old. */ 1690 private static final int SENDMSG_QUEUE = 2; 1691 sendMsg(int msg, int existingMsgPolicy, int delay)1692 private void sendMsg(int msg, int existingMsgPolicy, int delay) { 1693 sendIILMsg(msg, existingMsgPolicy, 0, 0, null, delay); 1694 } 1695 sendILMsg(int msg, int existingMsgPolicy, int arg, Object obj, int delay)1696 private void sendILMsg(int msg, int existingMsgPolicy, int arg, Object obj, int delay) { 1697 sendIILMsg(msg, existingMsgPolicy, arg, 0, obj, delay); 1698 } 1699 sendLMsg(int msg, int existingMsgPolicy, Object obj, int delay)1700 private void sendLMsg(int msg, int existingMsgPolicy, Object obj, int delay) { 1701 sendIILMsg(msg, existingMsgPolicy, 0, 0, obj, delay); 1702 } 1703 sendIMsg(int msg, int existingMsgPolicy, int arg, int delay)1704 private void sendIMsg(int msg, int existingMsgPolicy, int arg, int delay) { 1705 sendIILMsg(msg, existingMsgPolicy, arg, 0, null, delay); 1706 } 1707 sendMsgNoDelay(int msg, int existingMsgPolicy)1708 private void sendMsgNoDelay(int msg, int existingMsgPolicy) { 1709 sendIILMsg(msg, existingMsgPolicy, 0, 0, null, 0); 1710 } 1711 sendIMsgNoDelay(int msg, int existingMsgPolicy, int arg)1712 private void sendIMsgNoDelay(int msg, int existingMsgPolicy, int arg) { 1713 sendIILMsg(msg, existingMsgPolicy, arg, 0, null, 0); 1714 } 1715 sendIIMsgNoDelay(int msg, int existingMsgPolicy, int arg1, int arg2)1716 private void sendIIMsgNoDelay(int msg, int existingMsgPolicy, int arg1, int arg2) { 1717 sendIILMsg(msg, existingMsgPolicy, arg1, arg2, null, 0); 1718 } 1719 sendILMsgNoDelay(int msg, int existingMsgPolicy, int arg, Object obj)1720 private void sendILMsgNoDelay(int msg, int existingMsgPolicy, int arg, Object obj) { 1721 sendIILMsg(msg, existingMsgPolicy, arg, 0, obj, 0); 1722 } 1723 sendLMsgNoDelay(int msg, int existingMsgPolicy, Object obj)1724 private void sendLMsgNoDelay(int msg, int existingMsgPolicy, Object obj) { 1725 sendIILMsg(msg, existingMsgPolicy, 0, 0, obj, 0); 1726 } 1727 sendIILMsgNoDelay(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj)1728 private void sendIILMsgNoDelay(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj) { 1729 sendIILMsg(msg, existingMsgPolicy, arg1, arg2, obj, 0); 1730 } 1731 sendIILMsg(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj, int delay)1732 private void sendIILMsg(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj, 1733 int delay) { 1734 if (existingMsgPolicy == SENDMSG_REPLACE) { 1735 mBrokerHandler.removeMessages(msg); 1736 } else if (existingMsgPolicy == SENDMSG_NOOP && mBrokerHandler.hasMessages(msg)) { 1737 return; 1738 } 1739 1740 if (isMessageHandledUnderWakelock(msg)) { 1741 final long identity = Binder.clearCallingIdentity(); 1742 try { 1743 mBrokerEventWakeLock.acquire(BROKER_WAKELOCK_TIMEOUT_MS); 1744 } catch (Exception e) { 1745 Log.e(TAG, "Exception acquiring wakelock", e); 1746 } 1747 Binder.restoreCallingIdentity(identity); 1748 } 1749 1750 if (MESSAGES_MUTE_MUSIC.contains(msg)) { 1751 checkMessagesMuteMusic(msg); 1752 } 1753 1754 synchronized (sLastDeviceConnectionMsgTimeLock) { 1755 long time = SystemClock.uptimeMillis() + delay; 1756 1757 switch (msg) { 1758 case MSG_L_SET_BT_ACTIVE_DEVICE: 1759 case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE: 1760 case MSG_IL_BTA2DP_TIMEOUT: 1761 case MSG_IL_BTLEAUDIO_TIMEOUT: 1762 case MSG_L_A2DP_DEVICE_CONFIG_CHANGE: 1763 if (sLastDeviceConnectMsgTime >= time) { 1764 // add a little delay to make sure messages are ordered as expected 1765 time = sLastDeviceConnectMsgTime + 30; 1766 } 1767 sLastDeviceConnectMsgTime = time; 1768 break; 1769 default: 1770 break; 1771 } 1772 mBrokerHandler.sendMessageAtTime(mBrokerHandler.obtainMessage(msg, arg1, arg2, obj), 1773 time); 1774 } 1775 } 1776 1777 /** List of messages for which music is muted while processing is pending */ 1778 private static final Set<Integer> MESSAGES_MUTE_MUSIC; 1779 static { 1780 MESSAGES_MUTE_MUSIC = new HashSet<>(); 1781 MESSAGES_MUTE_MUSIC.add(MSG_L_SET_BT_ACTIVE_DEVICE); 1782 MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONFIG_CHANGE); 1783 MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT); 1784 MESSAGES_MUTE_MUSIC.add(MSG_IIL_SET_FORCE_BT_A2DP_USE); 1785 } 1786 1787 private AtomicBoolean mMusicMuted = new AtomicBoolean(false); 1788 hasIntersection(Set<T> a, Set<T> b)1789 private static <T> boolean hasIntersection(Set<T> a, Set<T> b) { 1790 for (T e : a) { 1791 if (b.contains(e)) return true; 1792 } 1793 return false; 1794 } 1795 messageMutesMusic(int message)1796 boolean messageMutesMusic(int message) { 1797 if (message == 0) { 1798 return false; 1799 } 1800 // Do not mute on bluetooth event if music is playing on a wired headset. 1801 if ((message == MSG_L_SET_BT_ACTIVE_DEVICE 1802 || message == MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT 1803 || message == MSG_L_A2DP_DEVICE_CONFIG_CHANGE) 1804 && AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0) 1805 && hasIntersection(mDeviceInventory.DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET, 1806 mAudioService.getDeviceSetForStream(AudioSystem.STREAM_MUSIC))) { 1807 return false; 1808 } 1809 return true; 1810 } 1811 1812 /** Mutes or unmutes music according to pending A2DP messages */ checkMessagesMuteMusic(int message)1813 private void checkMessagesMuteMusic(int message) { 1814 boolean mute = messageMutesMusic(message); 1815 if (!mute) { 1816 for (int msg : MESSAGES_MUTE_MUSIC) { 1817 if (mBrokerHandler.hasMessages(msg)) { 1818 if (messageMutesMusic(msg)) { 1819 mute = true; 1820 break; 1821 } 1822 } 1823 } 1824 } 1825 1826 if (mute != mMusicMuted.getAndSet(mute)) { 1827 mAudioService.setMusicMute(mute); 1828 } 1829 } 1830 1831 // List of applications requesting a specific route for communication. 1832 @GuardedBy("mDeviceStateLock") 1833 private final @NonNull LinkedList<CommunicationRouteClient> mCommunicationRouteClients = 1834 new LinkedList<CommunicationRouteClient>(); 1835 1836 private class CommunicationRouteClient implements IBinder.DeathRecipient { 1837 private final IBinder mCb; 1838 private final int mPid; 1839 private AudioDeviceAttributes mDevice; 1840 CommunicationRouteClient(IBinder cb, int pid, AudioDeviceAttributes device)1841 CommunicationRouteClient(IBinder cb, int pid, AudioDeviceAttributes device) { 1842 mCb = cb; 1843 mPid = pid; 1844 mDevice = device; 1845 } 1846 registerDeathRecipient()1847 public boolean registerDeathRecipient() { 1848 boolean status = false; 1849 try { 1850 mCb.linkToDeath(this, 0); 1851 status = true; 1852 } catch (RemoteException e) { 1853 Log.w(TAG, "CommunicationRouteClient could not link to " + mCb + " binder death"); 1854 } 1855 return status; 1856 } 1857 unregisterDeathRecipient()1858 public void unregisterDeathRecipient() { 1859 try { 1860 mCb.unlinkToDeath(this, 0); 1861 } catch (NoSuchElementException e) { 1862 Log.w(TAG, "CommunicationRouteClient could not not unregistered to binder"); 1863 } 1864 } 1865 1866 @Override binderDied()1867 public void binderDied() { 1868 postCommunicationRouteClientDied(this); 1869 } 1870 getBinder()1871 IBinder getBinder() { 1872 return mCb; 1873 } 1874 getPid()1875 int getPid() { 1876 return mPid; 1877 } 1878 getDevice()1879 AudioDeviceAttributes getDevice() { 1880 return mDevice; 1881 } 1882 requestsBluetoothSco()1883 boolean requestsBluetoothSco() { 1884 return mDevice != null 1885 && mDevice.getType() 1886 == AudioDeviceInfo.TYPE_BLUETOOTH_SCO; 1887 } 1888 requestsSpeakerphone()1889 boolean requestsSpeakerphone() { 1890 return mDevice != null 1891 && mDevice.getType() 1892 == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER; 1893 } 1894 } 1895 1896 // @GuardedBy("mSetModeLock") 1897 @GuardedBy("mDeviceStateLock") onCommunicationRouteClientDied(CommunicationRouteClient client)1898 private void onCommunicationRouteClientDied(CommunicationRouteClient client) { 1899 if (client == null) { 1900 return; 1901 } 1902 Log.w(TAG, "Communication client died"); 1903 setCommunicationRouteForClient(client.getBinder(), client.getPid(), null, 1904 BtHelper.SCO_MODE_UNDEFINED, "onCommunicationRouteClientDied"); 1905 } 1906 1907 /** 1908 * Determines which preferred device for phone strategy should be sent to audio policy manager 1909 * as a function of current SCO audio activation state and active communication route requests. 1910 * SCO audio state has the highest priority as it can result from external activation by 1911 * telephony service. 1912 * @return selected forced usage for communication. 1913 */ 1914 @GuardedBy("mDeviceStateLock") preferredCommunicationDevice()1915 @Nullable private AudioDeviceAttributes preferredCommunicationDevice() { 1916 boolean btSCoOn = mBluetoothScoOn && mBtHelper.isBluetoothScoOn(); 1917 if (btSCoOn) { 1918 // Use the SCO device known to BtHelper so that it matches exactly 1919 // what has been communicated to audio policy manager. The device 1920 // returned by requestedCommunicationDevice() can be a dummy SCO device if legacy 1921 // APIs are used to start SCO audio. 1922 AudioDeviceAttributes device = mBtHelper.getHeadsetAudioDevice(); 1923 if (device != null) { 1924 return device; 1925 } 1926 } 1927 AudioDeviceAttributes device = requestedCommunicationDevice(); 1928 if (device == null || device.getType() == AudioDeviceInfo.TYPE_BLUETOOTH_SCO) { 1929 // Do not indicate BT SCO selection if SCO is requested but SCO is not ON 1930 return null; 1931 } 1932 return device; 1933 } 1934 1935 /** 1936 * Configures audio policy manager and audio HAL according to active communication route. 1937 * Always called from message Handler. 1938 */ 1939 // @GuardedBy("mSetModeLock") 1940 @GuardedBy("mDeviceStateLock") onUpdateCommunicationRoute(String eventSource)1941 private void onUpdateCommunicationRoute(String eventSource) { 1942 AudioDeviceAttributes preferredCommunicationDevice = preferredCommunicationDevice(); 1943 if (AudioService.DEBUG_COMM_RTE) { 1944 Log.v(TAG, "onUpdateCommunicationRoute, preferredCommunicationDevice: " 1945 + preferredCommunicationDevice + " eventSource: " + eventSource); 1946 } 1947 AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent( 1948 "onUpdateCommunicationRoute, preferredCommunicationDevice: " 1949 + preferredCommunicationDevice + " eventSource: " + eventSource))); 1950 1951 if (preferredCommunicationDevice == null 1952 || preferredCommunicationDevice.getType() != AudioDeviceInfo.TYPE_BLUETOOTH_SCO) { 1953 mAudioSystem.setParameters("BT_SCO=off"); 1954 } else { 1955 mAudioSystem.setParameters("BT_SCO=on"); 1956 } 1957 if (preferredCommunicationDevice == null) { 1958 AudioDeviceAttributes defaultDevice = getDefaultCommunicationDevice(); 1959 if (defaultDevice != null) { 1960 setPreferredDevicesForStrategySync( 1961 mCommunicationStrategyId, Arrays.asList(defaultDevice)); 1962 setPreferredDevicesForStrategySync( 1963 mAccessibilityStrategyId, Arrays.asList(defaultDevice)); 1964 } else { 1965 removePreferredDevicesForStrategySync(mCommunicationStrategyId); 1966 removePreferredDevicesForStrategySync(mAccessibilityStrategyId); 1967 } 1968 } else { 1969 setPreferredDevicesForStrategySync( 1970 mCommunicationStrategyId, Arrays.asList(preferredCommunicationDevice)); 1971 setPreferredDevicesForStrategySync( 1972 mAccessibilityStrategyId, Arrays.asList(preferredCommunicationDevice)); 1973 } 1974 onUpdatePhoneStrategyDevice(preferredCommunicationDevice); 1975 } 1976 1977 /** 1978 * Select new communication device from communication route client at the top of the stack 1979 * and restore communication route including restarting SCO audio if needed. 1980 */ 1981 // @GuardedBy("mSetModeLock") 1982 @GuardedBy("mDeviceStateLock") onUpdateCommunicationRouteClient(String eventSource)1983 private void onUpdateCommunicationRouteClient(String eventSource) { 1984 onUpdateCommunicationRoute(eventSource); 1985 CommunicationRouteClient crc = topCommunicationRouteClient(); 1986 if (AudioService.DEBUG_COMM_RTE) { 1987 Log.v(TAG, "onUpdateCommunicationRouteClient, crc: " 1988 + crc + " eventSource: " + eventSource); 1989 } 1990 if (crc != null) { 1991 setCommunicationRouteForClient(crc.getBinder(), crc.getPid(), crc.getDevice(), 1992 BtHelper.SCO_MODE_UNDEFINED, eventSource); 1993 } 1994 } 1995 1996 // @GuardedBy("mSetModeLock") 1997 @GuardedBy("mDeviceStateLock") onUpdatePhoneStrategyDevice(AudioDeviceAttributes device)1998 private void onUpdatePhoneStrategyDevice(AudioDeviceAttributes device) { 1999 boolean wasSpeakerphoneActive = isSpeakerphoneActive(); 2000 mPreferredCommunicationDevice = device; 2001 updateActiveCommunicationDevice(); 2002 if (wasSpeakerphoneActive != isSpeakerphoneActive()) { 2003 try { 2004 mContext.sendBroadcastAsUser( 2005 new Intent(AudioManager.ACTION_SPEAKERPHONE_STATE_CHANGED) 2006 .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY), 2007 UserHandle.ALL); 2008 } catch (Exception e) { 2009 Log.w(TAG, "failed to broadcast ACTION_SPEAKERPHONE_STATE_CHANGED: " + e); 2010 } 2011 } 2012 mAudioService.postUpdateRingerModeServiceInt(); 2013 dispatchCommunicationDevice(); 2014 } 2015 removeCommunicationRouteClient( IBinder cb, boolean unregister)2016 private CommunicationRouteClient removeCommunicationRouteClient( 2017 IBinder cb, boolean unregister) { 2018 for (CommunicationRouteClient cl : mCommunicationRouteClients) { 2019 if (cl.getBinder() == cb) { 2020 if (unregister) { 2021 cl.unregisterDeathRecipient(); 2022 } 2023 mCommunicationRouteClients.remove(cl); 2024 return cl; 2025 } 2026 } 2027 return null; 2028 } 2029 2030 @GuardedBy("mDeviceStateLock") addCommunicationRouteClient( IBinder cb, int pid, AudioDeviceAttributes device)2031 private CommunicationRouteClient addCommunicationRouteClient( 2032 IBinder cb, int pid, AudioDeviceAttributes device) { 2033 // always insert new request at first position 2034 removeCommunicationRouteClient(cb, true); 2035 CommunicationRouteClient client = new CommunicationRouteClient(cb, pid, device); 2036 if (client.registerDeathRecipient()) { 2037 mCommunicationRouteClients.add(0, client); 2038 return client; 2039 } 2040 return null; 2041 } 2042 2043 @GuardedBy("mDeviceStateLock") getCommunicationRouteClientForPid(int pid)2044 private CommunicationRouteClient getCommunicationRouteClientForPid(int pid) { 2045 for (CommunicationRouteClient cl : mCommunicationRouteClients) { 2046 if (cl.getPid() == pid) { 2047 return cl; 2048 } 2049 } 2050 return null; 2051 } 2052 2053 @GuardedBy("mDeviceStateLock") communnicationDeviceCompatOn()2054 private boolean communnicationDeviceCompatOn() { 2055 return mAudioModeOwner.mMode == AudioSystem.MODE_IN_COMMUNICATION 2056 && !(CompatChanges.isChangeEnabled( 2057 USE_SET_COMMUNICATION_DEVICE, mAudioModeOwner.mUid) 2058 || mAudioModeOwner.mUid == android.os.Process.SYSTEM_UID); 2059 } 2060 2061 @GuardedBy("mDeviceStateLock") getDefaultCommunicationDevice()2062 AudioDeviceAttributes getDefaultCommunicationDevice() { 2063 // For system server (Telecom) and APKs targeting S and above, we let the audio 2064 // policy routing rules select the default communication device. 2065 // For older APKs, we force Hearing Aid or LE Audio headset when connected as 2066 // those APKs cannot select a LE Audio or Hearing Aid device explicitly. 2067 AudioDeviceAttributes device = null; 2068 if (communnicationDeviceCompatOn()) { 2069 // If both LE and Hearing Aid are active (thie should not happen), 2070 // priority to Hearing Aid. 2071 device = mDeviceInventory.getDeviceOfType(AudioSystem.DEVICE_OUT_HEARING_AID); 2072 if (device == null) { 2073 device = mDeviceInventory.getDeviceOfType(AudioSystem.DEVICE_OUT_BLE_HEADSET); 2074 } 2075 } 2076 return device; 2077 } 2078 getDeviceSensorUuid(AudioDeviceAttributes device)2079 @Nullable UUID getDeviceSensorUuid(AudioDeviceAttributes device) { 2080 synchronized (mDeviceStateLock) { 2081 return mDeviceInventory.getDeviceSensorUuid(device); 2082 } 2083 } 2084 } 2085