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.bluetooth.BluetoothA2dp; 20 import android.bluetooth.BluetoothDevice; 21 import android.bluetooth.BluetoothHeadset; 22 import android.bluetooth.BluetoothHearingAid; 23 import android.bluetooth.BluetoothProfile; 24 import android.content.ContentResolver; 25 import android.content.Context; 26 import android.content.Intent; 27 import android.media.AudioDeviceAttributes; 28 import android.media.AudioRoutesInfo; 29 import android.media.AudioSystem; 30 import android.media.IAudioRoutesObserver; 31 import android.media.IStrategyPreferredDeviceDispatcher; 32 import android.media.MediaMetrics; 33 import android.os.Binder; 34 import android.os.Handler; 35 import android.os.IBinder; 36 import android.os.Looper; 37 import android.os.Message; 38 import android.os.PowerManager; 39 import android.os.RemoteException; 40 import android.os.SystemClock; 41 import android.text.TextUtils; 42 import android.util.Log; 43 import android.util.PrintWriterPrinter; 44 45 import com.android.internal.annotations.GuardedBy; 46 47 import java.io.PrintWriter; 48 import java.util.ArrayList; 49 import java.util.HashSet; 50 import java.util.NoSuchElementException; 51 import java.util.Set; 52 import java.util.concurrent.atomic.AtomicBoolean; 53 54 55 /** @hide */ 56 /*package*/ final class AudioDeviceBroker { 57 58 private static final String TAG = "AS.AudioDeviceBroker"; 59 60 private static final long BROKER_WAKELOCK_TIMEOUT_MS = 5000; //5s 61 62 /*package*/ static final int BTA2DP_DOCK_TIMEOUT_MS = 8000; 63 // Timeout for connection to bluetooth headset service 64 /*package*/ static final int BT_HEADSET_CNCT_TIMEOUT_MS = 3000; 65 66 // Delay before checking it music should be unmuted after processing an A2DP message 67 private static final int BTA2DP_MUTE_CHECK_DELAY_MS = 100; 68 69 private final @NonNull AudioService mAudioService; 70 private final @NonNull Context mContext; 71 72 /** Forced device usage for communications sent to AudioSystem */ 73 private int mForcedUseForComm; 74 /** 75 * Externally reported force device usage state returned by getters: always consistent 76 * with requests by setters */ 77 private int mForcedUseForCommExt; 78 79 // Manages all connected devices, only ever accessed on the message loop 80 private final AudioDeviceInventory mDeviceInventory; 81 // Manages notifications to BT service 82 private final BtHelper mBtHelper; 83 // Adapter for system_server-reserved operations 84 private final SystemServerAdapter mSystemServer; 85 86 87 //------------------------------------------------------------------- 88 // we use a different lock than mDeviceStateLock so as not to create 89 // lock contention between enqueueing a message and handling them 90 private static final Object sLastDeviceConnectionMsgTimeLock = new Object(); 91 @GuardedBy("sLastDeviceConnectionMsgTimeLock") 92 private static long sLastDeviceConnectMsgTime = 0; 93 94 // General lock to be taken whenever the state of the audio devices is to be checked or changed 95 private final Object mDeviceStateLock = new Object(); 96 97 // Request to override default use of A2DP for media. 98 @GuardedBy("mDeviceStateLock") 99 private boolean mBluetoothA2dpEnabled; 100 101 // lock always taken when accessing AudioService.mSetModeDeathHandlers 102 // TODO do not "share" the lock between AudioService and BtHelpr, see b/123769055 103 /*package*/ final Object mSetModeLock = new Object(); 104 105 /** PID of current audio mode owner communicated by AudioService */ 106 private int mModeOwnerPid = 0; 107 108 //------------------------------------------------------------------- AudioDeviceBroker(@onNull Context context, @NonNull AudioService service)109 /*package*/ AudioDeviceBroker(@NonNull Context context, @NonNull AudioService service) { 110 mContext = context; 111 mAudioService = service; 112 mBtHelper = new BtHelper(this); 113 mDeviceInventory = new AudioDeviceInventory(this); 114 mSystemServer = SystemServerAdapter.getDefaultAdapter(mContext); 115 116 init(); 117 } 118 119 /** for test purposes only, inject AudioDeviceInventory and adapter for operations running 120 * in system_server */ AudioDeviceBroker(@onNull Context context, @NonNull AudioService service, @NonNull AudioDeviceInventory mockDeviceInventory, @NonNull SystemServerAdapter mockSystemServer)121 AudioDeviceBroker(@NonNull Context context, @NonNull AudioService service, 122 @NonNull AudioDeviceInventory mockDeviceInventory, 123 @NonNull SystemServerAdapter mockSystemServer) { 124 mContext = context; 125 mAudioService = service; 126 mBtHelper = new BtHelper(this); 127 mDeviceInventory = mockDeviceInventory; 128 mSystemServer = mockSystemServer; 129 130 init(); 131 } 132 init()133 private void init() { 134 setupMessaging(mContext); 135 136 mForcedUseForComm = AudioSystem.FORCE_NONE; 137 mForcedUseForCommExt = mForcedUseForComm; 138 } 139 getContext()140 /*package*/ Context getContext() { 141 return mContext; 142 } 143 144 //--------------------------------------------------------------------- 145 // Communication from AudioService 146 // All methods are asynchronous and never block 147 // All permission checks are done in AudioService, all incoming calls are considered "safe" 148 // All post* methods are asynchronous 149 onSystemReady()150 /*package*/ void onSystemReady() { 151 synchronized (mSetModeLock) { 152 synchronized (mDeviceStateLock) { 153 mModeOwnerPid = mAudioService.getModeOwnerPid(); 154 mBtHelper.onSystemReady(); 155 } 156 } 157 } 158 onAudioServerDied()159 /*package*/ void onAudioServerDied() { 160 // Restore forced usage for communications and record 161 synchronized (mDeviceStateLock) { 162 AudioSystem.setParameters( 163 "BT_SCO=" + (mForcedUseForComm == AudioSystem.FORCE_BT_SCO ? "on" : "off")); 164 onSetForceUse(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, 165 false /*fromA2dp*/, "onAudioServerDied"); 166 onSetForceUse(AudioSystem.FOR_RECORD, mForcedUseForComm, 167 false /*fromA2dp*/, "onAudioServerDied"); 168 } 169 // restore devices 170 sendMsgNoDelay(MSG_RESTORE_DEVICES, SENDMSG_REPLACE); 171 } 172 setForceUse_Async(int useCase, int config, String eventSource)173 /*package*/ void setForceUse_Async(int useCase, int config, String eventSource) { 174 sendIILMsgNoDelay(MSG_IIL_SET_FORCE_USE, SENDMSG_QUEUE, 175 useCase, config, eventSource); 176 } 177 toggleHdmiIfConnected_Async()178 /*package*/ void toggleHdmiIfConnected_Async() { 179 sendMsgNoDelay(MSG_TOGGLE_HDMI, SENDMSG_QUEUE); 180 } 181 disconnectAllBluetoothProfiles()182 /*package*/ void disconnectAllBluetoothProfiles() { 183 synchronized (mDeviceStateLock) { 184 mBtHelper.disconnectAllBluetoothProfiles(); 185 } 186 } 187 188 /** 189 * Handle BluetoothHeadset intents where the action is one of 190 * {@link BluetoothHeadset#ACTION_ACTIVE_DEVICE_CHANGED} or 191 * {@link BluetoothHeadset#ACTION_AUDIO_STATE_CHANGED}. 192 * @param intent 193 */ receiveBtEvent(@onNull Intent intent)194 /*package*/ void receiveBtEvent(@NonNull Intent intent) { 195 synchronized (mSetModeLock) { 196 synchronized (mDeviceStateLock) { 197 mBtHelper.receiveBtEvent(intent); 198 } 199 } 200 } 201 setBluetoothA2dpOn_Async(boolean on, String source)202 /*package*/ void setBluetoothA2dpOn_Async(boolean on, String source) { 203 synchronized (mDeviceStateLock) { 204 if (mBluetoothA2dpEnabled == on) { 205 return; 206 } 207 mBluetoothA2dpEnabled = on; 208 mBrokerHandler.removeMessages(MSG_IIL_SET_FORCE_BT_A2DP_USE); 209 sendIILMsgNoDelay(MSG_IIL_SET_FORCE_BT_A2DP_USE, SENDMSG_QUEUE, 210 AudioSystem.FOR_MEDIA, 211 mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP, 212 source); 213 } 214 } 215 216 /** 217 * Turns speakerphone on/off 218 * @param on 219 * @param eventSource for logging purposes 220 * @return true if speakerphone state changed 221 */ setSpeakerphoneOn(IBinder cb, int pid, boolean on, String eventSource)222 /*package*/ boolean setSpeakerphoneOn(IBinder cb, int pid, boolean on, String eventSource) { 223 synchronized (mDeviceStateLock) { 224 if (!addSpeakerphoneClient(cb, pid, on)) { 225 return false; 226 } 227 if (on) { 228 // Cancel BT SCO ON request by this same client: speakerphone and BT SCO routes 229 // are mutually exclusive. 230 // See symmetrical operation for startBluetoothScoForClient_Sync(). 231 mBtHelper.stopBluetoothScoForPid(pid); 232 } 233 final boolean wasOn = isSpeakerphoneOn(); 234 updateSpeakerphoneOn(eventSource); 235 return (wasOn != isSpeakerphoneOn()); 236 } 237 } 238 239 /** 240 * Turns speakerphone off for a given pid and update speakerphone state. 241 * @param pid 242 */ 243 @GuardedBy("mDeviceStateLock") setSpeakerphoneOffForPid(int pid)244 private void setSpeakerphoneOffForPid(int pid) { 245 SpeakerphoneClient client = getSpeakerphoneClientForPid(pid); 246 if (client == null) { 247 return; 248 } 249 client.unregisterDeathRecipient(); 250 mSpeakerphoneClients.remove(client); 251 final String eventSource = new StringBuilder("setSpeakerphoneOffForPid(") 252 .append(pid).append(")").toString(); 253 updateSpeakerphoneOn(eventSource); 254 } 255 256 @GuardedBy("mDeviceStateLock") updateSpeakerphoneOn(String eventSource)257 private void updateSpeakerphoneOn(String eventSource) { 258 if (isSpeakerphoneOnRequested()) { 259 if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) { 260 setForceUse_Async(AudioSystem.FOR_RECORD, AudioSystem.FORCE_NONE, eventSource); 261 } 262 mForcedUseForComm = AudioSystem.FORCE_SPEAKER; 263 } else if (mForcedUseForComm == AudioSystem.FORCE_SPEAKER) { 264 if (mBtHelper.isBluetoothScoOn()) { 265 mForcedUseForComm = AudioSystem.FORCE_BT_SCO; 266 setForceUse_Async( 267 AudioSystem.FOR_RECORD, AudioSystem.FORCE_BT_SCO, eventSource); 268 } else { 269 mForcedUseForComm = AudioSystem.FORCE_NONE; 270 } 271 } 272 mForcedUseForCommExt = mForcedUseForComm; 273 setForceUse_Async(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, eventSource); 274 } 275 276 /** 277 * Returns if speakerphone is requested ON or OFF. 278 * If the current audio mode owner is in the speakerphone client list, use this preference. 279 * Otherwise use first client's preference (first client corresponds to latest request). 280 * Speakerphone is requested OFF if no client is in the list. 281 * @return true if speakerphone is requested ON, false otherwise 282 */ 283 @GuardedBy("mDeviceStateLock") isSpeakerphoneOnRequested()284 private boolean isSpeakerphoneOnRequested() { 285 if (mSpeakerphoneClients.isEmpty()) { 286 return false; 287 } 288 for (SpeakerphoneClient cl : mSpeakerphoneClients) { 289 if (cl.getPid() == mModeOwnerPid) { 290 return cl.isOn(); 291 } 292 } 293 return mSpeakerphoneClients.get(0).isOn(); 294 } 295 isSpeakerphoneOn()296 /*package*/ boolean isSpeakerphoneOn() { 297 synchronized (mDeviceStateLock) { 298 return (mForcedUseForCommExt == AudioSystem.FORCE_SPEAKER); 299 } 300 } 301 setWiredDeviceConnectionState(int type, @AudioService.ConnectionState int state, String address, String name, String caller)302 /*package*/ void setWiredDeviceConnectionState(int type, 303 @AudioService.ConnectionState int state, String address, String name, 304 String caller) { 305 //TODO move logging here just like in setBluetooth* methods 306 synchronized (mDeviceStateLock) { 307 mDeviceInventory.setWiredDeviceConnectionState(type, state, address, name, caller); 308 } 309 } 310 311 private static final class BtDeviceConnectionInfo { 312 final @NonNull BluetoothDevice mDevice; 313 final @AudioService.BtProfileConnectionState int mState; 314 final int mProfile; 315 final boolean mSupprNoisy; 316 final int mVolume; 317 BtDeviceConnectionInfo(@onNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state, int profile, boolean suppressNoisyIntent, int vol)318 BtDeviceConnectionInfo(@NonNull BluetoothDevice device, 319 @AudioService.BtProfileConnectionState int state, 320 int profile, boolean suppressNoisyIntent, int vol) { 321 mDevice = device; 322 mState = state; 323 mProfile = profile; 324 mSupprNoisy = suppressNoisyIntent; 325 mVolume = vol; 326 } 327 328 // redefine equality op so we can match messages intended for this device 329 @Override equals(Object o)330 public boolean equals(Object o) { 331 if (o == null) { 332 return false; 333 } 334 if (this == o) { 335 return true; 336 } 337 if (o instanceof BtDeviceConnectionInfo) { 338 return mDevice.equals(((BtDeviceConnectionInfo) o).mDevice); 339 } 340 return false; 341 } 342 343 @Override toString()344 public String toString() { 345 return "BtDeviceConnectionInfo dev=" + mDevice.toString(); 346 } 347 } 348 349 postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent( @onNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state, int profile, boolean suppressNoisyIntent, int a2dpVolume)350 /*package*/ void postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent( 351 @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state, 352 int profile, boolean suppressNoisyIntent, int a2dpVolume) { 353 final BtDeviceConnectionInfo info = new BtDeviceConnectionInfo(device, state, profile, 354 suppressNoisyIntent, a2dpVolume); 355 356 final String name = TextUtils.emptyIfNull(device.getName()); 357 new MediaMetrics.Item(MediaMetrics.Name.AUDIO_DEVICE + MediaMetrics.SEPARATOR 358 + "postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent") 359 .set(MediaMetrics.Property.STATE, state == BluetoothProfile.STATE_CONNECTED 360 ? MediaMetrics.Value.CONNECTED : MediaMetrics.Value.DISCONNECTED) 361 .set(MediaMetrics.Property.INDEX, a2dpVolume) 362 .set(MediaMetrics.Property.NAME, name) 363 .record(); 364 365 // operations of removing and posting messages related to A2DP device state change must be 366 // mutually exclusive 367 synchronized (mDeviceStateLock) { 368 // when receiving a request to change the connection state of a device, this last 369 // request is the source of truth, so cancel all previous requests that are already in 370 // the handler 371 removeScheduledA2dpEvents(device); 372 373 sendLMsgNoDelay( 374 state == BluetoothProfile.STATE_CONNECTED 375 ? MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION 376 : MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION, 377 SENDMSG_QUEUE, info); 378 } 379 } 380 381 /** remove all previously scheduled connection and state change events for the given device */ 382 @GuardedBy("mDeviceStateLock") removeScheduledA2dpEvents(@onNull BluetoothDevice device)383 private void removeScheduledA2dpEvents(@NonNull BluetoothDevice device) { 384 mBrokerHandler.removeEqualMessages(MSG_L_A2DP_DEVICE_CONFIG_CHANGE, device); 385 386 final BtDeviceConnectionInfo connectionInfoToRemove = new BtDeviceConnectionInfo(device, 387 // the next parameters of the constructor will be ignored when finding the message 388 // to remove as the equality of the message's object is tested on the device itself 389 // (see BtDeviceConnectionInfo.equals() method override) 390 BluetoothProfile.STATE_CONNECTED, 0, false, -1); 391 mBrokerHandler.removeEqualMessages(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION, 392 connectionInfoToRemove); 393 mBrokerHandler.removeEqualMessages(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION, 394 connectionInfoToRemove); 395 396 final BtHelper.BluetoothA2dpDeviceInfo devInfoToRemove = 397 new BtHelper.BluetoothA2dpDeviceInfo(device); 398 mBrokerHandler.removeEqualMessages(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED, 399 devInfoToRemove); 400 mBrokerHandler.removeEqualMessages(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED, 401 devInfoToRemove); 402 mBrokerHandler.removeEqualMessages(MSG_L_A2DP_ACTIVE_DEVICE_CHANGE, 403 devInfoToRemove); 404 } 405 406 private static final class HearingAidDeviceConnectionInfo { 407 final @NonNull BluetoothDevice mDevice; 408 final @AudioService.BtProfileConnectionState int mState; 409 final boolean mSupprNoisy; 410 final int mMusicDevice; 411 final @NonNull String mEventSource; 412 HearingAidDeviceConnectionInfo(@onNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state, boolean suppressNoisyIntent, int musicDevice, @NonNull String eventSource)413 HearingAidDeviceConnectionInfo(@NonNull BluetoothDevice device, 414 @AudioService.BtProfileConnectionState int state, 415 boolean suppressNoisyIntent, int musicDevice, @NonNull String eventSource) { 416 mDevice = device; 417 mState = state; 418 mSupprNoisy = suppressNoisyIntent; 419 mMusicDevice = musicDevice; 420 mEventSource = eventSource; 421 } 422 } 423 postBluetoothHearingAidDeviceConnectionState( @onNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state, boolean suppressNoisyIntent, int musicDevice, @NonNull String eventSource)424 /*package*/ void postBluetoothHearingAidDeviceConnectionState( 425 @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state, 426 boolean suppressNoisyIntent, int musicDevice, @NonNull String eventSource) { 427 final HearingAidDeviceConnectionInfo info = new HearingAidDeviceConnectionInfo( 428 device, state, suppressNoisyIntent, musicDevice, eventSource); 429 sendLMsgNoDelay(MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT, SENDMSG_QUEUE, info); 430 } 431 432 // never called by system components setBluetoothScoOnByApp(boolean on)433 /*package*/ void setBluetoothScoOnByApp(boolean on) { 434 synchronized (mDeviceStateLock) { 435 mForcedUseForCommExt = on ? AudioSystem.FORCE_BT_SCO : AudioSystem.FORCE_NONE; 436 } 437 } 438 isBluetoothScoOnForApp()439 /*package*/ boolean isBluetoothScoOnForApp() { 440 synchronized (mDeviceStateLock) { 441 return mForcedUseForCommExt == AudioSystem.FORCE_BT_SCO; 442 } 443 } 444 setBluetoothScoOn(boolean on, String eventSource)445 /*package*/ void setBluetoothScoOn(boolean on, String eventSource) { 446 //Log.i(TAG, "setBluetoothScoOn: " + on + " " + eventSource); 447 synchronized (mDeviceStateLock) { 448 if (on) { 449 // do not accept SCO ON if SCO audio is not connected 450 if (!mBtHelper.isBluetoothScoOn()) { 451 mForcedUseForCommExt = AudioSystem.FORCE_BT_SCO; 452 return; 453 } 454 mForcedUseForComm = AudioSystem.FORCE_BT_SCO; 455 } else if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) { 456 mForcedUseForComm = isSpeakerphoneOnRequested() 457 ? AudioSystem.FORCE_SPEAKER : AudioSystem.FORCE_NONE; 458 } 459 mForcedUseForCommExt = mForcedUseForComm; 460 AudioSystem.setParameters("BT_SCO=" + (on ? "on" : "off")); 461 sendIILMsgNoDelay(MSG_IIL_SET_FORCE_USE, SENDMSG_QUEUE, 462 AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, eventSource); 463 sendIILMsgNoDelay(MSG_IIL_SET_FORCE_USE, SENDMSG_QUEUE, 464 AudioSystem.FOR_RECORD, mForcedUseForComm, eventSource); 465 } 466 // Un-mute ringtone stream volume 467 mAudioService.postUpdateRingerModeServiceInt(); 468 } 469 startWatchingRoutes(IAudioRoutesObserver observer)470 /*package*/ AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) { 471 synchronized (mDeviceStateLock) { 472 return mDeviceInventory.startWatchingRoutes(observer); 473 } 474 } 475 getCurAudioRoutes()476 /*package*/ AudioRoutesInfo getCurAudioRoutes() { 477 synchronized (mDeviceStateLock) { 478 return mDeviceInventory.getCurAudioRoutes(); 479 } 480 } 481 isAvrcpAbsoluteVolumeSupported()482 /*package*/ boolean isAvrcpAbsoluteVolumeSupported() { 483 synchronized (mDeviceStateLock) { 484 return mBtHelper.isAvrcpAbsoluteVolumeSupported(); 485 } 486 } 487 isBluetoothA2dpOn()488 /*package*/ boolean isBluetoothA2dpOn() { 489 synchronized (mDeviceStateLock) { 490 return mBluetoothA2dpEnabled; 491 } 492 } 493 postSetAvrcpAbsoluteVolumeIndex(int index)494 /*package*/ void postSetAvrcpAbsoluteVolumeIndex(int index) { 495 sendIMsgNoDelay(MSG_I_SET_AVRCP_ABSOLUTE_VOLUME, SENDMSG_REPLACE, index); 496 } 497 postSetHearingAidVolumeIndex(int index, int streamType)498 /*package*/ void postSetHearingAidVolumeIndex(int index, int streamType) { 499 sendIIMsgNoDelay(MSG_II_SET_HEARING_AID_VOLUME, SENDMSG_REPLACE, index, streamType); 500 } 501 postSetModeOwnerPid(int pid, int mode)502 /*package*/ void postSetModeOwnerPid(int pid, int mode) { 503 sendIIMsgNoDelay(MSG_I_SET_MODE_OWNER_PID, SENDMSG_REPLACE, pid, mode); 504 } 505 postBluetoothA2dpDeviceConfigChange(@onNull BluetoothDevice device)506 /*package*/ void postBluetoothA2dpDeviceConfigChange(@NonNull BluetoothDevice device) { 507 sendLMsgNoDelay(MSG_L_A2DP_DEVICE_CONFIG_CHANGE, SENDMSG_QUEUE, device); 508 } 509 510 @GuardedBy("mSetModeLock") startBluetoothScoForClient_Sync(IBinder cb, int scoAudioMode, @NonNull String eventSource)511 /*package*/ void startBluetoothScoForClient_Sync(IBinder cb, int scoAudioMode, 512 @NonNull String eventSource) { 513 synchronized (mDeviceStateLock) { 514 // Cancel speakerphone ON request by this same client: speakerphone and BT SCO routes 515 // are mutually exclusive. 516 // See symmetrical operation for setSpeakerphoneOn(true). 517 setSpeakerphoneOffForPid(Binder.getCallingPid()); 518 mBtHelper.startBluetoothScoForClient(cb, scoAudioMode, eventSource); 519 } 520 } 521 522 @GuardedBy("mSetModeLock") stopBluetoothScoForClient_Sync(IBinder cb, @NonNull String eventSource)523 /*package*/ void stopBluetoothScoForClient_Sync(IBinder cb, @NonNull String eventSource) { 524 synchronized (mDeviceStateLock) { 525 mBtHelper.stopBluetoothScoForClient(cb, eventSource); 526 } 527 } 528 setPreferredDeviceForStrategySync(int strategy, @NonNull AudioDeviceAttributes device)529 /*package*/ int setPreferredDeviceForStrategySync(int strategy, 530 @NonNull AudioDeviceAttributes device) { 531 return mDeviceInventory.setPreferredDeviceForStrategySync(strategy, device); 532 } 533 removePreferredDeviceForStrategySync(int strategy)534 /*package*/ int removePreferredDeviceForStrategySync(int strategy) { 535 return mDeviceInventory.removePreferredDeviceForStrategySync(strategy); 536 } 537 registerStrategyPreferredDeviceDispatcher( @onNull IStrategyPreferredDeviceDispatcher dispatcher)538 /*package*/ void registerStrategyPreferredDeviceDispatcher( 539 @NonNull IStrategyPreferredDeviceDispatcher dispatcher) { 540 mDeviceInventory.registerStrategyPreferredDeviceDispatcher(dispatcher); 541 } 542 unregisterStrategyPreferredDeviceDispatcher( @onNull IStrategyPreferredDeviceDispatcher dispatcher)543 /*package*/ void unregisterStrategyPreferredDeviceDispatcher( 544 @NonNull IStrategyPreferredDeviceDispatcher dispatcher) { 545 mDeviceInventory.unregisterStrategyPreferredDeviceDispatcher(dispatcher); 546 } 547 548 //--------------------------------------------------------------------- 549 // Communication with (to) AudioService 550 //TODO check whether the AudioService methods are candidates to move here postAccessoryPlugMediaUnmute(int device)551 /*package*/ void postAccessoryPlugMediaUnmute(int device) { 552 mAudioService.postAccessoryPlugMediaUnmute(device); 553 } 554 getVssVolumeForDevice(int streamType, int device)555 /*package*/ int getVssVolumeForDevice(int streamType, int device) { 556 return mAudioService.getVssVolumeForDevice(streamType, device); 557 } 558 getModeOwnerPid()559 /*package*/ int getModeOwnerPid() { 560 return mModeOwnerPid; 561 } 562 getDeviceForStream(int streamType)563 /*package*/ int getDeviceForStream(int streamType) { 564 return mAudioService.getDeviceForStream(streamType); 565 } 566 postApplyVolumeOnDevice(int streamType, int device, String caller)567 /*package*/ void postApplyVolumeOnDevice(int streamType, int device, String caller) { 568 mAudioService.postApplyVolumeOnDevice(streamType, device, caller); 569 } 570 postSetVolumeIndexOnDevice(int streamType, int vssVolIndex, int device, String caller)571 /*package*/ void postSetVolumeIndexOnDevice(int streamType, int vssVolIndex, int device, 572 String caller) { 573 mAudioService.postSetVolumeIndexOnDevice(streamType, vssVolIndex, device, caller); 574 } 575 postObserveDevicesForAllStreams()576 /*packages*/ void postObserveDevicesForAllStreams() { 577 mAudioService.postObserveDevicesForAllStreams(); 578 } 579 isInCommunication()580 /*package*/ boolean isInCommunication() { 581 return mAudioService.isInCommunication(); 582 } 583 hasMediaDynamicPolicy()584 /*package*/ boolean hasMediaDynamicPolicy() { 585 return mAudioService.hasMediaDynamicPolicy(); 586 } 587 getContentResolver()588 /*package*/ ContentResolver getContentResolver() { 589 return mAudioService.getContentResolver(); 590 } 591 checkMusicActive(int deviceType, String caller)592 /*package*/ void checkMusicActive(int deviceType, String caller) { 593 mAudioService.checkMusicActive(deviceType, caller); 594 } 595 checkVolumeCecOnHdmiConnection( @udioService.ConnectionState int state, String caller)596 /*package*/ void checkVolumeCecOnHdmiConnection( 597 @AudioService.ConnectionState int state, String caller) { 598 mAudioService.postCheckVolumeCecOnHdmiConnection(state, caller); 599 } 600 hasAudioFocusUsers()601 /*package*/ boolean hasAudioFocusUsers() { 602 return mAudioService.hasAudioFocusUsers(); 603 } 604 605 //--------------------------------------------------------------------- 606 // Message handling on behalf of helper classes postBroadcastScoConnectionState(int state)607 /*package*/ void postBroadcastScoConnectionState(int state) { 608 sendIMsgNoDelay(MSG_I_BROADCAST_BT_CONNECTION_STATE, SENDMSG_QUEUE, state); 609 } 610 postBroadcastBecomingNoisy()611 /*package*/ void postBroadcastBecomingNoisy() { 612 sendMsgNoDelay(MSG_BROADCAST_AUDIO_BECOMING_NOISY, SENDMSG_REPLACE); 613 } 614 615 @GuardedBy("mDeviceStateLock") postA2dpSinkConnection(@udioService.BtProfileConnectionState int state, @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo, int delay)616 /*package*/ void postA2dpSinkConnection(@AudioService.BtProfileConnectionState int state, 617 @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo, int delay) { 618 sendILMsg(state == BluetoothA2dp.STATE_CONNECTED 619 ? MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED 620 : MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED, 621 SENDMSG_QUEUE, 622 state, btDeviceInfo, delay); 623 } 624 postA2dpSourceConnection(@udioService.BtProfileConnectionState int state, @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo, int delay)625 /*package*/ void postA2dpSourceConnection(@AudioService.BtProfileConnectionState int state, 626 @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo, int delay) { 627 sendILMsg(MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE, SENDMSG_QUEUE, 628 state, btDeviceInfo, delay); 629 } 630 postSetWiredDeviceConnectionState( AudioDeviceInventory.WiredDeviceConnectionState connectionState, int delay)631 /*package*/ void postSetWiredDeviceConnectionState( 632 AudioDeviceInventory.WiredDeviceConnectionState connectionState, int delay) { 633 sendLMsg(MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE, SENDMSG_QUEUE, connectionState, delay); 634 } 635 postSetHearingAidConnectionState( @udioService.BtProfileConnectionState int state, @NonNull BluetoothDevice device, int delay)636 /*package*/ void postSetHearingAidConnectionState( 637 @AudioService.BtProfileConnectionState int state, 638 @NonNull BluetoothDevice device, int delay) { 639 sendILMsg(MSG_IL_SET_HEARING_AID_CONNECTION_STATE, SENDMSG_QUEUE, 640 state, 641 device, 642 delay); 643 } 644 postDisconnectA2dp()645 /*package*/ void postDisconnectA2dp() { 646 sendMsgNoDelay(MSG_DISCONNECT_A2DP, SENDMSG_QUEUE); 647 } 648 postDisconnectA2dpSink()649 /*package*/ void postDisconnectA2dpSink() { 650 sendMsgNoDelay(MSG_DISCONNECT_A2DP_SINK, SENDMSG_QUEUE); 651 } 652 postDisconnectHearingAid()653 /*package*/ void postDisconnectHearingAid() { 654 sendMsgNoDelay(MSG_DISCONNECT_BT_HEARING_AID, SENDMSG_QUEUE); 655 } 656 postDisconnectHeadset()657 /*package*/ void postDisconnectHeadset() { 658 sendMsgNoDelay(MSG_DISCONNECT_BT_HEADSET, SENDMSG_QUEUE); 659 } 660 postBtA2dpProfileConnected(BluetoothA2dp a2dpProfile)661 /*package*/ void postBtA2dpProfileConnected(BluetoothA2dp a2dpProfile) { 662 sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP, SENDMSG_QUEUE, a2dpProfile); 663 } 664 postBtA2dpSinkProfileConnected(BluetoothProfile profile)665 /*package*/ void postBtA2dpSinkProfileConnected(BluetoothProfile profile) { 666 sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP_SINK, SENDMSG_QUEUE, profile); 667 } 668 postBtHeasetProfileConnected(BluetoothHeadset headsetProfile)669 /*package*/ void postBtHeasetProfileConnected(BluetoothHeadset headsetProfile) { 670 sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEADSET, SENDMSG_QUEUE, headsetProfile); 671 } 672 postBtHearingAidProfileConnected(BluetoothHearingAid hearingAidProfile)673 /*package*/ void postBtHearingAidProfileConnected(BluetoothHearingAid hearingAidProfile) { 674 sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEARING_AID, SENDMSG_QUEUE, 675 hearingAidProfile); 676 } 677 postScoClientDied(Object obj)678 /*package*/ void postScoClientDied(Object obj) { 679 sendLMsgNoDelay(MSG_L_SCOCLIENT_DIED, SENDMSG_QUEUE, obj); 680 } 681 postSpeakerphoneClientDied(Object obj)682 /*package*/ void postSpeakerphoneClientDied(Object obj) { 683 sendLMsgNoDelay(MSG_L_SPEAKERPHONE_CLIENT_DIED, SENDMSG_QUEUE, obj); 684 } 685 postSaveSetPreferredDeviceForStrategy(int strategy, AudioDeviceAttributes device)686 /*package*/ void postSaveSetPreferredDeviceForStrategy(int strategy, 687 AudioDeviceAttributes device) 688 { 689 sendILMsgNoDelay(MSG_IL_SAVE_PREF_DEVICE_FOR_STRATEGY, SENDMSG_QUEUE, strategy, device); 690 } 691 postSaveRemovePreferredDeviceForStrategy(int strategy)692 /*package*/ void postSaveRemovePreferredDeviceForStrategy(int strategy) { 693 sendIMsgNoDelay(MSG_I_SAVE_REMOVE_PREF_DEVICE_FOR_STRATEGY, SENDMSG_QUEUE, strategy); 694 } 695 696 //--------------------------------------------------------------------- 697 // Method forwarding between the helper classes (BtHelper, AudioDeviceInventory) 698 // only call from a "handle"* method or "on"* method 699 700 // Handles request to override default use of A2DP for media. 701 //@GuardedBy("mConnectedDevices") setBluetoothA2dpOnInt(boolean on, boolean fromA2dp, String source)702 /*package*/ void setBluetoothA2dpOnInt(boolean on, boolean fromA2dp, String source) { 703 // for logging only 704 final String eventSource = new StringBuilder("setBluetoothA2dpOn(").append(on) 705 .append(") from u/pid:").append(Binder.getCallingUid()).append("/") 706 .append(Binder.getCallingPid()).append(" src:").append(source).toString(); 707 708 synchronized (mDeviceStateLock) { 709 mBluetoothA2dpEnabled = on; 710 mBrokerHandler.removeMessages(MSG_IIL_SET_FORCE_BT_A2DP_USE); 711 onSetForceUse( 712 AudioSystem.FOR_MEDIA, 713 mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP, 714 fromA2dp, 715 eventSource); 716 } 717 } 718 handleDeviceConnection(boolean connect, int device, String address, String deviceName)719 /*package*/ boolean handleDeviceConnection(boolean connect, int device, String address, 720 String deviceName) { 721 synchronized (mDeviceStateLock) { 722 return mDeviceInventory.handleDeviceConnection(connect, device, address, deviceName); 723 } 724 } 725 postSetA2dpSourceConnectionState(@luetoothProfile.BtProfileState int state, @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo)726 /*package*/ void postSetA2dpSourceConnectionState(@BluetoothProfile.BtProfileState int state, 727 @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo) { 728 final int intState = (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0; 729 sendILMsgNoDelay(MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE, SENDMSG_QUEUE, state, 730 btDeviceInfo); 731 } 732 handleFailureToConnectToBtHeadsetService(int delay)733 /*package*/ void handleFailureToConnectToBtHeadsetService(int delay) { 734 sendMsg(MSG_BT_HEADSET_CNCT_FAILED, SENDMSG_REPLACE, delay); 735 } 736 handleCancelFailureToConnectToBtHeadsetService()737 /*package*/ void handleCancelFailureToConnectToBtHeadsetService() { 738 mBrokerHandler.removeMessages(MSG_BT_HEADSET_CNCT_FAILED); 739 } 740 postReportNewRoutes(boolean fromA2dp)741 /*package*/ void postReportNewRoutes(boolean fromA2dp) { 742 sendMsgNoDelay(fromA2dp ? MSG_REPORT_NEW_ROUTES_A2DP : MSG_REPORT_NEW_ROUTES, SENDMSG_NOOP); 743 } 744 postA2dpActiveDeviceChange( @onNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo)745 /*package*/ void postA2dpActiveDeviceChange( 746 @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo) { 747 sendLMsgNoDelay(MSG_L_A2DP_ACTIVE_DEVICE_CHANGE, SENDMSG_QUEUE, btDeviceInfo); 748 } 749 750 // must be called synchronized on mConnectedDevices hasScheduledA2dpSinkConnectionState(BluetoothDevice btDevice)751 /*package*/ boolean hasScheduledA2dpSinkConnectionState(BluetoothDevice btDevice) { 752 final BtHelper.BluetoothA2dpDeviceInfo devInfoToCheck = 753 new BtHelper.BluetoothA2dpDeviceInfo(btDevice); 754 return (mBrokerHandler.hasEqualMessages( 755 MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED, devInfoToCheck) 756 || mBrokerHandler.hasEqualMessages( 757 MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED, devInfoToCheck)); 758 } 759 setA2dpTimeout(String address, int a2dpCodec, int delayMs)760 /*package*/ void setA2dpTimeout(String address, int a2dpCodec, int delayMs) { 761 sendILMsg(MSG_IL_BTA2DP_TIMEOUT, SENDMSG_QUEUE, a2dpCodec, address, delayMs); 762 } 763 setAvrcpAbsoluteVolumeSupported(boolean supported)764 /*package*/ void setAvrcpAbsoluteVolumeSupported(boolean supported) { 765 synchronized (mDeviceStateLock) { 766 mBtHelper.setAvrcpAbsoluteVolumeSupported(supported); 767 } 768 } 769 getBluetoothA2dpEnabled()770 /*package*/ boolean getBluetoothA2dpEnabled() { 771 synchronized (mDeviceStateLock) { 772 return mBluetoothA2dpEnabled; 773 } 774 } 775 getA2dpCodec(@onNull BluetoothDevice device)776 /*package*/ int getA2dpCodec(@NonNull BluetoothDevice device) { 777 synchronized (mDeviceStateLock) { 778 return mBtHelper.getA2dpCodec(device); 779 } 780 } 781 dump(PrintWriter pw, String prefix)782 /*package*/ void dump(PrintWriter pw, String prefix) { 783 if (mBrokerHandler != null) { 784 pw.println(prefix + "Message handler (watch for unhandled messages):"); 785 mBrokerHandler.dump(new PrintWriterPrinter(pw), prefix + " "); 786 } else { 787 pw.println("Message handler is null"); 788 } 789 790 mDeviceInventory.dump(pw, prefix); 791 792 pw.println("\n" + prefix + "mForcedUseForComm: " 793 + AudioSystem.forceUseConfigToString(mForcedUseForComm)); 794 pw.println(prefix + "mForcedUseForCommExt: " 795 + AudioSystem.forceUseConfigToString(mForcedUseForCommExt)); 796 pw.println(prefix + "mModeOwnerPid: " + mModeOwnerPid); 797 pw.println(prefix + "Speakerphone clients:"); 798 mSpeakerphoneClients.forEach((cl) -> { 799 pw.println(" " + prefix + "pid: " + cl.getPid() + " on: " 800 + cl.isOn() + " cb: " + cl.getBinder()); }); 801 802 mBtHelper.dump(pw, prefix); 803 } 804 805 //--------------------------------------------------------------------- 806 // Internal handling of messages 807 // These methods are ALL synchronous, in response to message handling in BrokerHandler 808 // Blocking in any of those will block the message queue 809 onSetForceUse(int useCase, int config, boolean fromA2dp, String eventSource)810 private void onSetForceUse(int useCase, int config, boolean fromA2dp, String eventSource) { 811 if (useCase == AudioSystem.FOR_MEDIA) { 812 postReportNewRoutes(fromA2dp); 813 } 814 AudioService.sForceUseLogger.log( 815 new AudioServiceEvents.ForceUseEvent(useCase, config, eventSource)); 816 new MediaMetrics.Item(MediaMetrics.Name.AUDIO_FORCE_USE + MediaMetrics.SEPARATOR 817 + AudioSystem.forceUseUsageToString(useCase)) 818 .set(MediaMetrics.Property.EVENT, "onSetForceUse") 819 .set(MediaMetrics.Property.FORCE_USE_DUE_TO, eventSource) 820 .set(MediaMetrics.Property.FORCE_USE_MODE, 821 AudioSystem.forceUseConfigToString(config)) 822 .record(); 823 AudioSystem.setForceUse(useCase, config); 824 } 825 onSendBecomingNoisyIntent()826 private void onSendBecomingNoisyIntent() { 827 AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent( 828 "broadcast ACTION_AUDIO_BECOMING_NOISY")).printLog(TAG)); 829 mSystemServer.sendDeviceBecomingNoisyIntent(); 830 } 831 832 //--------------------------------------------------------------------- 833 // Message handling 834 private BrokerHandler mBrokerHandler; 835 private BrokerThread mBrokerThread; 836 private PowerManager.WakeLock mBrokerEventWakeLock; 837 setupMessaging(Context ctxt)838 private void setupMessaging(Context ctxt) { 839 final PowerManager pm = (PowerManager) ctxt.getSystemService(Context.POWER_SERVICE); 840 mBrokerEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 841 "handleAudioDeviceEvent"); 842 mBrokerThread = new BrokerThread(); 843 mBrokerThread.start(); 844 waitForBrokerHandlerCreation(); 845 } 846 waitForBrokerHandlerCreation()847 private void waitForBrokerHandlerCreation() { 848 synchronized (this) { 849 while (mBrokerHandler == null) { 850 try { 851 wait(); 852 } catch (InterruptedException e) { 853 Log.e(TAG, "Interruption while waiting on BrokerHandler"); 854 } 855 } 856 } 857 } 858 859 /** Class that handles the device broker's message queue */ 860 private class BrokerThread extends Thread { BrokerThread()861 BrokerThread() { 862 super("AudioDeviceBroker"); 863 } 864 865 @Override run()866 public void run() { 867 // Set this thread up so the handler will work on it 868 Looper.prepare(); 869 870 synchronized (AudioDeviceBroker.this) { 871 mBrokerHandler = new BrokerHandler(); 872 873 // Notify that the handler has been created 874 AudioDeviceBroker.this.notify(); 875 } 876 877 Looper.loop(); 878 } 879 } 880 881 /** Class that handles the message queue */ 882 private class BrokerHandler extends Handler { 883 884 @Override handleMessage(Message msg)885 public void handleMessage(Message msg) { 886 switch (msg.what) { 887 case MSG_RESTORE_DEVICES: 888 synchronized (mDeviceStateLock) { 889 mDeviceInventory.onRestoreDevices(); 890 mBtHelper.onAudioServerDiedRestoreA2dp(); 891 } 892 break; 893 case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE: 894 synchronized (mDeviceStateLock) { 895 mDeviceInventory.onSetWiredDeviceConnectionState( 896 (AudioDeviceInventory.WiredDeviceConnectionState) msg.obj); 897 } 898 break; 899 case MSG_I_BROADCAST_BT_CONNECTION_STATE: 900 synchronized (mDeviceStateLock) { 901 mBtHelper.onBroadcastScoConnectionState(msg.arg1); 902 } 903 break; 904 case MSG_IIL_SET_FORCE_USE: // intended fall-through 905 case MSG_IIL_SET_FORCE_BT_A2DP_USE: 906 onSetForceUse(msg.arg1, msg.arg2, 907 (msg.what == MSG_IIL_SET_FORCE_BT_A2DP_USE), (String) msg.obj); 908 break; 909 case MSG_REPORT_NEW_ROUTES: 910 case MSG_REPORT_NEW_ROUTES_A2DP: 911 synchronized (mDeviceStateLock) { 912 mDeviceInventory.onReportNewRoutes(); 913 } 914 break; 915 case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED: 916 case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED: 917 synchronized (mDeviceStateLock) { 918 mDeviceInventory.onSetA2dpSinkConnectionState( 919 (BtHelper.BluetoothA2dpDeviceInfo) msg.obj, msg.arg1); 920 } 921 break; 922 case MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE: 923 synchronized (mDeviceStateLock) { 924 mDeviceInventory.onSetA2dpSourceConnectionState( 925 (BtHelper.BluetoothA2dpDeviceInfo) msg.obj, msg.arg1); 926 } 927 break; 928 case MSG_IL_SET_HEARING_AID_CONNECTION_STATE: 929 synchronized (mDeviceStateLock) { 930 mDeviceInventory.onSetHearingAidConnectionState( 931 (BluetoothDevice) msg.obj, msg.arg1, 932 mAudioService.getHearingAidStreamType()); 933 } 934 break; 935 case MSG_BT_HEADSET_CNCT_FAILED: 936 synchronized (mSetModeLock) { 937 synchronized (mDeviceStateLock) { 938 mBtHelper.resetBluetoothSco(); 939 } 940 } 941 break; 942 case MSG_IL_BTA2DP_TIMEOUT: 943 // msg.obj == address of BTA2DP device 944 synchronized (mDeviceStateLock) { 945 mDeviceInventory.onMakeA2dpDeviceUnavailableNow((String) msg.obj, msg.arg1); 946 } 947 break; 948 case MSG_L_A2DP_DEVICE_CONFIG_CHANGE: 949 final int a2dpCodec; 950 final BluetoothDevice btDevice = (BluetoothDevice) msg.obj; 951 synchronized (mDeviceStateLock) { 952 a2dpCodec = mBtHelper.getA2dpCodec(btDevice); 953 // TODO: name of method being called on AudioDeviceInventory is currently 954 // misleading (config change vs active device change), to be 955 // reconciliated once the BT side has been updated. 956 mDeviceInventory.onBluetoothA2dpActiveDeviceChange( 957 new BtHelper.BluetoothA2dpDeviceInfo(btDevice, -1, a2dpCodec), 958 BtHelper.EVENT_DEVICE_CONFIG_CHANGE); 959 } 960 break; 961 case MSG_BROADCAST_AUDIO_BECOMING_NOISY: 962 onSendBecomingNoisyIntent(); 963 break; 964 case MSG_II_SET_HEARING_AID_VOLUME: 965 synchronized (mDeviceStateLock) { 966 mBtHelper.setHearingAidVolume(msg.arg1, msg.arg2); 967 } 968 break; 969 case MSG_I_SET_AVRCP_ABSOLUTE_VOLUME: 970 synchronized (mDeviceStateLock) { 971 mBtHelper.setAvrcpAbsoluteVolumeIndex(msg.arg1); 972 } 973 break; 974 case MSG_I_SET_MODE_OWNER_PID: 975 synchronized (mSetModeLock) { 976 synchronized (mDeviceStateLock) { 977 if (mModeOwnerPid != msg.arg1) { 978 mModeOwnerPid = msg.arg1; 979 if (msg.arg2 != AudioSystem.MODE_RINGTONE) { 980 updateSpeakerphoneOn("setNewModeOwner"); 981 } 982 if (mModeOwnerPid != 0) { 983 mBtHelper.disconnectBluetoothSco(mModeOwnerPid); 984 } 985 } 986 } 987 } 988 break; 989 case MSG_L_SCOCLIENT_DIED: 990 synchronized (mSetModeLock) { 991 synchronized (mDeviceStateLock) { 992 mBtHelper.scoClientDied(msg.obj); 993 } 994 } 995 break; 996 case MSG_L_SPEAKERPHONE_CLIENT_DIED: 997 synchronized (mDeviceStateLock) { 998 speakerphoneClientDied(msg.obj); 999 } 1000 break; 1001 case MSG_TOGGLE_HDMI: 1002 synchronized (mDeviceStateLock) { 1003 mDeviceInventory.onToggleHdmi(); 1004 } 1005 break; 1006 case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE: 1007 synchronized (mDeviceStateLock) { 1008 mDeviceInventory.onBluetoothA2dpActiveDeviceChange( 1009 (BtHelper.BluetoothA2dpDeviceInfo) msg.obj, 1010 BtHelper.EVENT_ACTIVE_DEVICE_CHANGE); 1011 } 1012 break; 1013 case MSG_DISCONNECT_A2DP: 1014 synchronized (mDeviceStateLock) { 1015 mDeviceInventory.disconnectA2dp(); 1016 } 1017 break; 1018 case MSG_DISCONNECT_A2DP_SINK: 1019 synchronized (mDeviceStateLock) { 1020 mDeviceInventory.disconnectA2dpSink(); 1021 } 1022 break; 1023 case MSG_DISCONNECT_BT_HEARING_AID: 1024 synchronized (mDeviceStateLock) { 1025 mDeviceInventory.disconnectHearingAid(); 1026 } 1027 break; 1028 case MSG_DISCONNECT_BT_HEADSET: 1029 synchronized (mSetModeLock) { 1030 synchronized (mDeviceStateLock) { 1031 mBtHelper.disconnectHeadset(); 1032 } 1033 } 1034 break; 1035 case MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP: 1036 synchronized (mDeviceStateLock) { 1037 mBtHelper.onA2dpProfileConnected((BluetoothA2dp) msg.obj); 1038 } 1039 break; 1040 case MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP_SINK: 1041 synchronized (mDeviceStateLock) { 1042 mBtHelper.onA2dpSinkProfileConnected((BluetoothProfile) msg.obj); 1043 } 1044 break; 1045 case MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEARING_AID: 1046 synchronized (mDeviceStateLock) { 1047 mBtHelper.onHearingAidProfileConnected((BluetoothHearingAid) msg.obj); 1048 } 1049 break; 1050 case MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEADSET: 1051 synchronized (mSetModeLock) { 1052 synchronized (mDeviceStateLock) { 1053 mBtHelper.onHeadsetProfileConnected((BluetoothHeadset) msg.obj); 1054 } 1055 } 1056 break; 1057 case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION: 1058 case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION: { 1059 final BtDeviceConnectionInfo info = (BtDeviceConnectionInfo) msg.obj; 1060 AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent( 1061 "msg: setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent " 1062 + " state=" + info.mState 1063 // only querying address as this is the only readily available 1064 // field on the device 1065 + " addr=" + info.mDevice.getAddress() 1066 + " prof=" + info.mProfile + " supprNoisy=" + info.mSupprNoisy 1067 + " vol=" + info.mVolume)).printLog(TAG)); 1068 synchronized (mDeviceStateLock) { 1069 mDeviceInventory.setBluetoothA2dpDeviceConnectionState( 1070 info.mDevice, info.mState, info.mProfile, info.mSupprNoisy, 1071 AudioSystem.DEVICE_NONE, info.mVolume); 1072 } 1073 } break; 1074 case MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT: { 1075 final HearingAidDeviceConnectionInfo info = 1076 (HearingAidDeviceConnectionInfo) msg.obj; 1077 AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent( 1078 "msg: setHearingAidDeviceConnectionState state=" + info.mState 1079 + " addr=" + info.mDevice.getAddress() 1080 + " supprNoisy=" + info.mSupprNoisy 1081 + " src=" + info.mEventSource)).printLog(TAG)); 1082 synchronized (mDeviceStateLock) { 1083 mDeviceInventory.setBluetoothHearingAidDeviceConnectionState( 1084 info.mDevice, info.mState, info.mSupprNoisy, info.mMusicDevice); 1085 } 1086 } break; 1087 case MSG_IL_SAVE_PREF_DEVICE_FOR_STRATEGY: { 1088 final int strategy = msg.arg1; 1089 final AudioDeviceAttributes device = (AudioDeviceAttributes) msg.obj; 1090 mDeviceInventory.onSaveSetPreferredDevice(strategy, device); 1091 } break; 1092 case MSG_I_SAVE_REMOVE_PREF_DEVICE_FOR_STRATEGY: { 1093 final int strategy = msg.arg1; 1094 mDeviceInventory.onSaveRemovePreferredDevice(strategy); 1095 } break; 1096 case MSG_CHECK_MUTE_MUSIC: 1097 checkMessagesMuteMusic(0); 1098 break; 1099 default: 1100 Log.wtf(TAG, "Invalid message " + msg.what); 1101 } 1102 1103 // Give some time to Bluetooth service to post a connection message 1104 // in case of active device switch 1105 if (MESSAGES_MUTE_MUSIC.contains(msg.what)) { 1106 sendMsg(MSG_CHECK_MUTE_MUSIC, SENDMSG_REPLACE, BTA2DP_MUTE_CHECK_DELAY_MS); 1107 } 1108 1109 if (isMessageHandledUnderWakelock(msg.what)) { 1110 try { 1111 mBrokerEventWakeLock.release(); 1112 } catch (Exception e) { 1113 Log.e(TAG, "Exception releasing wakelock", e); 1114 } 1115 } 1116 } 1117 } 1118 1119 // List of all messages. If a message has be handled under wakelock, add it to 1120 // the isMessageHandledUnderWakelock(int) method 1121 // Naming of msg indicates arguments, using JNI argument grammar 1122 // (e.g. II indicates two int args, IL indicates int and Obj arg) 1123 private static final int MSG_RESTORE_DEVICES = 1; 1124 private static final int MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE = 2; 1125 private static final int MSG_I_BROADCAST_BT_CONNECTION_STATE = 3; 1126 private static final int MSG_IIL_SET_FORCE_USE = 4; 1127 private static final int MSG_IIL_SET_FORCE_BT_A2DP_USE = 5; 1128 private static final int MSG_TOGGLE_HDMI = 6; 1129 private static final int MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE = 7; 1130 private static final int MSG_IL_SET_HEARING_AID_CONNECTION_STATE = 8; 1131 private static final int MSG_BT_HEADSET_CNCT_FAILED = 9; 1132 private static final int MSG_IL_BTA2DP_TIMEOUT = 10; 1133 1134 // process change of A2DP device configuration, obj is BluetoothDevice 1135 private static final int MSG_L_A2DP_DEVICE_CONFIG_CHANGE = 11; 1136 1137 private static final int MSG_BROADCAST_AUDIO_BECOMING_NOISY = 12; 1138 private static final int MSG_REPORT_NEW_ROUTES = 13; 1139 private static final int MSG_II_SET_HEARING_AID_VOLUME = 14; 1140 private static final int MSG_I_SET_AVRCP_ABSOLUTE_VOLUME = 15; 1141 private static final int MSG_I_SET_MODE_OWNER_PID = 16; 1142 1143 // process active A2DP device change, obj is BtHelper.BluetoothA2dpDeviceInfo 1144 private static final int MSG_L_A2DP_ACTIVE_DEVICE_CHANGE = 18; 1145 1146 private static final int MSG_DISCONNECT_A2DP = 19; 1147 private static final int MSG_DISCONNECT_A2DP_SINK = 20; 1148 private static final int MSG_DISCONNECT_BT_HEARING_AID = 21; 1149 private static final int MSG_DISCONNECT_BT_HEADSET = 22; 1150 private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP = 23; 1151 private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP_SINK = 24; 1152 private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEARING_AID = 25; 1153 private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEADSET = 26; 1154 1155 // process change of state, obj is BtHelper.BluetoothA2dpDeviceInfo 1156 private static final int MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED = 27; 1157 private static final int MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED = 28; 1158 1159 // process external command to (dis)connect an A2DP device, obj is BtDeviceConnectionInfo 1160 private static final int MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION = 29; 1161 private static final int MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION = 30; 1162 1163 // process external command to (dis)connect a hearing aid device 1164 private static final int MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT = 31; 1165 1166 // a ScoClient died in BtHelper 1167 private static final int MSG_L_SCOCLIENT_DIED = 32; 1168 private static final int MSG_IL_SAVE_PREF_DEVICE_FOR_STRATEGY = 33; 1169 private static final int MSG_I_SAVE_REMOVE_PREF_DEVICE_FOR_STRATEGY = 34; 1170 1171 private static final int MSG_L_SPEAKERPHONE_CLIENT_DIED = 35; 1172 private static final int MSG_CHECK_MUTE_MUSIC = 36; 1173 private static final int MSG_REPORT_NEW_ROUTES_A2DP = 37; 1174 1175 isMessageHandledUnderWakelock(int msgId)1176 private static boolean isMessageHandledUnderWakelock(int msgId) { 1177 switch(msgId) { 1178 case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE: 1179 case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED: 1180 case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED: 1181 case MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE: 1182 case MSG_IL_SET_HEARING_AID_CONNECTION_STATE: 1183 case MSG_IL_BTA2DP_TIMEOUT: 1184 case MSG_L_A2DP_DEVICE_CONFIG_CHANGE: 1185 case MSG_TOGGLE_HDMI: 1186 case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE: 1187 case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION: 1188 case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION: 1189 case MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT: 1190 case MSG_CHECK_MUTE_MUSIC: 1191 return true; 1192 default: 1193 return false; 1194 } 1195 } 1196 1197 // Message helper methods 1198 1199 // sendMsg() flags 1200 /** If the msg is already queued, replace it with this one. */ 1201 private static final int SENDMSG_REPLACE = 0; 1202 /** If the msg is already queued, ignore this one and leave the old. */ 1203 private static final int SENDMSG_NOOP = 1; 1204 /** If the msg is already queued, queue this one and leave the old. */ 1205 private static final int SENDMSG_QUEUE = 2; 1206 sendMsg(int msg, int existingMsgPolicy, int delay)1207 private void sendMsg(int msg, int existingMsgPolicy, int delay) { 1208 sendIILMsg(msg, existingMsgPolicy, 0, 0, null, delay); 1209 } 1210 sendILMsg(int msg, int existingMsgPolicy, int arg, Object obj, int delay)1211 private void sendILMsg(int msg, int existingMsgPolicy, int arg, Object obj, int delay) { 1212 sendIILMsg(msg, existingMsgPolicy, arg, 0, obj, delay); 1213 } 1214 sendLMsg(int msg, int existingMsgPolicy, Object obj, int delay)1215 private void sendLMsg(int msg, int existingMsgPolicy, Object obj, int delay) { 1216 sendIILMsg(msg, existingMsgPolicy, 0, 0, obj, delay); 1217 } 1218 sendIMsg(int msg, int existingMsgPolicy, int arg, int delay)1219 private void sendIMsg(int msg, int existingMsgPolicy, int arg, int delay) { 1220 sendIILMsg(msg, existingMsgPolicy, arg, 0, null, delay); 1221 } 1222 sendMsgNoDelay(int msg, int existingMsgPolicy)1223 private void sendMsgNoDelay(int msg, int existingMsgPolicy) { 1224 sendIILMsg(msg, existingMsgPolicy, 0, 0, null, 0); 1225 } 1226 sendIMsgNoDelay(int msg, int existingMsgPolicy, int arg)1227 private void sendIMsgNoDelay(int msg, int existingMsgPolicy, int arg) { 1228 sendIILMsg(msg, existingMsgPolicy, arg, 0, null, 0); 1229 } 1230 sendIIMsgNoDelay(int msg, int existingMsgPolicy, int arg1, int arg2)1231 private void sendIIMsgNoDelay(int msg, int existingMsgPolicy, int arg1, int arg2) { 1232 sendIILMsg(msg, existingMsgPolicy, arg1, arg2, null, 0); 1233 } 1234 sendILMsgNoDelay(int msg, int existingMsgPolicy, int arg, Object obj)1235 private void sendILMsgNoDelay(int msg, int existingMsgPolicy, int arg, Object obj) { 1236 sendIILMsg(msg, existingMsgPolicy, arg, 0, obj, 0); 1237 } 1238 sendLMsgNoDelay(int msg, int existingMsgPolicy, Object obj)1239 private void sendLMsgNoDelay(int msg, int existingMsgPolicy, Object obj) { 1240 sendIILMsg(msg, existingMsgPolicy, 0, 0, obj, 0); 1241 } 1242 sendIILMsgNoDelay(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj)1243 private void sendIILMsgNoDelay(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj) { 1244 sendIILMsg(msg, existingMsgPolicy, arg1, arg2, obj, 0); 1245 } 1246 sendIILMsg(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj, int delay)1247 private void sendIILMsg(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj, 1248 int delay) { 1249 if (existingMsgPolicy == SENDMSG_REPLACE) { 1250 mBrokerHandler.removeMessages(msg); 1251 } else if (existingMsgPolicy == SENDMSG_NOOP && mBrokerHandler.hasMessages(msg)) { 1252 return; 1253 } 1254 1255 if (isMessageHandledUnderWakelock(msg)) { 1256 final long identity = Binder.clearCallingIdentity(); 1257 try { 1258 mBrokerEventWakeLock.acquire(BROKER_WAKELOCK_TIMEOUT_MS); 1259 } catch (Exception e) { 1260 Log.e(TAG, "Exception acquiring wakelock", e); 1261 } 1262 Binder.restoreCallingIdentity(identity); 1263 } 1264 1265 if (MESSAGES_MUTE_MUSIC.contains(msg)) { 1266 checkMessagesMuteMusic(msg); 1267 } 1268 1269 synchronized (sLastDeviceConnectionMsgTimeLock) { 1270 long time = SystemClock.uptimeMillis() + delay; 1271 1272 switch (msg) { 1273 case MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE: 1274 case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED: 1275 case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED: 1276 case MSG_IL_SET_HEARING_AID_CONNECTION_STATE: 1277 case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE: 1278 case MSG_IL_BTA2DP_TIMEOUT: 1279 case MSG_L_A2DP_DEVICE_CONFIG_CHANGE: 1280 case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE: 1281 if (sLastDeviceConnectMsgTime >= time) { 1282 // add a little delay to make sure messages are ordered as expected 1283 time = sLastDeviceConnectMsgTime + 30; 1284 } 1285 sLastDeviceConnectMsgTime = time; 1286 break; 1287 default: 1288 break; 1289 } 1290 mBrokerHandler.sendMessageAtTime(mBrokerHandler.obtainMessage(msg, arg1, arg2, obj), 1291 time); 1292 } 1293 } 1294 1295 /** List of messages for which music is muted while processing is pending */ 1296 private static final Set<Integer> MESSAGES_MUTE_MUSIC; 1297 static { 1298 MESSAGES_MUTE_MUSIC = new HashSet<>(); 1299 MESSAGES_MUTE_MUSIC.add(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED); 1300 MESSAGES_MUTE_MUSIC.add(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED); 1301 MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONFIG_CHANGE); 1302 MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_ACTIVE_DEVICE_CHANGE); 1303 MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION); 1304 MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION); 1305 MESSAGES_MUTE_MUSIC.add(MSG_IIL_SET_FORCE_BT_A2DP_USE); 1306 MESSAGES_MUTE_MUSIC.add(MSG_REPORT_NEW_ROUTES_A2DP); 1307 } 1308 1309 private AtomicBoolean mMusicMuted = new AtomicBoolean(false); 1310 1311 /** Mutes or unmutes music according to pending A2DP messages */ checkMessagesMuteMusic(int message)1312 private void checkMessagesMuteMusic(int message) { 1313 boolean mute = message != 0; 1314 if (!mute) { 1315 for (int msg : MESSAGES_MUTE_MUSIC) { 1316 if (mBrokerHandler.hasMessages(msg)) { 1317 mute = true; 1318 break; 1319 } 1320 } 1321 } 1322 1323 if (mute != mMusicMuted.getAndSet(mute)) { 1324 mAudioService.setMusicMute(mute); 1325 } 1326 } 1327 1328 private class SpeakerphoneClient implements IBinder.DeathRecipient { 1329 private final IBinder mCb; 1330 private final int mPid; 1331 private final boolean mOn; SpeakerphoneClient(IBinder cb, int pid, boolean on)1332 SpeakerphoneClient(IBinder cb, int pid, boolean on) { 1333 mCb = cb; 1334 mPid = pid; 1335 mOn = on; 1336 } 1337 registerDeathRecipient()1338 public boolean registerDeathRecipient() { 1339 boolean status = false; 1340 try { 1341 mCb.linkToDeath(this, 0); 1342 status = true; 1343 } catch (RemoteException e) { 1344 Log.w(TAG, "SpeakerphoneClient could not link to " + mCb + " binder death"); 1345 } 1346 return status; 1347 } 1348 unregisterDeathRecipient()1349 public void unregisterDeathRecipient() { 1350 try { 1351 mCb.unlinkToDeath(this, 0); 1352 } catch (NoSuchElementException e) { 1353 Log.w(TAG, "SpeakerphoneClient could not not unregistered to binder"); 1354 } 1355 } 1356 1357 @Override binderDied()1358 public void binderDied() { 1359 postSpeakerphoneClientDied(this); 1360 } 1361 getBinder()1362 IBinder getBinder() { 1363 return mCb; 1364 } 1365 getPid()1366 int getPid() { 1367 return mPid; 1368 } 1369 isOn()1370 boolean isOn() { 1371 return mOn; 1372 } 1373 } 1374 1375 @GuardedBy("mDeviceStateLock") speakerphoneClientDied(Object obj)1376 private void speakerphoneClientDied(Object obj) { 1377 if (obj == null) { 1378 return; 1379 } 1380 Log.w(TAG, "Speaker client died"); 1381 if (removeSpeakerphoneClient(((SpeakerphoneClient) obj).getBinder(), false) != null) { 1382 updateSpeakerphoneOn("speakerphoneClientDied"); 1383 } 1384 } 1385 removeSpeakerphoneClient(IBinder cb, boolean unregister)1386 private SpeakerphoneClient removeSpeakerphoneClient(IBinder cb, boolean unregister) { 1387 for (SpeakerphoneClient cl : mSpeakerphoneClients) { 1388 if (cl.getBinder() == cb) { 1389 if (unregister) { 1390 cl.unregisterDeathRecipient(); 1391 } 1392 mSpeakerphoneClients.remove(cl); 1393 return cl; 1394 } 1395 } 1396 return null; 1397 } 1398 1399 @GuardedBy("mDeviceStateLock") addSpeakerphoneClient(IBinder cb, int pid, boolean on)1400 private boolean addSpeakerphoneClient(IBinder cb, int pid, boolean on) { 1401 // always insert new request at first position 1402 removeSpeakerphoneClient(cb, true); 1403 SpeakerphoneClient client = new SpeakerphoneClient(cb, pid, on); 1404 if (client.registerDeathRecipient()) { 1405 mSpeakerphoneClients.add(0, client); 1406 return true; 1407 } 1408 return false; 1409 } 1410 1411 @GuardedBy("mDeviceStateLock") getSpeakerphoneClientForPid(int pid)1412 private SpeakerphoneClient getSpeakerphoneClientForPid(int pid) { 1413 for (SpeakerphoneClient cl : mSpeakerphoneClients) { 1414 if (cl.getPid() == pid) { 1415 return cl; 1416 } 1417 } 1418 return null; 1419 } 1420 1421 // List of clients requesting speakerPhone ON 1422 @GuardedBy("mDeviceStateLock") 1423 private final @NonNull ArrayList<SpeakerphoneClient> mSpeakerphoneClients = 1424 new ArrayList<SpeakerphoneClient>(); 1425 1426 } 1427