blob: 451fd66d4327374007bea1ce0285e6441f398da0 [file] [log] [blame]
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001/*
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 */
16package com.android.server.audio;
17
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -080018import static com.android.server.audio.AudioService.CONNECTION_STATE_CONNECTED;
19import static com.android.server.audio.AudioService.CONNECTION_STATE_DISCONNECTED;
20
Jean-Michel Trivi58850372018-09-14 16:01:28 -070021import android.annotation.NonNull;
22import android.bluetooth.BluetoothA2dp;
23import android.bluetooth.BluetoothDevice;
Jean-Michel Trivi43ff4f32019-02-07 12:08:39 -080024import android.bluetooth.BluetoothHeadset;
25import android.bluetooth.BluetoothHearingAid;
Jean-Michel Trivi58850372018-09-14 16:01:28 -070026import android.bluetooth.BluetoothProfile;
27import android.content.ContentResolver;
28import android.content.Context;
29import android.content.Intent;
30import android.media.AudioManager;
31import android.media.AudioRoutesInfo;
32import android.media.AudioSystem;
33import android.media.IAudioRoutesObserver;
34import android.os.Binder;
35import android.os.Handler;
36import android.os.IBinder;
37import android.os.Looper;
38import android.os.Message;
39import android.os.PowerManager;
40import android.os.SystemClock;
41import android.os.UserHandle;
42import android.util.Log;
43
44import com.android.internal.annotations.GuardedBy;
45
46import java.util.ArrayList;
47
48/** @hide */
49/*package*/ final class AudioDeviceBroker {
50
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -080051 private static final String TAG = "AS.AudioDeviceBroker";
Jean-Michel Trivi58850372018-09-14 16:01:28 -070052
53 private static final long BROKER_WAKELOCK_TIMEOUT_MS = 5000; //5s
54
55 /*package*/ static final int BTA2DP_DOCK_TIMEOUT_MS = 8000;
56 // Timeout for connection to bluetooth headset service
57 /*package*/ static final int BT_HEADSET_CNCT_TIMEOUT_MS = 3000;
58
59 private final @NonNull AudioService mAudioService;
60 private final @NonNull Context mContext;
61
62 /** Forced device usage for communications sent to AudioSystem */
63 private int mForcedUseForComm;
64 /**
65 * Externally reported force device usage state returned by getters: always consistent
66 * with requests by setters */
67 private int mForcedUseForCommExt;
68
69 // Manages all connected devices, only ever accessed on the message loop
Jean-Michel Trivi58850372018-09-14 16:01:28 -070070 private final AudioDeviceInventory mDeviceInventory;
71 // Manages notifications to BT service
72 private final BtHelper mBtHelper;
73
74
75 //-------------------------------------------------------------------
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -080076 // we use a different lock than mDeviceStateLock so as not to create
77 // lock contention between enqueueing a message and handling them
Jean-Michel Trivi58850372018-09-14 16:01:28 -070078 private static final Object sLastDeviceConnectionMsgTimeLock = new Object();
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -080079 @GuardedBy("sLastDeviceConnectionMsgTimeLock")
Jean-Michel Trivi58850372018-09-14 16:01:28 -070080 private static long sLastDeviceConnectMsgTime = 0;
81
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -080082 // General lock to be taken whenever the state of the audio devices is to be checked or changed
83 private final Object mDeviceStateLock = new Object();
84
Jean-Michel Trivi58850372018-09-14 16:01:28 -070085 // Request to override default use of A2DP for media.
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -080086 @GuardedBy("mDeviceStateLock")
Jean-Michel Trivi58850372018-09-14 16:01:28 -070087 private boolean mBluetoothA2dpEnabled;
88
Jean-Michel Trivi58850372018-09-14 16:01:28 -070089 // lock always taken when accessing AudioService.mSetModeDeathHandlers
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -080090 // TODO do not "share" the lock between AudioService and BtHelpr, see b/123769055
Jean-Michel Trivi58850372018-09-14 16:01:28 -070091 /*package*/ final Object mSetModeLock = new Object();
92
93 //-------------------------------------------------------------------
94 /*package*/ AudioDeviceBroker(@NonNull Context context, @NonNull AudioService service) {
95 mContext = context;
96 mAudioService = service;
97 setupMessaging(context);
98 mBtHelper = new BtHelper(this);
99 mDeviceInventory = new AudioDeviceInventory(this);
100
101 mForcedUseForComm = AudioSystem.FORCE_NONE;
102 mForcedUseForCommExt = mForcedUseForComm;
103
104 }
105
106 /*package*/ Context getContext() {
107 return mContext;
108 }
109
110 //---------------------------------------------------------------------
111 // Communication from AudioService
112 // All methods are asynchronous and never block
113 // All permission checks are done in AudioService, all incoming calls are considered "safe"
114 // All post* methods are asynchronous
115
116 /*package*/ void onSystemReady() {
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800117 synchronized (mDeviceStateLock) {
118 mBtHelper.onSystemReady();
119 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700120 }
121
122 /*package*/ void onAudioServerDied() {
123 // Restore forced usage for communications and record
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800124 synchronized (mDeviceStateLock) {
125 onSetForceUse(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, "onAudioServerDied");
126 onSetForceUse(AudioSystem.FOR_RECORD, mForcedUseForComm, "onAudioServerDied");
127 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700128 // restore devices
129 sendMsgNoDelay(MSG_RESTORE_DEVICES, SENDMSG_REPLACE);
130 }
131
132 /*package*/ void setForceUse_Async(int useCase, int config, String eventSource) {
133 sendIILMsgNoDelay(MSG_IIL_SET_FORCE_USE, SENDMSG_QUEUE,
134 useCase, config, eventSource);
135 }
136
137 /*package*/ void toggleHdmiIfConnected_Async() {
138 sendMsgNoDelay(MSG_TOGGLE_HDMI, SENDMSG_QUEUE);
139 }
140
141 /*package*/ void disconnectAllBluetoothProfiles() {
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800142 synchronized (mDeviceStateLock) {
143 mBtHelper.disconnectAllBluetoothProfiles();
144 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700145 }
146
147 /**
148 * Handle BluetoothHeadset intents where the action is one of
149 * {@link BluetoothHeadset#ACTION_ACTIVE_DEVICE_CHANGED} or
150 * {@link BluetoothHeadset#ACTION_AUDIO_STATE_CHANGED}.
151 * @param intent
152 */
153 /*package*/ void receiveBtEvent(@NonNull Intent intent) {
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800154 synchronized (mDeviceStateLock) {
155 mBtHelper.receiveBtEvent(intent);
156 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700157 }
158
159 /*package*/ void setBluetoothA2dpOn_Async(boolean on, String source) {
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800160 synchronized (mDeviceStateLock) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700161 if (mBluetoothA2dpEnabled == on) {
162 return;
163 }
164 mBluetoothA2dpEnabled = on;
165 mBrokerHandler.removeMessages(MSG_IIL_SET_FORCE_BT_A2DP_USE);
166 sendIILMsgNoDelay(MSG_IIL_SET_FORCE_BT_A2DP_USE, SENDMSG_QUEUE,
167 AudioSystem.FOR_MEDIA,
168 mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP,
169 source);
170 }
171 }
172
173 /*package*/ void setSpeakerphoneOn(boolean on, String eventSource) {
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800174 synchronized (mDeviceStateLock) {
175 if (on) {
176 if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
177 setForceUse_Async(AudioSystem.FOR_RECORD, AudioSystem.FORCE_NONE, eventSource);
178 }
179 mForcedUseForComm = AudioSystem.FORCE_SPEAKER;
180 } else if (mForcedUseForComm == AudioSystem.FORCE_SPEAKER) {
181 mForcedUseForComm = AudioSystem.FORCE_NONE;
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700182 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700183
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800184 mForcedUseForCommExt = mForcedUseForComm;
185 setForceUse_Async(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, eventSource);
186 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700187 }
188
189 /*package*/ boolean isSpeakerphoneOn() {
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800190 synchronized (mDeviceStateLock) {
191 return (mForcedUseForCommExt == AudioSystem.FORCE_SPEAKER);
192 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700193 }
194
195 /*package*/ void setWiredDeviceConnectionState(int type,
196 @AudioService.ConnectionState int state, String address, String name,
197 String caller) {
198 //TODO move logging here just like in setBluetooth* methods
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800199 synchronized (mDeviceStateLock) {
200 mDeviceInventory.setWiredDeviceConnectionState(type, state, address, name, caller);
201 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700202 }
203
Jean-Michel Trivifc86cfa2019-03-01 10:15:47 -0800204 private static final class BtDeviceConnectionInfo {
205 final @NonNull BluetoothDevice mDevice;
206 final @AudioService.BtProfileConnectionState int mState;
207 final int mProfile;
208 final boolean mSupprNoisy;
209 final int mVolume;
210
211 BtDeviceConnectionInfo(@NonNull BluetoothDevice device,
212 @AudioService.BtProfileConnectionState int state,
213 int profile, boolean suppressNoisyIntent, int vol) {
214 mDevice = device;
215 mState = state;
216 mProfile = profile;
217 mSupprNoisy = suppressNoisyIntent;
218 mVolume = vol;
219 }
220 }
221
222 /*package*/ void postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700223 @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
224 int profile, boolean suppressNoisyIntent, int a2dpVolume) {
Jean-Michel Trivifc86cfa2019-03-01 10:15:47 -0800225 final BtDeviceConnectionInfo info = new BtDeviceConnectionInfo(device, state, profile,
226 suppressNoisyIntent, a2dpVolume);
227
228 // TODO add a check to try to remove unprocessed messages for the same device (the old
229 // check didn't work), and make sure it doesn't conflict with config change message
230 sendLMsgNoDelay(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT, SENDMSG_QUEUE, info);
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700231 }
232
233 /*package*/ int handleBluetoothA2dpActiveDeviceChange(
234 @NonNull BluetoothDevice device,
235 @AudioService.BtProfileConnectionState int state, int profile,
236 boolean suppressNoisyIntent, int a2dpVolume) {
Jean-Michel Trivifc86cfa2019-03-01 10:15:47 -0800237 // FIXME method was added by @a8439e2 but never used, and now conflicts with async behavior
238 // of handleBluetoothA2dpDeviceConfigChange and
239 // setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800240 synchronized (mDeviceStateLock) {
241 return mDeviceInventory.handleBluetoothA2dpActiveDeviceChange(device, state, profile,
242 suppressNoisyIntent, a2dpVolume);
243 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700244 }
245
Jean-Michel Trivifc86cfa2019-03-01 10:15:47 -0800246 private static final class HearingAidDeviceConnectionInfo {
247 final @NonNull BluetoothDevice mDevice;
248 final @AudioService.BtProfileConnectionState int mState;
249 final boolean mSupprNoisy;
250 final int mMusicDevice;
251 final @NonNull String mEventSource;
252
253 HearingAidDeviceConnectionInfo(@NonNull BluetoothDevice device,
254 @AudioService.BtProfileConnectionState int state,
255 boolean suppressNoisyIntent, int musicDevice, @NonNull String eventSource) {
256 mDevice = device;
257 mState = state;
258 mSupprNoisy = suppressNoisyIntent;
259 mMusicDevice = musicDevice;
260 mEventSource = eventSource;
261 }
262 }
263
264 /*package*/ void postBluetoothHearingAidDeviceConnectionState(
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700265 @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
266 boolean suppressNoisyIntent, int musicDevice, @NonNull String eventSource) {
Jean-Michel Trivifc86cfa2019-03-01 10:15:47 -0800267 final HearingAidDeviceConnectionInfo info = new HearingAidDeviceConnectionInfo(
268 device, state, suppressNoisyIntent, musicDevice, eventSource);
269 sendLMsgNoDelay(MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT, SENDMSG_QUEUE, info);
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700270 }
271
272 // never called by system components
273 /*package*/ void setBluetoothScoOnByApp(boolean on) {
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800274 synchronized (mDeviceStateLock) {
275 mForcedUseForCommExt = on ? AudioSystem.FORCE_BT_SCO : AudioSystem.FORCE_NONE;
276 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700277 }
278
279 /*package*/ boolean isBluetoothScoOnForApp() {
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800280 synchronized (mDeviceStateLock) {
281 return mForcedUseForCommExt == AudioSystem.FORCE_BT_SCO;
282 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700283 }
284
285 /*package*/ void setBluetoothScoOn(boolean on, String eventSource) {
286 //Log.i(TAG, "setBluetoothScoOnInt: " + on + " " + eventSource);
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800287 synchronized (mDeviceStateLock) {
288 if (on) {
289 // do not accept SCO ON if SCO audio is not connected
290 if (!mBtHelper.isBluetoothScoOn()) {
291 mForcedUseForCommExt = AudioSystem.FORCE_BT_SCO;
292 return;
293 }
294 mForcedUseForComm = AudioSystem.FORCE_BT_SCO;
295 } else if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
296 mForcedUseForComm = AudioSystem.FORCE_NONE;
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700297 }
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800298 mForcedUseForCommExt = mForcedUseForComm;
299 AudioSystem.setParameters("BT_SCO=" + (on ? "on" : "off"));
300 sendIILMsgNoDelay(MSG_IIL_SET_FORCE_USE, SENDMSG_QUEUE,
301 AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, eventSource);
302 sendIILMsgNoDelay(MSG_IIL_SET_FORCE_USE, SENDMSG_QUEUE,
303 AudioSystem.FOR_RECORD, mForcedUseForComm, eventSource);
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700304 }
Jean-Michel Trivica49d312019-02-14 15:55:39 -0800305 // Un-mute ringtone stream volume
306 mAudioService.postUpdateRingerModeServiceInt();
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700307 }
308
309 /*package*/ AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) {
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800310 synchronized (mDeviceStateLock) {
311 return mDeviceInventory.startWatchingRoutes(observer);
312 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700313 }
314
315 /*package*/ AudioRoutesInfo getCurAudioRoutes() {
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800316 synchronized (mDeviceStateLock) {
317 return mDeviceInventory.getCurAudioRoutes();
318 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700319 }
320
321 /*package*/ boolean isAvrcpAbsoluteVolumeSupported() {
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800322 synchronized (mDeviceStateLock) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700323 return mBtHelper.isAvrcpAbsoluteVolumeSupported();
324 }
325 }
326
327 /*package*/ boolean isBluetoothA2dpOn() {
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800328 synchronized (mDeviceStateLock) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700329 return mBluetoothA2dpEnabled;
330 }
331 }
332
333 /*package*/ void postSetAvrcpAbsoluteVolumeIndex(int index) {
334 sendIMsgNoDelay(MSG_I_SET_AVRCP_ABSOLUTE_VOLUME, SENDMSG_REPLACE, index);
335 }
336
337 /*package*/ void postSetHearingAidVolumeIndex(int index, int streamType) {
338 sendIIMsgNoDelay(MSG_II_SET_HEARING_AID_VOLUME, SENDMSG_REPLACE, index, streamType);
339 }
340
341 /*package*/ void postDisconnectBluetoothSco(int exceptPid) {
342 sendIMsgNoDelay(MSG_I_DISCONNECT_BT_SCO, SENDMSG_REPLACE, exceptPid);
343 }
344
345 /*package*/ void postBluetoothA2dpDeviceConfigChange(@NonNull BluetoothDevice device) {
346 sendLMsgNoDelay(MSG_L_A2DP_DEVICE_CONFIG_CHANGE, SENDMSG_QUEUE, device);
347 }
348
349 /*package*/ void startBluetoothScoForClient_Sync(IBinder cb, int scoAudioMode,
350 @NonNull String eventSource) {
351 mBtHelper.startBluetoothScoForClient(cb, scoAudioMode, eventSource);
352 }
353
354 /*package*/ void stopBluetoothScoForClient_Sync(IBinder cb, @NonNull String eventSource) {
355 mBtHelper.stopBluetoothScoForClient(cb, eventSource);
356 }
357
358 //---------------------------------------------------------------------
359 // Communication with (to) AudioService
360 //TODO check whether the AudioService methods are candidates to move here
361 /*package*/ void postAccessoryPlugMediaUnmute(int device) {
362 mAudioService.postAccessoryPlugMediaUnmute(device);
363 }
364
365 /*package*/ AudioService.VolumeStreamState getStreamState(int streamType) {
366 return mAudioService.getStreamState(streamType);
367 }
368
369 /*package*/ ArrayList<AudioService.SetModeDeathHandler> getSetModeDeathHandlers() {
370 return mAudioService.mSetModeDeathHandlers;
371 }
372
373 /*package*/ int getDeviceForStream(int streamType) {
374 return mAudioService.getDeviceForStream(streamType);
375 }
376
377 /*package*/ void setDeviceVolume(AudioService.VolumeStreamState streamState, int device) {
378 mAudioService.setDeviceVolume(streamState, device);
379 }
380
381 /*packages*/ void observeDevicesForAllStreams() {
382 mAudioService.observeDevicesForAllStreams();
383 }
384
385 /*package*/ boolean isInCommunication() {
386 return mAudioService.isInCommunication();
387 }
388
389 /*package*/ boolean hasMediaDynamicPolicy() {
390 return mAudioService.hasMediaDynamicPolicy();
391 }
392
393 /*package*/ ContentResolver getContentResolver() {
394 return mAudioService.getContentResolver();
395 }
396
397 /*package*/ void checkMusicActive(int deviceType, String caller) {
398 mAudioService.checkMusicActive(deviceType, caller);
399 }
400
401 /*package*/ void checkVolumeCecOnHdmiConnection(int state, String caller) {
402 mAudioService.checkVolumeCecOnHdmiConnection(state, caller);
403 }
404
405 //---------------------------------------------------------------------
406 // Message handling on behalf of helper classes
Jean-Michel Trivib9465152019-02-06 15:20:19 -0800407 /*package*/ void postBroadcastScoConnectionState(int state) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700408 sendIMsgNoDelay(MSG_I_BROADCAST_BT_CONNECTION_STATE, SENDMSG_QUEUE, state);
409 }
410
Jean-Michel Trivib9465152019-02-06 15:20:19 -0800411 /*package*/ void postBroadcastBecomingNoisy() {
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700412 sendMsgNoDelay(MSG_BROADCAST_AUDIO_BECOMING_NOISY, SENDMSG_REPLACE);
413 }
414
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700415 /*package*/ void postA2dpSinkConnection(int state,
416 @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo, int delay) {
417 sendILMsg(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE, SENDMSG_QUEUE,
418 state, btDeviceInfo, delay);
419 }
420
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700421 /*package*/ void postA2dpSourceConnection(int state,
422 @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo, int delay) {
423 sendILMsg(MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE, SENDMSG_QUEUE,
424 state, btDeviceInfo, delay);
425 }
426
427 /*package*/ void postSetWiredDeviceConnectionState(
428 AudioDeviceInventory.WiredDeviceConnectionState connectionState, int delay) {
429 sendLMsg(MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE, SENDMSG_QUEUE, connectionState, delay);
430 }
431
432 /*package*/ void postSetHearingAidConnectionState(
433 @AudioService.BtProfileConnectionState int state,
434 @NonNull BluetoothDevice device, int delay) {
435 sendILMsg(MSG_IL_SET_HEARING_AID_CONNECTION_STATE, SENDMSG_QUEUE,
436 state,
437 device,
438 delay);
439 }
440
Jean-Michel Trivib9465152019-02-06 15:20:19 -0800441 /*package*/ void postDisconnectA2dp() {
442 sendMsgNoDelay(MSG_DISCONNECT_A2DP, SENDMSG_QUEUE);
443 }
444
445 /*package*/ void postDisconnectA2dpSink() {
446 sendMsgNoDelay(MSG_DISCONNECT_A2DP_SINK, SENDMSG_QUEUE);
447 }
448
449 /*package*/ void postDisconnectHearingAid() {
Jean-Michel Trivi43ff4f32019-02-07 12:08:39 -0800450 sendMsgNoDelay(MSG_DISCONNECT_BT_HEARING_AID, SENDMSG_QUEUE);
Jean-Michel Trivib9465152019-02-06 15:20:19 -0800451 }
452
453 /*package*/ void postDisconnectHeadset() {
Jean-Michel Trivi43ff4f32019-02-07 12:08:39 -0800454 sendMsgNoDelay(MSG_DISCONNECT_BT_HEADSET, SENDMSG_QUEUE);
455 }
456
457 /*package*/ void postBtA2dpProfileConnected(BluetoothA2dp a2dpProfile) {
458 sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP, SENDMSG_QUEUE, a2dpProfile);
459 }
460
461 /*package*/ void postBtA2dpSinkProfileConnected(BluetoothProfile profile) {
462 sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP_SINK, SENDMSG_QUEUE, profile);
463 }
464
465 /*package*/ void postBtHeasetProfileConnected(BluetoothHeadset headsetProfile) {
466 sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEADSET, SENDMSG_QUEUE, headsetProfile);
467 }
468
469 /*package*/ void postBtHearingAidProfileConnected(BluetoothHearingAid hearingAidProfile) {
470 sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEARING_AID, SENDMSG_QUEUE,
471 hearingAidProfile);
Jean-Michel Trivib9465152019-02-06 15:20:19 -0800472 }
473
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700474 //---------------------------------------------------------------------
475 // Method forwarding between the helper classes (BtHelper, AudioDeviceInventory)
476 // only call from a "handle"* method or "on"* method
477
478 // Handles request to override default use of A2DP for media.
479 //@GuardedBy("mConnectedDevices")
480 /*package*/ void setBluetoothA2dpOnInt(boolean on, String source) {
481 // for logging only
482 final String eventSource = new StringBuilder("setBluetoothA2dpOn(").append(on)
483 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
484 .append(Binder.getCallingPid()).append(" src:").append(source).toString();
485
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800486 synchronized (mDeviceStateLock) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700487 mBluetoothA2dpEnabled = on;
488 mBrokerHandler.removeMessages(MSG_IIL_SET_FORCE_BT_A2DP_USE);
489 onSetForceUse(
490 AudioSystem.FOR_MEDIA,
491 mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP,
492 eventSource);
493 }
494 }
495
496 /*package*/ boolean handleDeviceConnection(boolean connect, int device, String address,
497 String deviceName) {
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800498 synchronized (mDeviceStateLock) {
499 return mDeviceInventory.handleDeviceConnection(connect, device, address, deviceName);
500 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700501 }
502
Jean-Michel Trivi43ff4f32019-02-07 12:08:39 -0800503 @GuardedBy("mDeviceStateLock")
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700504 /*package*/ void handleSetA2dpSinkConnectionState(@BluetoothProfile.BtProfileState int state,
505 @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo) {
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800506 final int intState = (state == BluetoothA2dp.STATE_CONNECTED)
507 ? CONNECTION_STATE_CONNECTED : CONNECTION_STATE_DISCONNECTED;
Jean-Michel Trivi43ff4f32019-02-07 12:08:39 -0800508 final int delay = mDeviceInventory.checkSendBecomingNoisyIntent(
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800509 AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, intState,
510 AudioSystem.DEVICE_NONE);
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700511 final String addr = btDeviceInfo == null ? "null" : btDeviceInfo.getBtDevice().getAddress();
512
513 if (AudioService.DEBUG_DEVICES) {
514 Log.d(TAG, "handleSetA2dpSinkConnectionState btDevice= " + btDeviceInfo
515 + " state= " + state
516 + " is dock: " + btDeviceInfo.getBtDevice().isBluetoothDock());
517 }
518 sendILMsg(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE, SENDMSG_QUEUE,
519 state, btDeviceInfo, delay);
520 }
521
Jean-Michel Trivib9465152019-02-06 15:20:19 -0800522 /*package*/ void postSetA2dpSourceConnectionState(@BluetoothProfile.BtProfileState int state,
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700523 @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo) {
524 final int intState = (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0;
525 sendILMsgNoDelay(MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE, SENDMSG_QUEUE, state,
526 btDeviceInfo);
527 }
528
529 /*package*/ void handleFailureToConnectToBtHeadsetService(int delay) {
530 sendMsg(MSG_BT_HEADSET_CNCT_FAILED, SENDMSG_REPLACE, delay);
531 }
532
533 /*package*/ void handleCancelFailureToConnectToBtHeadsetService() {
534 mBrokerHandler.removeMessages(MSG_BT_HEADSET_CNCT_FAILED);
535 }
536
537 /*package*/ void postReportNewRoutes() {
538 sendMsgNoDelay(MSG_REPORT_NEW_ROUTES, SENDMSG_NOOP);
539 }
540
541 /*package*/ void cancelA2dpDockTimeout() {
542 mBrokerHandler.removeMessages(MSG_IL_BTA2DP_DOCK_TIMEOUT);
543 }
544
545 /*package*/ void postA2dpActiveDeviceChange(BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo) {
546 sendLMsgNoDelay(MSG_L_A2DP_ACTIVE_DEVICE_CHANGE, SENDMSG_QUEUE, btDeviceInfo);
547 }
548
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700549 /*package*/ boolean hasScheduledA2dpDockTimeout() {
550 return mBrokerHandler.hasMessages(MSG_IL_BTA2DP_DOCK_TIMEOUT);
551 }
552
553 //###
554 // must be called synchronized on mConnectedDevices
555 /*package*/ boolean hasScheduledA2dpSinkConnectionState(BluetoothDevice btDevice) {
556 return mBrokerHandler.hasMessages(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE,
557 new BtHelper.BluetoothA2dpDeviceInfo(btDevice));
558 }
559
560 /*package*/ void setA2dpDockTimeout(String address, int a2dpCodec, int delayMs) {
561 sendILMsg(MSG_IL_BTA2DP_DOCK_TIMEOUT, SENDMSG_QUEUE, a2dpCodec, address, delayMs);
562 }
563
564 /*package*/ void setAvrcpAbsoluteVolumeSupported(boolean supported) {
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800565 synchronized (mDeviceStateLock) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700566 mBtHelper.setAvrcpAbsoluteVolumeSupported(supported);
567 }
568 }
569
570 /*package*/ boolean getBluetoothA2dpEnabled() {
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800571 synchronized (mDeviceStateLock) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700572 return mBluetoothA2dpEnabled;
573 }
574 }
575
576 /*package*/ int getA2dpCodec(@NonNull BluetoothDevice device) {
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800577 synchronized (mDeviceStateLock) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700578 return mBtHelper.getA2dpCodec(device);
579 }
580 }
581
582 //---------------------------------------------------------------------
583 // Internal handling of messages
584 // These methods are ALL synchronous, in response to message handling in BrokerHandler
585 // Blocking in any of those will block the message queue
586
587 private void onSetForceUse(int useCase, int config, String eventSource) {
588 if (useCase == AudioSystem.FOR_MEDIA) {
589 postReportNewRoutes();
590 }
591 AudioService.sForceUseLogger.log(
592 new AudioServiceEvents.ForceUseEvent(useCase, config, eventSource));
593 AudioSystem.setForceUse(useCase, config);
594 }
595
596 private void onSendBecomingNoisyIntent() {
597 AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
598 "broadcast ACTION_AUDIO_BECOMING_NOISY")).printLog(TAG));
599 sendBroadcastToAll(new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY));
600 }
601
602 //---------------------------------------------------------------------
603 // Message handling
604 private BrokerHandler mBrokerHandler;
605 private BrokerThread mBrokerThread;
606 private PowerManager.WakeLock mBrokerEventWakeLock;
607
608 private void setupMessaging(Context ctxt) {
609 final PowerManager pm = (PowerManager) ctxt.getSystemService(Context.POWER_SERVICE);
610 mBrokerEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
611 "handleAudioDeviceEvent");
612 mBrokerThread = new BrokerThread();
613 mBrokerThread.start();
614 waitForBrokerHandlerCreation();
615 }
616
617 private void waitForBrokerHandlerCreation() {
618 synchronized (this) {
619 while (mBrokerHandler == null) {
620 try {
621 wait();
622 } catch (InterruptedException e) {
623 Log.e(TAG, "Interruption while waiting on BrokerHandler");
624 }
625 }
626 }
627 }
628
629 /** Class that handles the device broker's message queue */
630 private class BrokerThread extends Thread {
631 BrokerThread() {
632 super("AudioDeviceBroker");
633 }
634
635 @Override
636 public void run() {
637 // Set this thread up so the handler will work on it
638 Looper.prepare();
639
640 synchronized (AudioDeviceBroker.this) {
641 mBrokerHandler = new BrokerHandler();
642
643 // Notify that the handler has been created
644 AudioDeviceBroker.this.notify();
645 }
646
647 Looper.loop();
648 }
649 }
650
651 /** Class that handles the message queue */
652 private class BrokerHandler extends Handler {
653
654 @Override
655 public void handleMessage(Message msg) {
656 switch (msg.what) {
657 case MSG_RESTORE_DEVICES:
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800658 synchronized (mDeviceStateLock) {
659 mDeviceInventory.onRestoreDevices();
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700660 mBtHelper.onAudioServerDiedRestoreA2dp();
661 }
662 break;
663 case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE:
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800664 synchronized (mDeviceStateLock) {
665 mDeviceInventory.onSetWiredDeviceConnectionState(
666 (AudioDeviceInventory.WiredDeviceConnectionState) msg.obj);
667 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700668 break;
669 case MSG_I_BROADCAST_BT_CONNECTION_STATE:
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800670 synchronized (mDeviceStateLock) {
671 mBtHelper.onBroadcastScoConnectionState(msg.arg1);
672 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700673 break;
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800674 case MSG_IIL_SET_FORCE_USE: // intended fall-through
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700675 case MSG_IIL_SET_FORCE_BT_A2DP_USE:
676 onSetForceUse(msg.arg1, msg.arg2, (String) msg.obj);
677 break;
678 case MSG_REPORT_NEW_ROUTES:
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800679 synchronized (mDeviceStateLock) {
680 mDeviceInventory.onReportNewRoutes();
681 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700682 break;
683 case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE:
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800684 synchronized (mDeviceStateLock) {
685 mDeviceInventory.onSetA2dpSinkConnectionState(
686 (BtHelper.BluetoothA2dpDeviceInfo) msg.obj, msg.arg1);
687 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700688 break;
689 case MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE:
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800690 synchronized (mDeviceStateLock) {
691 mDeviceInventory.onSetA2dpSourceConnectionState(
692 (BtHelper.BluetoothA2dpDeviceInfo) msg.obj, msg.arg1);
693 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700694 break;
695 case MSG_IL_SET_HEARING_AID_CONNECTION_STATE:
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800696 synchronized (mDeviceStateLock) {
697 mDeviceInventory.onSetHearingAidConnectionState(
698 (BluetoothDevice) msg.obj, msg.arg1);
699 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700700 break;
701 case MSG_BT_HEADSET_CNCT_FAILED:
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800702 synchronized (mDeviceStateLock) {
703 mBtHelper.resetBluetoothSco();
704 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700705 break;
706 case MSG_IL_BTA2DP_DOCK_TIMEOUT:
707 // msg.obj == address of BTA2DP device
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800708 synchronized (mDeviceStateLock) {
709 mDeviceInventory.onMakeA2dpDeviceUnavailableNow((String) msg.obj, msg.arg1);
710 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700711 break;
712 case MSG_L_A2DP_DEVICE_CONFIG_CHANGE:
713 final int a2dpCodec;
714 final BluetoothDevice btDevice = (BluetoothDevice) msg.obj;
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800715 synchronized (mDeviceStateLock) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700716 a2dpCodec = mBtHelper.getA2dpCodec(btDevice);
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800717 mDeviceInventory.onBluetoothA2dpDeviceConfigChange(
718 new BtHelper.BluetoothA2dpDeviceInfo(btDevice, -1, a2dpCodec));
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700719 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700720 break;
721 case MSG_BROADCAST_AUDIO_BECOMING_NOISY:
722 onSendBecomingNoisyIntent();
723 break;
724 case MSG_II_SET_HEARING_AID_VOLUME:
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800725 synchronized (mDeviceStateLock) {
726 mBtHelper.setHearingAidVolume(msg.arg1, msg.arg2);
727 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700728 break;
729 case MSG_I_SET_AVRCP_ABSOLUTE_VOLUME:
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800730 synchronized (mDeviceStateLock) {
731 mBtHelper.setAvrcpAbsoluteVolumeIndex(msg.arg1);
732 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700733 break;
734 case MSG_I_DISCONNECT_BT_SCO:
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800735 synchronized (mDeviceStateLock) {
736 mBtHelper.disconnectBluetoothSco(msg.arg1);
737 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700738 break;
739 case MSG_TOGGLE_HDMI:
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800740 synchronized (mDeviceStateLock) {
741 mDeviceInventory.onToggleHdmi();
742 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700743 break;
744 case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE:
Jean-Michel Trivic4b9c962019-02-01 09:58:54 -0800745 synchronized (mDeviceStateLock) {
746 mDeviceInventory.onBluetoothA2dpActiveDeviceChange(
747 (BtHelper.BluetoothA2dpDeviceInfo) msg.obj);
748 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700749 break;
Jean-Michel Trivib9465152019-02-06 15:20:19 -0800750 case MSG_DISCONNECT_A2DP:
751 synchronized (mDeviceStateLock) {
752 mDeviceInventory.disconnectA2dp();
753 }
754 break;
755 case MSG_DISCONNECT_A2DP_SINK:
756 synchronized (mDeviceStateLock) {
757 mDeviceInventory.disconnectA2dpSink();
758 }
759 break;
Jean-Michel Trivi43ff4f32019-02-07 12:08:39 -0800760 case MSG_DISCONNECT_BT_HEARING_AID:
Jean-Michel Trivib9465152019-02-06 15:20:19 -0800761 synchronized (mDeviceStateLock) {
762 mDeviceInventory.disconnectHearingAid();
763 }
764 break;
Jean-Michel Trivi43ff4f32019-02-07 12:08:39 -0800765 case MSG_DISCONNECT_BT_HEADSET:
Jean-Michel Trivib9465152019-02-06 15:20:19 -0800766 synchronized (mDeviceStateLock) {
767 mBtHelper.disconnectHeadset();
768 }
769 break;
Jean-Michel Trivi43ff4f32019-02-07 12:08:39 -0800770 case MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP:
771 synchronized (mDeviceStateLock) {
772 mBtHelper.onA2dpProfileConnected((BluetoothA2dp) msg.obj);
773 }
774 break;
775 case MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP_SINK:
776 synchronized (mDeviceStateLock) {
777 mBtHelper.onA2dpSinkProfileConnected((BluetoothProfile) msg.obj);
778 }
779 break;
780 case MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEARING_AID:
781 synchronized (mDeviceStateLock) {
782 mBtHelper.onHearingAidProfileConnected((BluetoothHearingAid) msg.obj);
783 }
784 break;
785 case MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEADSET:
786 synchronized (mDeviceStateLock) {
787 mBtHelper.onHeadsetProfileConnected((BluetoothHeadset) msg.obj);
788 }
789 break;
Jean-Michel Trivifc86cfa2019-03-01 10:15:47 -0800790 case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT: {
791 final BtDeviceConnectionInfo info = (BtDeviceConnectionInfo) msg.obj;
792 AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
793 "setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent "
794 + " state=" + info.mState
795 // only querying address as this is the only readily available
796 // field on the device
797 + " addr=" + info.mDevice.getAddress()
798 + " prof=" + info.mProfile + " supprNoisy=" + info.mSupprNoisy
799 + " vol=" + info.mVolume)).printLog(TAG));
800 synchronized (mDeviceStateLock) {
801 mDeviceInventory.setBluetoothA2dpDeviceConnectionState(
802 info.mDevice, info.mState, info.mProfile, info.mSupprNoisy,
803 AudioSystem.DEVICE_NONE, info.mVolume);
804 }
805 } break;
806 case MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT: {
807 final HearingAidDeviceConnectionInfo info =
808 (HearingAidDeviceConnectionInfo) msg.obj;
809 AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
810 "setHearingAidDeviceConnectionState state=" + info.mState
811 + " addr=" + info.mDevice.getAddress()
812 + " supprNoisy=" + info.mSupprNoisy
813 + " src=" + info.mEventSource)).printLog(TAG));
814 synchronized (mDeviceStateLock) {
815 mDeviceInventory.setBluetoothHearingAidDeviceConnectionState(
816 info.mDevice, info.mState, info.mSupprNoisy, info.mMusicDevice);
817 }
818 } break;
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700819 default:
820 Log.wtf(TAG, "Invalid message " + msg.what);
821 }
822 if (isMessageHandledUnderWakelock(msg.what)) {
823 try {
824 mBrokerEventWakeLock.release();
825 } catch (Exception e) {
826 Log.e(TAG, "Exception releasing wakelock", e);
827 }
828 }
829 }
830 }
831
832 // List of all messages. If a message has be handled under wakelock, add it to
833 // the isMessageHandledUnderWakelock(int) method
834 // Naming of msg indicates arguments, using JNI argument grammar
835 // (e.g. II indicates two int args, IL indicates int and Obj arg)
836 private static final int MSG_RESTORE_DEVICES = 1;
837 private static final int MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE = 2;
838 private static final int MSG_I_BROADCAST_BT_CONNECTION_STATE = 3;
839 private static final int MSG_IIL_SET_FORCE_USE = 4;
840 private static final int MSG_IIL_SET_FORCE_BT_A2DP_USE = 5;
841 private static final int MSG_IL_SET_A2DP_SINK_CONNECTION_STATE = 6;
842 private static final int MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE = 7;
843 private static final int MSG_IL_SET_HEARING_AID_CONNECTION_STATE = 8;
844 private static final int MSG_BT_HEADSET_CNCT_FAILED = 9;
845 private static final int MSG_IL_BTA2DP_DOCK_TIMEOUT = 10;
846 private static final int MSG_L_A2DP_DEVICE_CONFIG_CHANGE = 11;
847 private static final int MSG_BROADCAST_AUDIO_BECOMING_NOISY = 12;
848 private static final int MSG_REPORT_NEW_ROUTES = 13;
849 private static final int MSG_II_SET_HEARING_AID_VOLUME = 14;
850 private static final int MSG_I_SET_AVRCP_ABSOLUTE_VOLUME = 15;
851 private static final int MSG_I_DISCONNECT_BT_SCO = 16;
852 private static final int MSG_TOGGLE_HDMI = 17;
853 private static final int MSG_L_A2DP_ACTIVE_DEVICE_CHANGE = 18;
Jean-Michel Trivib9465152019-02-06 15:20:19 -0800854 private static final int MSG_DISCONNECT_A2DP = 19;
855 private static final int MSG_DISCONNECT_A2DP_SINK = 20;
Jean-Michel Trivi43ff4f32019-02-07 12:08:39 -0800856 private static final int MSG_DISCONNECT_BT_HEARING_AID = 21;
857 private static final int MSG_DISCONNECT_BT_HEADSET = 22;
858 private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP = 23;
859 private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP_SINK = 24;
860 private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEARING_AID = 25;
861 private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEADSET = 26;
Jean-Michel Trivifc86cfa2019-03-01 10:15:47 -0800862 // process external command to (dis)connect an A2DP device
863 private static final int MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT = 27;
864 // process external command to (dis)connect a hearing aid device
865 private static final int MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT = 28;
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700866
867
868 private static boolean isMessageHandledUnderWakelock(int msgId) {
869 switch(msgId) {
870 case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE:
871 case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE:
872 case MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE:
873 case MSG_IL_SET_HEARING_AID_CONNECTION_STATE:
874 case MSG_IL_BTA2DP_DOCK_TIMEOUT:
875 case MSG_L_A2DP_DEVICE_CONFIG_CHANGE:
876 case MSG_TOGGLE_HDMI:
877 case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE:
Jean-Michel Trivifc86cfa2019-03-01 10:15:47 -0800878 case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT:
879 case MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT:
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700880 return true;
881 default:
882 return false;
883 }
884 }
885
886 // Message helper methods
887
888 // sendMsg() flags
889 /** If the msg is already queued, replace it with this one. */
890 private static final int SENDMSG_REPLACE = 0;
891 /** If the msg is already queued, ignore this one and leave the old. */
892 private static final int SENDMSG_NOOP = 1;
893 /** If the msg is already queued, queue this one and leave the old. */
894 private static final int SENDMSG_QUEUE = 2;
895
896 private void sendMsg(int msg, int existingMsgPolicy, int delay) {
897 sendIILMsg(msg, existingMsgPolicy, 0, 0, null, delay);
898 }
899
900 private void sendILMsg(int msg, int existingMsgPolicy, int arg, Object obj, int delay) {
901 sendIILMsg(msg, existingMsgPolicy, arg, 0, obj, delay);
902 }
903
904 private void sendLMsg(int msg, int existingMsgPolicy, Object obj, int delay) {
905 sendIILMsg(msg, existingMsgPolicy, 0, 0, obj, delay);
906 }
907
908 private void sendIMsg(int msg, int existingMsgPolicy, int arg, int delay) {
909 sendIILMsg(msg, existingMsgPolicy, arg, 0, null, delay);
910 }
911
912 private void sendMsgNoDelay(int msg, int existingMsgPolicy) {
913 sendIILMsg(msg, existingMsgPolicy, 0, 0, null, 0);
914 }
915
916 private void sendIMsgNoDelay(int msg, int existingMsgPolicy, int arg) {
917 sendIILMsg(msg, existingMsgPolicy, arg, 0, null, 0);
918 }
919
920 private void sendIIMsgNoDelay(int msg, int existingMsgPolicy, int arg1, int arg2) {
921 sendIILMsg(msg, existingMsgPolicy, arg1, arg2, null, 0);
922 }
923
924 private void sendILMsgNoDelay(int msg, int existingMsgPolicy, int arg, Object obj) {
925 sendIILMsg(msg, existingMsgPolicy, arg, 0, obj, 0);
926 }
927
928 private void sendLMsgNoDelay(int msg, int existingMsgPolicy, Object obj) {
929 sendIILMsg(msg, existingMsgPolicy, 0, 0, obj, 0);
930 }
931
932 private void sendIILMsgNoDelay(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj) {
933 sendIILMsg(msg, existingMsgPolicy, arg1, arg2, obj, 0);
934 }
935
936 private void sendIILMsg(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj,
937 int delay) {
938 if (existingMsgPolicy == SENDMSG_REPLACE) {
939 mBrokerHandler.removeMessages(msg);
940 } else if (existingMsgPolicy == SENDMSG_NOOP && mBrokerHandler.hasMessages(msg)) {
941 return;
942 }
943
944 if (isMessageHandledUnderWakelock(msg)) {
945 final long identity = Binder.clearCallingIdentity();
946 try {
947 mBrokerEventWakeLock.acquire(BROKER_WAKELOCK_TIMEOUT_MS);
948 } catch (Exception e) {
949 Log.e(TAG, "Exception acquiring wakelock", e);
950 }
951 Binder.restoreCallingIdentity(identity);
952 }
953
954 synchronized (sLastDeviceConnectionMsgTimeLock) {
955 long time = SystemClock.uptimeMillis() + delay;
956
957 switch (msg) {
958 case MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE:
959 case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE:
960 case MSG_IL_SET_HEARING_AID_CONNECTION_STATE:
961 case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE:
962 case MSG_IL_BTA2DP_DOCK_TIMEOUT:
963 case MSG_L_A2DP_DEVICE_CONFIG_CHANGE:
964 case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE:
965 if (sLastDeviceConnectMsgTime >= time) {
966 // add a little delay to make sure messages are ordered as expected
967 time = sLastDeviceConnectMsgTime + 30;
968 }
969 sLastDeviceConnectMsgTime = time;
970 break;
971 default:
972 break;
973 }
974
975 mBrokerHandler.sendMessageAtTime(mBrokerHandler.obtainMessage(msg, arg1, arg2, obj),
976 time);
977 }
978 }
979
980 //-------------------------------------------------------------
981 // internal utilities
982 private void sendBroadcastToAll(Intent intent) {
983 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
984 intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
985 final long ident = Binder.clearCallingIdentity();
986 try {
987 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
988 } finally {
989 Binder.restoreCallingIdentity(ident);
990 }
991 }
992}