1 /* 2 * Copyright 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.server.audio; 17 18 import static com.android.server.audio.AudioService.CONNECTION_STATE_CONNECTED; 19 import static com.android.server.audio.AudioService.CONNECTION_STATE_DISCONNECTED; 20 21 import android.annotation.NonNull; 22 import android.bluetooth.BluetoothA2dp; 23 import android.bluetooth.BluetoothDevice; 24 import android.bluetooth.BluetoothHeadset; 25 import android.bluetooth.BluetoothHearingAid; 26 import android.bluetooth.BluetoothProfile; 27 import android.content.ContentResolver; 28 import android.content.Context; 29 import android.content.Intent; 30 import android.media.AudioManager; 31 import android.media.AudioRoutesInfo; 32 import android.media.AudioSystem; 33 import android.media.IAudioRoutesObserver; 34 import android.os.Binder; 35 import android.os.Handler; 36 import android.os.IBinder; 37 import android.os.Looper; 38 import android.os.Message; 39 import android.os.PowerManager; 40 import android.os.SystemClock; 41 import android.os.UserHandle; 42 import android.util.Log; 43 44 import com.android.internal.annotations.GuardedBy; 45 46 47 /** @hide */ 48 /*package*/ final class AudioDeviceBroker { 49 50 private static final String TAG = "AS.AudioDeviceBroker"; 51 52 private static final long BROKER_WAKELOCK_TIMEOUT_MS = 5000; //5s 53 54 /*package*/ static final int BTA2DP_DOCK_TIMEOUT_MS = 8000; 55 // Timeout for connection to bluetooth headset service 56 /*package*/ static final int BT_HEADSET_CNCT_TIMEOUT_MS = 3000; 57 58 private final @NonNull AudioService mAudioService; 59 private final @NonNull Context mContext; 60 61 /** Forced device usage for communications sent to AudioSystem */ 62 private int mForcedUseForComm; 63 /** 64 * Externally reported force device usage state returned by getters: always consistent 65 * with requests by setters */ 66 private int mForcedUseForCommExt; 67 68 // Manages all connected devices, only ever accessed on the message loop 69 private final AudioDeviceInventory mDeviceInventory; 70 // Manages notifications to BT service 71 private final BtHelper mBtHelper; 72 73 74 //------------------------------------------------------------------- 75 // we use a different lock than mDeviceStateLock so as not to create 76 // lock contention between enqueueing a message and handling them 77 private static final Object sLastDeviceConnectionMsgTimeLock = new Object(); 78 @GuardedBy("sLastDeviceConnectionMsgTimeLock") 79 private static long sLastDeviceConnectMsgTime = 0; 80 81 // General lock to be taken whenever the state of the audio devices is to be checked or changed 82 private final Object mDeviceStateLock = new Object(); 83 84 // Request to override default use of A2DP for media. 85 @GuardedBy("mDeviceStateLock") 86 private boolean mBluetoothA2dpEnabled; 87 88 // lock always taken when accessing AudioService.mSetModeDeathHandlers 89 // TODO do not "share" the lock between AudioService and BtHelpr, see b/123769055 90 /*package*/ final Object mSetModeLock = new Object(); 91 92 //------------------------------------------------------------------- AudioDeviceBroker(@onNull Context context, @NonNull AudioService service)93 /*package*/ AudioDeviceBroker(@NonNull Context context, @NonNull AudioService service) { 94 mContext = context; 95 mAudioService = service; 96 setupMessaging(context); 97 mBtHelper = new BtHelper(this); 98 mDeviceInventory = new AudioDeviceInventory(this); 99 100 mForcedUseForComm = AudioSystem.FORCE_NONE; 101 mForcedUseForCommExt = mForcedUseForComm; 102 103 } 104 getContext()105 /*package*/ Context getContext() { 106 return mContext; 107 } 108 109 //--------------------------------------------------------------------- 110 // Communication from AudioService 111 // All methods are asynchronous and never block 112 // All permission checks are done in AudioService, all incoming calls are considered "safe" 113 // All post* methods are asynchronous 114 onSystemReady()115 /*package*/ void onSystemReady() { 116 synchronized (mSetModeLock) { 117 synchronized (mDeviceStateLock) { 118 mBtHelper.onSystemReady(); 119 } 120 } 121 } 122 onAudioServerDied()123 /*package*/ void onAudioServerDied() { 124 // Restore forced usage for communications and record 125 synchronized (mDeviceStateLock) { 126 onSetForceUse(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, "onAudioServerDied"); 127 onSetForceUse(AudioSystem.FOR_RECORD, mForcedUseForComm, "onAudioServerDied"); 128 } 129 // restore devices 130 sendMsgNoDelay(MSG_RESTORE_DEVICES, SENDMSG_REPLACE); 131 } 132 setForceUse_Async(int useCase, int config, String eventSource)133 /*package*/ void setForceUse_Async(int useCase, int config, String eventSource) { 134 sendIILMsgNoDelay(MSG_IIL_SET_FORCE_USE, SENDMSG_QUEUE, 135 useCase, config, eventSource); 136 } 137 toggleHdmiIfConnected_Async()138 /*package*/ void toggleHdmiIfConnected_Async() { 139 sendMsgNoDelay(MSG_TOGGLE_HDMI, SENDMSG_QUEUE); 140 } 141 disconnectAllBluetoothProfiles()142 /*package*/ void disconnectAllBluetoothProfiles() { 143 synchronized (mDeviceStateLock) { 144 mBtHelper.disconnectAllBluetoothProfiles(); 145 } 146 } 147 148 /** 149 * Handle BluetoothHeadset intents where the action is one of 150 * {@link BluetoothHeadset#ACTION_ACTIVE_DEVICE_CHANGED} or 151 * {@link BluetoothHeadset#ACTION_AUDIO_STATE_CHANGED}. 152 * @param intent 153 */ receiveBtEvent(@onNull Intent intent)154 /*package*/ void receiveBtEvent(@NonNull Intent intent) { 155 synchronized (mSetModeLock) { 156 synchronized (mDeviceStateLock) { 157 mBtHelper.receiveBtEvent(intent); 158 } 159 } 160 } 161 setBluetoothA2dpOn_Async(boolean on, String source)162 /*package*/ void setBluetoothA2dpOn_Async(boolean on, String source) { 163 synchronized (mDeviceStateLock) { 164 if (mBluetoothA2dpEnabled == on) { 165 return; 166 } 167 mBluetoothA2dpEnabled = on; 168 mBrokerHandler.removeMessages(MSG_IIL_SET_FORCE_BT_A2DP_USE); 169 sendIILMsgNoDelay(MSG_IIL_SET_FORCE_BT_A2DP_USE, SENDMSG_QUEUE, 170 AudioSystem.FOR_MEDIA, 171 mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP, 172 source); 173 } 174 } 175 176 /** 177 * Turns speakerphone on/off 178 * @param on 179 * @param eventSource for logging purposes 180 * @return true if speakerphone state changed 181 */ setSpeakerphoneOn(boolean on, String eventSource)182 /*package*/ boolean setSpeakerphoneOn(boolean on, String eventSource) { 183 synchronized (mDeviceStateLock) { 184 final boolean wasOn = isSpeakerphoneOn(); 185 if (on) { 186 if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) { 187 setForceUse_Async(AudioSystem.FOR_RECORD, AudioSystem.FORCE_NONE, eventSource); 188 } 189 mForcedUseForComm = AudioSystem.FORCE_SPEAKER; 190 } else if (mForcedUseForComm == AudioSystem.FORCE_SPEAKER) { 191 mForcedUseForComm = AudioSystem.FORCE_NONE; 192 } 193 194 mForcedUseForCommExt = mForcedUseForComm; 195 setForceUse_Async(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, eventSource); 196 return (wasOn != isSpeakerphoneOn()); 197 } 198 } 199 isSpeakerphoneOn()200 /*package*/ boolean isSpeakerphoneOn() { 201 synchronized (mDeviceStateLock) { 202 return (mForcedUseForCommExt == AudioSystem.FORCE_SPEAKER); 203 } 204 } 205 setWiredDeviceConnectionState(int type, @AudioService.ConnectionState int state, String address, String name, String caller)206 /*package*/ void setWiredDeviceConnectionState(int type, 207 @AudioService.ConnectionState int state, String address, String name, 208 String caller) { 209 //TODO move logging here just like in setBluetooth* methods 210 synchronized (mDeviceStateLock) { 211 mDeviceInventory.setWiredDeviceConnectionState(type, state, address, name, caller); 212 } 213 } 214 215 private static final class BtDeviceConnectionInfo { 216 final @NonNull BluetoothDevice mDevice; 217 final @AudioService.BtProfileConnectionState int mState; 218 final int mProfile; 219 final boolean mSupprNoisy; 220 final int mVolume; 221 BtDeviceConnectionInfo(@onNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state, int profile, boolean suppressNoisyIntent, int vol)222 BtDeviceConnectionInfo(@NonNull BluetoothDevice device, 223 @AudioService.BtProfileConnectionState int state, 224 int profile, boolean suppressNoisyIntent, int vol) { 225 mDevice = device; 226 mState = state; 227 mProfile = profile; 228 mSupprNoisy = suppressNoisyIntent; 229 mVolume = vol; 230 } 231 } 232 postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent( @onNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state, int profile, boolean suppressNoisyIntent, int a2dpVolume)233 /*package*/ void postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent( 234 @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state, 235 int profile, boolean suppressNoisyIntent, int a2dpVolume) { 236 final BtDeviceConnectionInfo info = new BtDeviceConnectionInfo(device, state, profile, 237 suppressNoisyIntent, a2dpVolume); 238 239 // TODO add a check to try to remove unprocessed messages for the same device (the old 240 // check didn't work), and make sure it doesn't conflict with config change message 241 sendLMsgNoDelay(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT, SENDMSG_QUEUE, info); 242 } 243 244 private static final class HearingAidDeviceConnectionInfo { 245 final @NonNull BluetoothDevice mDevice; 246 final @AudioService.BtProfileConnectionState int mState; 247 final boolean mSupprNoisy; 248 final int mMusicDevice; 249 final @NonNull String mEventSource; 250 HearingAidDeviceConnectionInfo(@onNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state, boolean suppressNoisyIntent, int musicDevice, @NonNull String eventSource)251 HearingAidDeviceConnectionInfo(@NonNull BluetoothDevice device, 252 @AudioService.BtProfileConnectionState int state, 253 boolean suppressNoisyIntent, int musicDevice, @NonNull String eventSource) { 254 mDevice = device; 255 mState = state; 256 mSupprNoisy = suppressNoisyIntent; 257 mMusicDevice = musicDevice; 258 mEventSource = eventSource; 259 } 260 } 261 postBluetoothHearingAidDeviceConnectionState( @onNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state, boolean suppressNoisyIntent, int musicDevice, @NonNull String eventSource)262 /*package*/ void postBluetoothHearingAidDeviceConnectionState( 263 @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state, 264 boolean suppressNoisyIntent, int musicDevice, @NonNull String eventSource) { 265 final HearingAidDeviceConnectionInfo info = new HearingAidDeviceConnectionInfo( 266 device, state, suppressNoisyIntent, musicDevice, eventSource); 267 sendLMsgNoDelay(MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT, SENDMSG_QUEUE, info); 268 } 269 270 // never called by system components setBluetoothScoOnByApp(boolean on)271 /*package*/ void setBluetoothScoOnByApp(boolean on) { 272 synchronized (mDeviceStateLock) { 273 mForcedUseForCommExt = on ? AudioSystem.FORCE_BT_SCO : AudioSystem.FORCE_NONE; 274 } 275 } 276 isBluetoothScoOnForApp()277 /*package*/ boolean isBluetoothScoOnForApp() { 278 synchronized (mDeviceStateLock) { 279 return mForcedUseForCommExt == AudioSystem.FORCE_BT_SCO; 280 } 281 } 282 setBluetoothScoOn(boolean on, String eventSource)283 /*package*/ void setBluetoothScoOn(boolean on, String eventSource) { 284 //Log.i(TAG, "setBluetoothScoOnInt: " + on + " " + eventSource); 285 synchronized (mDeviceStateLock) { 286 if (on) { 287 // do not accept SCO ON if SCO audio is not connected 288 if (!mBtHelper.isBluetoothScoOn()) { 289 mForcedUseForCommExt = AudioSystem.FORCE_BT_SCO; 290 return; 291 } 292 mForcedUseForComm = AudioSystem.FORCE_BT_SCO; 293 } else if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) { 294 mForcedUseForComm = AudioSystem.FORCE_NONE; 295 } 296 mForcedUseForCommExt = mForcedUseForComm; 297 AudioSystem.setParameters("BT_SCO=" + (on ? "on" : "off")); 298 sendIILMsgNoDelay(MSG_IIL_SET_FORCE_USE, SENDMSG_QUEUE, 299 AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, eventSource); 300 sendIILMsgNoDelay(MSG_IIL_SET_FORCE_USE, SENDMSG_QUEUE, 301 AudioSystem.FOR_RECORD, mForcedUseForComm, eventSource); 302 } 303 // Un-mute ringtone stream volume 304 mAudioService.postUpdateRingerModeServiceInt(); 305 } 306 startWatchingRoutes(IAudioRoutesObserver observer)307 /*package*/ AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) { 308 synchronized (mDeviceStateLock) { 309 return mDeviceInventory.startWatchingRoutes(observer); 310 } 311 } 312 getCurAudioRoutes()313 /*package*/ AudioRoutesInfo getCurAudioRoutes() { 314 synchronized (mDeviceStateLock) { 315 return mDeviceInventory.getCurAudioRoutes(); 316 } 317 } 318 isAvrcpAbsoluteVolumeSupported()319 /*package*/ boolean isAvrcpAbsoluteVolumeSupported() { 320 synchronized (mDeviceStateLock) { 321 return mBtHelper.isAvrcpAbsoluteVolumeSupported(); 322 } 323 } 324 isBluetoothA2dpOn()325 /*package*/ boolean isBluetoothA2dpOn() { 326 synchronized (mDeviceStateLock) { 327 return mBluetoothA2dpEnabled; 328 } 329 } 330 postSetAvrcpAbsoluteVolumeIndex(int index)331 /*package*/ void postSetAvrcpAbsoluteVolumeIndex(int index) { 332 sendIMsgNoDelay(MSG_I_SET_AVRCP_ABSOLUTE_VOLUME, SENDMSG_REPLACE, index); 333 } 334 postSetHearingAidVolumeIndex(int index, int streamType)335 /*package*/ void postSetHearingAidVolumeIndex(int index, int streamType) { 336 sendIIMsgNoDelay(MSG_II_SET_HEARING_AID_VOLUME, SENDMSG_REPLACE, index, streamType); 337 } 338 postDisconnectBluetoothSco(int exceptPid)339 /*package*/ void postDisconnectBluetoothSco(int exceptPid) { 340 sendIMsgNoDelay(MSG_I_DISCONNECT_BT_SCO, SENDMSG_REPLACE, exceptPid); 341 } 342 postBluetoothA2dpDeviceConfigChange(@onNull BluetoothDevice device)343 /*package*/ void postBluetoothA2dpDeviceConfigChange(@NonNull BluetoothDevice device) { 344 sendLMsgNoDelay(MSG_L_A2DP_DEVICE_CONFIG_CHANGE, SENDMSG_QUEUE, device); 345 } 346 347 @GuardedBy("mSetModeLock") startBluetoothScoForClient_Sync(IBinder cb, int scoAudioMode, @NonNull String eventSource)348 /*package*/ void startBluetoothScoForClient_Sync(IBinder cb, int scoAudioMode, 349 @NonNull String eventSource) { 350 synchronized (mDeviceStateLock) { 351 mBtHelper.startBluetoothScoForClient(cb, scoAudioMode, eventSource); 352 } 353 } 354 355 @GuardedBy("mSetModeLock") stopBluetoothScoForClient_Sync(IBinder cb, @NonNull String eventSource)356 /*package*/ void stopBluetoothScoForClient_Sync(IBinder cb, @NonNull String eventSource) { 357 synchronized (mDeviceStateLock) { 358 mBtHelper.stopBluetoothScoForClient(cb, eventSource); 359 } 360 } 361 362 //--------------------------------------------------------------------- 363 // Communication with (to) AudioService 364 //TODO check whether the AudioService methods are candidates to move here postAccessoryPlugMediaUnmute(int device)365 /*package*/ void postAccessoryPlugMediaUnmute(int device) { 366 mAudioService.postAccessoryPlugMediaUnmute(device); 367 } 368 getVssVolumeForDevice(int streamType, int device)369 /*package*/ int getVssVolumeForDevice(int streamType, int device) { 370 return mAudioService.getVssVolumeForDevice(streamType, device); 371 } 372 getModeOwnerPid()373 /*package*/ int getModeOwnerPid() { 374 return mAudioService.getModeOwnerPid(); 375 } 376 getDeviceForStream(int streamType)377 /*package*/ int getDeviceForStream(int streamType) { 378 return mAudioService.getDeviceForStream(streamType); 379 } 380 postApplyVolumeOnDevice(int streamType, int device, String caller)381 /*package*/ void postApplyVolumeOnDevice(int streamType, int device, String caller) { 382 mAudioService.postApplyVolumeOnDevice(streamType, device, caller); 383 } 384 postSetVolumeIndexOnDevice(int streamType, int vssVolIndex, int device, String caller)385 /*package*/ void postSetVolumeIndexOnDevice(int streamType, int vssVolIndex, int device, 386 String caller) { 387 mAudioService.postSetVolumeIndexOnDevice(streamType, vssVolIndex, device, caller); 388 } 389 postObserveDevicesForAllStreams()390 /*packages*/ void postObserveDevicesForAllStreams() { 391 mAudioService.postObserveDevicesForAllStreams(); 392 } 393 isInCommunication()394 /*package*/ boolean isInCommunication() { 395 return mAudioService.isInCommunication(); 396 } 397 hasMediaDynamicPolicy()398 /*package*/ boolean hasMediaDynamicPolicy() { 399 return mAudioService.hasMediaDynamicPolicy(); 400 } 401 getContentResolver()402 /*package*/ ContentResolver getContentResolver() { 403 return mAudioService.getContentResolver(); 404 } 405 checkMusicActive(int deviceType, String caller)406 /*package*/ void checkMusicActive(int deviceType, String caller) { 407 mAudioService.checkMusicActive(deviceType, caller); 408 } 409 checkVolumeCecOnHdmiConnection( @udioService.ConnectionState int state, String caller)410 /*package*/ void checkVolumeCecOnHdmiConnection( 411 @AudioService.ConnectionState int state, String caller) { 412 mAudioService.postCheckVolumeCecOnHdmiConnection(state, caller); 413 } 414 hasAudioFocusUsers()415 /*package*/ boolean hasAudioFocusUsers() { 416 return mAudioService.hasAudioFocusUsers(); 417 } 418 419 //--------------------------------------------------------------------- 420 // Message handling on behalf of helper classes postBroadcastScoConnectionState(int state)421 /*package*/ void postBroadcastScoConnectionState(int state) { 422 sendIMsgNoDelay(MSG_I_BROADCAST_BT_CONNECTION_STATE, SENDMSG_QUEUE, state); 423 } 424 postBroadcastBecomingNoisy()425 /*package*/ void postBroadcastBecomingNoisy() { 426 sendMsgNoDelay(MSG_BROADCAST_AUDIO_BECOMING_NOISY, SENDMSG_REPLACE); 427 } 428 postA2dpSinkConnection(int state, @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo, int delay)429 /*package*/ void postA2dpSinkConnection(int state, 430 @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo, int delay) { 431 sendILMsg(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE, SENDMSG_QUEUE, 432 state, btDeviceInfo, delay); 433 } 434 postA2dpSourceConnection(int state, @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo, int delay)435 /*package*/ void postA2dpSourceConnection(int state, 436 @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo, int delay) { 437 sendILMsg(MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE, SENDMSG_QUEUE, 438 state, btDeviceInfo, delay); 439 } 440 postSetWiredDeviceConnectionState( AudioDeviceInventory.WiredDeviceConnectionState connectionState, int delay)441 /*package*/ void postSetWiredDeviceConnectionState( 442 AudioDeviceInventory.WiredDeviceConnectionState connectionState, int delay) { 443 sendLMsg(MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE, SENDMSG_QUEUE, connectionState, delay); 444 } 445 postSetHearingAidConnectionState( @udioService.BtProfileConnectionState int state, @NonNull BluetoothDevice device, int delay)446 /*package*/ void postSetHearingAidConnectionState( 447 @AudioService.BtProfileConnectionState int state, 448 @NonNull BluetoothDevice device, int delay) { 449 sendILMsg(MSG_IL_SET_HEARING_AID_CONNECTION_STATE, SENDMSG_QUEUE, 450 state, 451 device, 452 delay); 453 } 454 postDisconnectA2dp()455 /*package*/ void postDisconnectA2dp() { 456 sendMsgNoDelay(MSG_DISCONNECT_A2DP, SENDMSG_QUEUE); 457 } 458 postDisconnectA2dpSink()459 /*package*/ void postDisconnectA2dpSink() { 460 sendMsgNoDelay(MSG_DISCONNECT_A2DP_SINK, SENDMSG_QUEUE); 461 } 462 postDisconnectHearingAid()463 /*package*/ void postDisconnectHearingAid() { 464 sendMsgNoDelay(MSG_DISCONNECT_BT_HEARING_AID, SENDMSG_QUEUE); 465 } 466 postDisconnectHeadset()467 /*package*/ void postDisconnectHeadset() { 468 sendMsgNoDelay(MSG_DISCONNECT_BT_HEADSET, SENDMSG_QUEUE); 469 } 470 postBtA2dpProfileConnected(BluetoothA2dp a2dpProfile)471 /*package*/ void postBtA2dpProfileConnected(BluetoothA2dp a2dpProfile) { 472 sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP, SENDMSG_QUEUE, a2dpProfile); 473 } 474 postBtA2dpSinkProfileConnected(BluetoothProfile profile)475 /*package*/ void postBtA2dpSinkProfileConnected(BluetoothProfile profile) { 476 sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP_SINK, SENDMSG_QUEUE, profile); 477 } 478 postBtHeasetProfileConnected(BluetoothHeadset headsetProfile)479 /*package*/ void postBtHeasetProfileConnected(BluetoothHeadset headsetProfile) { 480 sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEADSET, SENDMSG_QUEUE, headsetProfile); 481 } 482 postBtHearingAidProfileConnected(BluetoothHearingAid hearingAidProfile)483 /*package*/ void postBtHearingAidProfileConnected(BluetoothHearingAid hearingAidProfile) { 484 sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEARING_AID, SENDMSG_QUEUE, 485 hearingAidProfile); 486 } 487 postScoClientDied(Object obj)488 /*package*/ void postScoClientDied(Object obj) { 489 sendLMsgNoDelay(MSG_L_SCOCLIENT_DIED, SENDMSG_QUEUE, obj); 490 } 491 492 //--------------------------------------------------------------------- 493 // Method forwarding between the helper classes (BtHelper, AudioDeviceInventory) 494 // only call from a "handle"* method or "on"* method 495 496 // Handles request to override default use of A2DP for media. 497 //@GuardedBy("mConnectedDevices") setBluetoothA2dpOnInt(boolean on, String source)498 /*package*/ void setBluetoothA2dpOnInt(boolean on, String source) { 499 // for logging only 500 final String eventSource = new StringBuilder("setBluetoothA2dpOn(").append(on) 501 .append(") from u/pid:").append(Binder.getCallingUid()).append("/") 502 .append(Binder.getCallingPid()).append(" src:").append(source).toString(); 503 504 synchronized (mDeviceStateLock) { 505 mBluetoothA2dpEnabled = on; 506 mBrokerHandler.removeMessages(MSG_IIL_SET_FORCE_BT_A2DP_USE); 507 onSetForceUse( 508 AudioSystem.FOR_MEDIA, 509 mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP, 510 eventSource); 511 } 512 } 513 handleDeviceConnection(boolean connect, int device, String address, String deviceName)514 /*package*/ boolean handleDeviceConnection(boolean connect, int device, String address, 515 String deviceName) { 516 synchronized (mDeviceStateLock) { 517 return mDeviceInventory.handleDeviceConnection(connect, device, address, deviceName); 518 } 519 } 520 521 @GuardedBy("mDeviceStateLock") handleSetA2dpSinkConnectionState(@luetoothProfile.BtProfileState int state, @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo)522 /*package*/ void handleSetA2dpSinkConnectionState(@BluetoothProfile.BtProfileState int state, 523 @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo) { 524 final int intState = (state == BluetoothA2dp.STATE_CONNECTED) 525 ? CONNECTION_STATE_CONNECTED : CONNECTION_STATE_DISCONNECTED; 526 final int delay = mDeviceInventory.checkSendBecomingNoisyIntent( 527 AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, intState, 528 AudioSystem.DEVICE_NONE); 529 final String addr = btDeviceInfo == null ? "null" : btDeviceInfo.getBtDevice().getAddress(); 530 531 if (AudioService.DEBUG_DEVICES) { 532 Log.d(TAG, "handleSetA2dpSinkConnectionState btDevice= " + btDeviceInfo 533 + " state= " + state 534 + " is dock: " + btDeviceInfo.getBtDevice().isBluetoothDock()); 535 } 536 sendILMsg(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE, SENDMSG_QUEUE, 537 state, btDeviceInfo, delay); 538 } 539 postSetA2dpSourceConnectionState(@luetoothProfile.BtProfileState int state, @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo)540 /*package*/ void postSetA2dpSourceConnectionState(@BluetoothProfile.BtProfileState int state, 541 @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo) { 542 final int intState = (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0; 543 sendILMsgNoDelay(MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE, SENDMSG_QUEUE, state, 544 btDeviceInfo); 545 } 546 handleFailureToConnectToBtHeadsetService(int delay)547 /*package*/ void handleFailureToConnectToBtHeadsetService(int delay) { 548 sendMsg(MSG_BT_HEADSET_CNCT_FAILED, SENDMSG_REPLACE, delay); 549 } 550 handleCancelFailureToConnectToBtHeadsetService()551 /*package*/ void handleCancelFailureToConnectToBtHeadsetService() { 552 mBrokerHandler.removeMessages(MSG_BT_HEADSET_CNCT_FAILED); 553 } 554 postReportNewRoutes()555 /*package*/ void postReportNewRoutes() { 556 sendMsgNoDelay(MSG_REPORT_NEW_ROUTES, SENDMSG_NOOP); 557 } 558 cancelA2dpDockTimeout()559 /*package*/ void cancelA2dpDockTimeout() { 560 mBrokerHandler.removeMessages(MSG_IL_BTA2DP_DOCK_TIMEOUT); 561 } 562 postA2dpActiveDeviceChange( @onNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo)563 /*package*/ void postA2dpActiveDeviceChange( 564 @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo) { 565 sendLMsgNoDelay(MSG_L_A2DP_ACTIVE_DEVICE_CHANGE, SENDMSG_QUEUE, btDeviceInfo); 566 } 567 hasScheduledA2dpDockTimeout()568 /*package*/ boolean hasScheduledA2dpDockTimeout() { 569 return mBrokerHandler.hasMessages(MSG_IL_BTA2DP_DOCK_TIMEOUT); 570 } 571 572 // must be called synchronized on mConnectedDevices hasScheduledA2dpSinkConnectionState(BluetoothDevice btDevice)573 /*package*/ boolean hasScheduledA2dpSinkConnectionState(BluetoothDevice btDevice) { 574 return mBrokerHandler.hasMessages(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE, 575 new BtHelper.BluetoothA2dpDeviceInfo(btDevice)); 576 } 577 setA2dpDockTimeout(String address, int a2dpCodec, int delayMs)578 /*package*/ void setA2dpDockTimeout(String address, int a2dpCodec, int delayMs) { 579 sendILMsg(MSG_IL_BTA2DP_DOCK_TIMEOUT, SENDMSG_QUEUE, a2dpCodec, address, delayMs); 580 } 581 setAvrcpAbsoluteVolumeSupported(boolean supported)582 /*package*/ void setAvrcpAbsoluteVolumeSupported(boolean supported) { 583 synchronized (mDeviceStateLock) { 584 mBtHelper.setAvrcpAbsoluteVolumeSupported(supported); 585 } 586 } 587 getBluetoothA2dpEnabled()588 /*package*/ boolean getBluetoothA2dpEnabled() { 589 synchronized (mDeviceStateLock) { 590 return mBluetoothA2dpEnabled; 591 } 592 } 593 getA2dpCodec(@onNull BluetoothDevice device)594 /*package*/ int getA2dpCodec(@NonNull BluetoothDevice device) { 595 synchronized (mDeviceStateLock) { 596 return mBtHelper.getA2dpCodec(device); 597 } 598 } 599 600 //--------------------------------------------------------------------- 601 // Internal handling of messages 602 // These methods are ALL synchronous, in response to message handling in BrokerHandler 603 // Blocking in any of those will block the message queue 604 onSetForceUse(int useCase, int config, String eventSource)605 private void onSetForceUse(int useCase, int config, String eventSource) { 606 if (useCase == AudioSystem.FOR_MEDIA) { 607 postReportNewRoutes(); 608 } 609 AudioService.sForceUseLogger.log( 610 new AudioServiceEvents.ForceUseEvent(useCase, config, eventSource)); 611 AudioSystem.setForceUse(useCase, config); 612 } 613 onSendBecomingNoisyIntent()614 private void onSendBecomingNoisyIntent() { 615 AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent( 616 "broadcast ACTION_AUDIO_BECOMING_NOISY")).printLog(TAG)); 617 sendBroadcastToAll(new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY)); 618 } 619 620 //--------------------------------------------------------------------- 621 // Message handling 622 private BrokerHandler mBrokerHandler; 623 private BrokerThread mBrokerThread; 624 private PowerManager.WakeLock mBrokerEventWakeLock; 625 setupMessaging(Context ctxt)626 private void setupMessaging(Context ctxt) { 627 final PowerManager pm = (PowerManager) ctxt.getSystemService(Context.POWER_SERVICE); 628 mBrokerEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 629 "handleAudioDeviceEvent"); 630 mBrokerThread = new BrokerThread(); 631 mBrokerThread.start(); 632 waitForBrokerHandlerCreation(); 633 } 634 waitForBrokerHandlerCreation()635 private void waitForBrokerHandlerCreation() { 636 synchronized (this) { 637 while (mBrokerHandler == null) { 638 try { 639 wait(); 640 } catch (InterruptedException e) { 641 Log.e(TAG, "Interruption while waiting on BrokerHandler"); 642 } 643 } 644 } 645 } 646 647 /** Class that handles the device broker's message queue */ 648 private class BrokerThread extends Thread { BrokerThread()649 BrokerThread() { 650 super("AudioDeviceBroker"); 651 } 652 653 @Override run()654 public void run() { 655 // Set this thread up so the handler will work on it 656 Looper.prepare(); 657 658 synchronized (AudioDeviceBroker.this) { 659 mBrokerHandler = new BrokerHandler(); 660 661 // Notify that the handler has been created 662 AudioDeviceBroker.this.notify(); 663 } 664 665 Looper.loop(); 666 } 667 } 668 669 /** Class that handles the message queue */ 670 private class BrokerHandler extends Handler { 671 672 @Override handleMessage(Message msg)673 public void handleMessage(Message msg) { 674 switch (msg.what) { 675 case MSG_RESTORE_DEVICES: 676 synchronized (mDeviceStateLock) { 677 mDeviceInventory.onRestoreDevices(); 678 mBtHelper.onAudioServerDiedRestoreA2dp(); 679 } 680 break; 681 case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE: 682 synchronized (mDeviceStateLock) { 683 mDeviceInventory.onSetWiredDeviceConnectionState( 684 (AudioDeviceInventory.WiredDeviceConnectionState) msg.obj); 685 } 686 break; 687 case MSG_I_BROADCAST_BT_CONNECTION_STATE: 688 synchronized (mDeviceStateLock) { 689 mBtHelper.onBroadcastScoConnectionState(msg.arg1); 690 } 691 break; 692 case MSG_IIL_SET_FORCE_USE: // intended fall-through 693 case MSG_IIL_SET_FORCE_BT_A2DP_USE: 694 onSetForceUse(msg.arg1, msg.arg2, (String) msg.obj); 695 break; 696 case MSG_REPORT_NEW_ROUTES: 697 synchronized (mDeviceStateLock) { 698 mDeviceInventory.onReportNewRoutes(); 699 } 700 break; 701 case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE: 702 synchronized (mDeviceStateLock) { 703 mDeviceInventory.onSetA2dpSinkConnectionState( 704 (BtHelper.BluetoothA2dpDeviceInfo) msg.obj, msg.arg1); 705 } 706 break; 707 case MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE: 708 synchronized (mDeviceStateLock) { 709 mDeviceInventory.onSetA2dpSourceConnectionState( 710 (BtHelper.BluetoothA2dpDeviceInfo) msg.obj, msg.arg1); 711 } 712 break; 713 case MSG_IL_SET_HEARING_AID_CONNECTION_STATE: 714 synchronized (mDeviceStateLock) { 715 mDeviceInventory.onSetHearingAidConnectionState( 716 (BluetoothDevice) msg.obj, msg.arg1, 717 mAudioService.getHearingAidStreamType()); 718 } 719 break; 720 case MSG_BT_HEADSET_CNCT_FAILED: 721 synchronized (mSetModeLock) { 722 synchronized (mDeviceStateLock) { 723 mBtHelper.resetBluetoothSco(); 724 } 725 } 726 break; 727 case MSG_IL_BTA2DP_DOCK_TIMEOUT: 728 // msg.obj == address of BTA2DP device 729 synchronized (mDeviceStateLock) { 730 mDeviceInventory.onMakeA2dpDeviceUnavailableNow((String) msg.obj, msg.arg1); 731 } 732 break; 733 case MSG_L_A2DP_DEVICE_CONFIG_CHANGE: 734 final int a2dpCodec; 735 final BluetoothDevice btDevice = (BluetoothDevice) msg.obj; 736 synchronized (mDeviceStateLock) { 737 a2dpCodec = mBtHelper.getA2dpCodec(btDevice); 738 mDeviceInventory.onBluetoothA2dpActiveDeviceChange( 739 new BtHelper.BluetoothA2dpDeviceInfo(btDevice, -1, a2dpCodec), 740 BtHelper.EVENT_DEVICE_CONFIG_CHANGE); 741 } 742 break; 743 case MSG_BROADCAST_AUDIO_BECOMING_NOISY: 744 onSendBecomingNoisyIntent(); 745 break; 746 case MSG_II_SET_HEARING_AID_VOLUME: 747 synchronized (mDeviceStateLock) { 748 mBtHelper.setHearingAidVolume(msg.arg1, msg.arg2); 749 } 750 break; 751 case MSG_I_SET_AVRCP_ABSOLUTE_VOLUME: 752 synchronized (mDeviceStateLock) { 753 mBtHelper.setAvrcpAbsoluteVolumeIndex(msg.arg1); 754 } 755 break; 756 case MSG_I_DISCONNECT_BT_SCO: 757 synchronized (mSetModeLock) { 758 synchronized (mDeviceStateLock) { 759 mBtHelper.disconnectBluetoothSco(msg.arg1); 760 } 761 } 762 break; 763 case MSG_L_SCOCLIENT_DIED: 764 synchronized (mSetModeLock) { 765 synchronized (mDeviceStateLock) { 766 mBtHelper.scoClientDied(msg.obj); 767 } 768 } 769 break; 770 case MSG_TOGGLE_HDMI: 771 synchronized (mDeviceStateLock) { 772 mDeviceInventory.onToggleHdmi(); 773 } 774 break; 775 case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE: 776 synchronized (mDeviceStateLock) { 777 mDeviceInventory.onBluetoothA2dpActiveDeviceChange( 778 (BtHelper.BluetoothA2dpDeviceInfo) msg.obj, 779 BtHelper.EVENT_ACTIVE_DEVICE_CHANGE); 780 } 781 break; 782 case MSG_DISCONNECT_A2DP: 783 synchronized (mDeviceStateLock) { 784 mDeviceInventory.disconnectA2dp(); 785 } 786 break; 787 case MSG_DISCONNECT_A2DP_SINK: 788 synchronized (mDeviceStateLock) { 789 mDeviceInventory.disconnectA2dpSink(); 790 } 791 break; 792 case MSG_DISCONNECT_BT_HEARING_AID: 793 synchronized (mDeviceStateLock) { 794 mDeviceInventory.disconnectHearingAid(); 795 } 796 break; 797 case MSG_DISCONNECT_BT_HEADSET: 798 synchronized (mSetModeLock) { 799 synchronized (mDeviceStateLock) { 800 mBtHelper.disconnectHeadset(); 801 } 802 } 803 break; 804 case MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP: 805 synchronized (mDeviceStateLock) { 806 mBtHelper.onA2dpProfileConnected((BluetoothA2dp) msg.obj); 807 } 808 break; 809 case MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP_SINK: 810 synchronized (mDeviceStateLock) { 811 mBtHelper.onA2dpSinkProfileConnected((BluetoothProfile) msg.obj); 812 } 813 break; 814 case MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEARING_AID: 815 synchronized (mDeviceStateLock) { 816 mBtHelper.onHearingAidProfileConnected((BluetoothHearingAid) msg.obj); 817 } 818 break; 819 case MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEADSET: 820 synchronized (mSetModeLock) { 821 synchronized (mDeviceStateLock) { 822 mBtHelper.onHeadsetProfileConnected((BluetoothHeadset) msg.obj); 823 } 824 } 825 break; 826 case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT: { 827 final BtDeviceConnectionInfo info = (BtDeviceConnectionInfo) msg.obj; 828 AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent( 829 "setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent " 830 + " state=" + info.mState 831 // only querying address as this is the only readily available 832 // field on the device 833 + " addr=" + info.mDevice.getAddress() 834 + " prof=" + info.mProfile + " supprNoisy=" + info.mSupprNoisy 835 + " vol=" + info.mVolume)).printLog(TAG)); 836 synchronized (mDeviceStateLock) { 837 mDeviceInventory.setBluetoothA2dpDeviceConnectionState( 838 info.mDevice, info.mState, info.mProfile, info.mSupprNoisy, 839 AudioSystem.DEVICE_NONE, info.mVolume); 840 } 841 } break; 842 case MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT: { 843 final HearingAidDeviceConnectionInfo info = 844 (HearingAidDeviceConnectionInfo) msg.obj; 845 AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent( 846 "setHearingAidDeviceConnectionState state=" + info.mState 847 + " addr=" + info.mDevice.getAddress() 848 + " supprNoisy=" + info.mSupprNoisy 849 + " src=" + info.mEventSource)).printLog(TAG)); 850 synchronized (mDeviceStateLock) { 851 mDeviceInventory.setBluetoothHearingAidDeviceConnectionState( 852 info.mDevice, info.mState, info.mSupprNoisy, info.mMusicDevice); 853 } 854 } break; 855 default: 856 Log.wtf(TAG, "Invalid message " + msg.what); 857 } 858 if (isMessageHandledUnderWakelock(msg.what)) { 859 try { 860 mBrokerEventWakeLock.release(); 861 } catch (Exception e) { 862 Log.e(TAG, "Exception releasing wakelock", e); 863 } 864 } 865 } 866 } 867 868 // List of all messages. If a message has be handled under wakelock, add it to 869 // the isMessageHandledUnderWakelock(int) method 870 // Naming of msg indicates arguments, using JNI argument grammar 871 // (e.g. II indicates two int args, IL indicates int and Obj arg) 872 private static final int MSG_RESTORE_DEVICES = 1; 873 private static final int MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE = 2; 874 private static final int MSG_I_BROADCAST_BT_CONNECTION_STATE = 3; 875 private static final int MSG_IIL_SET_FORCE_USE = 4; 876 private static final int MSG_IIL_SET_FORCE_BT_A2DP_USE = 5; 877 private static final int MSG_IL_SET_A2DP_SINK_CONNECTION_STATE = 6; 878 private static final int MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE = 7; 879 private static final int MSG_IL_SET_HEARING_AID_CONNECTION_STATE = 8; 880 private static final int MSG_BT_HEADSET_CNCT_FAILED = 9; 881 private static final int MSG_IL_BTA2DP_DOCK_TIMEOUT = 10; 882 private static final int MSG_L_A2DP_DEVICE_CONFIG_CHANGE = 11; 883 private static final int MSG_BROADCAST_AUDIO_BECOMING_NOISY = 12; 884 private static final int MSG_REPORT_NEW_ROUTES = 13; 885 private static final int MSG_II_SET_HEARING_AID_VOLUME = 14; 886 private static final int MSG_I_SET_AVRCP_ABSOLUTE_VOLUME = 15; 887 private static final int MSG_I_DISCONNECT_BT_SCO = 16; 888 private static final int MSG_TOGGLE_HDMI = 17; 889 private static final int MSG_L_A2DP_ACTIVE_DEVICE_CHANGE = 18; 890 private static final int MSG_DISCONNECT_A2DP = 19; 891 private static final int MSG_DISCONNECT_A2DP_SINK = 20; 892 private static final int MSG_DISCONNECT_BT_HEARING_AID = 21; 893 private static final int MSG_DISCONNECT_BT_HEADSET = 22; 894 private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP = 23; 895 private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP_SINK = 24; 896 private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEARING_AID = 25; 897 private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEADSET = 26; 898 // process external command to (dis)connect an A2DP device 899 private static final int MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT = 27; 900 // process external command to (dis)connect a hearing aid device 901 private static final int MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT = 28; 902 // a ScoClient died in BtHelper 903 private static final int MSG_L_SCOCLIENT_DIED = 29; 904 905 isMessageHandledUnderWakelock(int msgId)906 private static boolean isMessageHandledUnderWakelock(int msgId) { 907 switch(msgId) { 908 case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE: 909 case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE: 910 case MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE: 911 case MSG_IL_SET_HEARING_AID_CONNECTION_STATE: 912 case MSG_IL_BTA2DP_DOCK_TIMEOUT: 913 case MSG_L_A2DP_DEVICE_CONFIG_CHANGE: 914 case MSG_TOGGLE_HDMI: 915 case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE: 916 case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT: 917 case MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT: 918 return true; 919 default: 920 return false; 921 } 922 } 923 924 // Message helper methods 925 926 // sendMsg() flags 927 /** If the msg is already queued, replace it with this one. */ 928 private static final int SENDMSG_REPLACE = 0; 929 /** If the msg is already queued, ignore this one and leave the old. */ 930 private static final int SENDMSG_NOOP = 1; 931 /** If the msg is already queued, queue this one and leave the old. */ 932 private static final int SENDMSG_QUEUE = 2; 933 sendMsg(int msg, int existingMsgPolicy, int delay)934 private void sendMsg(int msg, int existingMsgPolicy, int delay) { 935 sendIILMsg(msg, existingMsgPolicy, 0, 0, null, delay); 936 } 937 sendILMsg(int msg, int existingMsgPolicy, int arg, Object obj, int delay)938 private void sendILMsg(int msg, int existingMsgPolicy, int arg, Object obj, int delay) { 939 sendIILMsg(msg, existingMsgPolicy, arg, 0, obj, delay); 940 } 941 sendLMsg(int msg, int existingMsgPolicy, Object obj, int delay)942 private void sendLMsg(int msg, int existingMsgPolicy, Object obj, int delay) { 943 sendIILMsg(msg, existingMsgPolicy, 0, 0, obj, delay); 944 } 945 sendIMsg(int msg, int existingMsgPolicy, int arg, int delay)946 private void sendIMsg(int msg, int existingMsgPolicy, int arg, int delay) { 947 sendIILMsg(msg, existingMsgPolicy, arg, 0, null, delay); 948 } 949 sendMsgNoDelay(int msg, int existingMsgPolicy)950 private void sendMsgNoDelay(int msg, int existingMsgPolicy) { 951 sendIILMsg(msg, existingMsgPolicy, 0, 0, null, 0); 952 } 953 sendIMsgNoDelay(int msg, int existingMsgPolicy, int arg)954 private void sendIMsgNoDelay(int msg, int existingMsgPolicy, int arg) { 955 sendIILMsg(msg, existingMsgPolicy, arg, 0, null, 0); 956 } 957 sendIIMsgNoDelay(int msg, int existingMsgPolicy, int arg1, int arg2)958 private void sendIIMsgNoDelay(int msg, int existingMsgPolicy, int arg1, int arg2) { 959 sendIILMsg(msg, existingMsgPolicy, arg1, arg2, null, 0); 960 } 961 sendILMsgNoDelay(int msg, int existingMsgPolicy, int arg, Object obj)962 private void sendILMsgNoDelay(int msg, int existingMsgPolicy, int arg, Object obj) { 963 sendIILMsg(msg, existingMsgPolicy, arg, 0, obj, 0); 964 } 965 sendLMsgNoDelay(int msg, int existingMsgPolicy, Object obj)966 private void sendLMsgNoDelay(int msg, int existingMsgPolicy, Object obj) { 967 sendIILMsg(msg, existingMsgPolicy, 0, 0, obj, 0); 968 } 969 sendIILMsgNoDelay(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj)970 private void sendIILMsgNoDelay(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj) { 971 sendIILMsg(msg, existingMsgPolicy, arg1, arg2, obj, 0); 972 } 973 sendIILMsg(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj, int delay)974 private void sendIILMsg(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj, 975 int delay) { 976 if (existingMsgPolicy == SENDMSG_REPLACE) { 977 mBrokerHandler.removeMessages(msg); 978 } else if (existingMsgPolicy == SENDMSG_NOOP && mBrokerHandler.hasMessages(msg)) { 979 return; 980 } 981 982 if (isMessageHandledUnderWakelock(msg)) { 983 final long identity = Binder.clearCallingIdentity(); 984 try { 985 mBrokerEventWakeLock.acquire(BROKER_WAKELOCK_TIMEOUT_MS); 986 } catch (Exception e) { 987 Log.e(TAG, "Exception acquiring wakelock", e); 988 } 989 Binder.restoreCallingIdentity(identity); 990 } 991 992 synchronized (sLastDeviceConnectionMsgTimeLock) { 993 long time = SystemClock.uptimeMillis() + delay; 994 995 switch (msg) { 996 case MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE: 997 case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE: 998 case MSG_IL_SET_HEARING_AID_CONNECTION_STATE: 999 case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE: 1000 case MSG_IL_BTA2DP_DOCK_TIMEOUT: 1001 case MSG_L_A2DP_DEVICE_CONFIG_CHANGE: 1002 case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE: 1003 if (sLastDeviceConnectMsgTime >= time) { 1004 // add a little delay to make sure messages are ordered as expected 1005 time = sLastDeviceConnectMsgTime + 30; 1006 } 1007 sLastDeviceConnectMsgTime = time; 1008 break; 1009 default: 1010 break; 1011 } 1012 1013 mBrokerHandler.sendMessageAtTime(mBrokerHandler.obtainMessage(msg, arg1, arg2, obj), 1014 time); 1015 } 1016 } 1017 1018 //------------------------------------------------------------- 1019 // internal utilities sendBroadcastToAll(Intent intent)1020 private void sendBroadcastToAll(Intent intent) { 1021 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1022 intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); 1023 final long ident = Binder.clearCallingIdentity(); 1024 try { 1025 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 1026 } finally { 1027 Binder.restoreCallingIdentity(ident); 1028 } 1029 } 1030 } 1031