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