1 /*
2  * Copyright 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.server.audio;
17 
18 import static android.media.audio.Flags.scoManagedByAudio;
19 
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.app.compat.CompatChanges;
23 import android.bluetooth.BluetoothDevice;
24 import android.bluetooth.BluetoothHeadset;
25 import android.bluetooth.BluetoothProfile;
26 import android.compat.annotation.ChangeId;
27 import android.compat.annotation.EnabledSince;
28 import android.content.ContentResolver;
29 import android.content.Context;
30 import android.content.Intent;
31 import android.media.AudioAttributes;
32 import android.media.AudioDeviceAttributes;
33 import android.media.AudioDeviceInfo;
34 import android.media.AudioManager;
35 import android.media.AudioManager.AudioDeviceCategory;
36 import android.media.AudioPlaybackConfiguration;
37 import android.media.AudioRecordingConfiguration;
38 import android.media.AudioRoutesInfo;
39 import android.media.AudioSystem;
40 import android.media.BluetoothProfileConnectionInfo;
41 import android.media.IAudioRoutesObserver;
42 import android.media.ICapturePresetDevicesRoleDispatcher;
43 import android.media.ICommunicationDeviceDispatcher;
44 import android.media.IStrategyNonDefaultDevicesDispatcher;
45 import android.media.IStrategyPreferredDevicesDispatcher;
46 import android.media.MediaMetrics;
47 import android.media.audiopolicy.AudioProductStrategy;
48 import android.os.Binder;
49 import android.os.Handler;
50 import android.os.IBinder;
51 import android.os.Looper;
52 import android.os.Message;
53 import android.os.PowerManager;
54 import android.os.RemoteCallbackList;
55 import android.os.RemoteException;
56 import android.os.SystemClock;
57 import android.os.UserHandle;
58 import android.provider.Settings;
59 import android.sysprop.BluetoothProperties;
60 import android.text.TextUtils;
61 import android.util.Log;
62 import android.util.Pair;
63 import android.util.PrintWriterPrinter;
64 
65 import com.android.internal.annotations.GuardedBy;
66 import com.android.server.utils.EventLogger;
67 
68 import java.io.PrintWriter;
69 import java.util.ArrayList;
70 import java.util.Arrays;
71 import java.util.Collection;
72 import java.util.HashSet;
73 import java.util.LinkedList;
74 import java.util.List;
75 import java.util.NoSuchElementException;
76 import java.util.Objects;
77 import java.util.Set;
78 import java.util.concurrent.atomic.AtomicBoolean;
79 
80 /**
81  * @hide
82  * (non final for mocking/spying)
83  */
84 public class AudioDeviceBroker {
85 
86     private static final String TAG = "AS.AudioDeviceBroker";
87 
88     private static final long BROKER_WAKELOCK_TIMEOUT_MS = 5000; //5s
89 
90     /*package*/ static final  int BTA2DP_DOCK_TIMEOUT_MS = 8000;
91     // Timeout for connection to bluetooth headset service
92     /*package*/ static final int BT_HEADSET_CNCT_TIMEOUT_MS = 3000;
93 
94     // Delay before checking it music should be unmuted after processing an A2DP message
95     private static final int BTA2DP_MUTE_CHECK_DELAY_MS = 100;
96 
97     private final @NonNull AudioService mAudioService;
98     private final @NonNull Context mContext;
99     private final @NonNull AudioSystemAdapter mAudioSystem;
100 
101     /** ID for Communication strategy retrieved form audio policy manager */
102     /*package*/  int mCommunicationStrategyId = -1;
103 
104     /** ID for Accessibility strategy retrieved form audio policy manager */
105     private int mAccessibilityStrategyId = -1;
106 
107 
108     /** Active communication device reported by audio policy manager */
109     /*package*/ AudioDeviceInfo mActiveCommunicationDevice;
110     /** Last preferred device set for communication strategy */
111     private AudioDeviceAttributes mPreferredCommunicationDevice;
112 
113     // Manages all connected devices, only ever accessed on the message loop
114     private final AudioDeviceInventory mDeviceInventory;
115     // Manages notifications to BT service
116     private final BtHelper mBtHelper;
117     // Adapter for system_server-reserved operations
118     private final SystemServerAdapter mSystemServer;
119 
120 
121     //-------------------------------------------------------------------
122     // we use a different lock than mDeviceStateLock so as not to create
123     // lock contention between enqueueing a message and handling them
124     private static final Object sLastDeviceConnectionMsgTimeLock = new Object();
125     @GuardedBy("sLastDeviceConnectionMsgTimeLock")
126     private static long sLastDeviceConnectMsgTime = 0;
127 
128     // General lock to be taken whenever the state of the audio devices is to be checked or changed
129     private final Object mDeviceStateLock = new Object();
130 
131     // Request to override default use of A2DP for media.
132     private AtomicBoolean mBluetoothA2dpEnabled = new AtomicBoolean(false);
133 
134     // lock always taken when accessing AudioService.mSetModeDeathHandlers
135     // TODO do not "share" the lock between AudioService and BtHelpr, see b/123769055
136     /*package*/ final Object mSetModeLock = new Object();
137 
138     /** AudioModeInfo contains information on current audio mode owner
139      * communicated by AudioService */
140     /* package */ static final class AudioModeInfo {
141         /** Current audio mode */
142         final int mMode;
143         /** PID of current audio mode owner */
144         final int mPid;
145         /** UID of current audio mode owner */
146         final int mUid;
147 
AudioModeInfo(int mode, int pid, int uid)148         AudioModeInfo(int mode, int pid, int uid) {
149             mMode = mode;
150             mPid = pid;
151             mUid = uid;
152         }
153 
154         @Override
toString()155         public String toString() {
156             return "AudioModeInfo: mMode=" + AudioSystem.modeToString(mMode)
157                     + ", mPid=" + mPid
158                     + ", mUid=" + mUid;
159         }
160     };
161 
162     private AudioModeInfo mAudioModeOwner = new AudioModeInfo(AudioSystem.MODE_NORMAL, 0, 0);
163 
164     /**
165      * Indicates that default communication device is chosen by routing rules in audio policy
166      * manager and not forced by AudioDeviceBroker.
167      */
168     @ChangeId
169     @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.S_V2)
170     public static final long USE_SET_COMMUNICATION_DEVICE = 243827847L;
171 
172     /** Indicates if headset profile connection and SCO audio control use the new implementation
173      * aligned with other BT profiles. True if both the feature flag Flags.scoManagedByAudio() and
174      * the system property audio.sco.managed.by.audio are true.
175      */
176     private final boolean mScoManagedByAudio;
isScoManagedByAudio()177     /*package*/ boolean isScoManagedByAudio() {
178         return mScoManagedByAudio;
179     }
180 
181     //-------------------------------------------------------------------
AudioDeviceBroker(@onNull Context context, @NonNull AudioService service, @NonNull AudioSystemAdapter audioSystem)182     /*package*/ AudioDeviceBroker(@NonNull Context context, @NonNull AudioService service,
183             @NonNull AudioSystemAdapter audioSystem) {
184         mContext = context;
185         mAudioService = service;
186         mBtHelper = new BtHelper(this, context);
187         mDeviceInventory = new AudioDeviceInventory(this);
188         mSystemServer = SystemServerAdapter.getDefaultAdapter(mContext);
189         mAudioSystem = audioSystem;
190         mScoManagedByAudio = scoManagedByAudio()
191                 && BluetoothProperties.isScoManagedByAudioEnabled().orElse(false);
192         init();
193     }
194 
195     /** for test purposes only, inject AudioDeviceInventory and adapter for operations running
196      *  in system_server */
AudioDeviceBroker(@onNull Context context, @NonNull AudioService service, @NonNull AudioDeviceInventory mockDeviceInventory, @NonNull SystemServerAdapter mockSystemServer, @NonNull AudioSystemAdapter audioSystem)197     AudioDeviceBroker(@NonNull Context context, @NonNull AudioService service,
198                       @NonNull AudioDeviceInventory mockDeviceInventory,
199                       @NonNull SystemServerAdapter mockSystemServer,
200                       @NonNull AudioSystemAdapter audioSystem) {
201         mContext = context;
202         mAudioService = service;
203         mBtHelper = new BtHelper(this, context);
204         mDeviceInventory = mockDeviceInventory;
205         mSystemServer = mockSystemServer;
206         mAudioSystem = audioSystem;
207         mScoManagedByAudio = scoManagedByAudio()
208                 && BluetoothProperties.isScoManagedByAudioEnabled().orElse(false);
209         init();
210     }
211 
initRoutingStrategyIds()212     private void initRoutingStrategyIds() {
213         List<AudioProductStrategy> strategies = AudioProductStrategy.getAudioProductStrategies();
214         mCommunicationStrategyId = -1;
215         mAccessibilityStrategyId = -1;
216         for (AudioProductStrategy strategy : strategies) {
217             if (mCommunicationStrategyId == -1
218                     && strategy.getAudioAttributesForLegacyStreamType(
219                             AudioSystem.STREAM_VOICE_CALL) != null) {
220                 mCommunicationStrategyId = strategy.getId();
221             }
222             if (mAccessibilityStrategyId == -1
223                     && strategy.getAudioAttributesForLegacyStreamType(
224                             AudioSystem.STREAM_ACCESSIBILITY) != null) {
225                 mAccessibilityStrategyId = strategy.getId();
226             }
227         }
228     }
229 
init()230     private void init() {
231         setupMessaging(mContext);
232 
233         initAudioHalBluetoothState();
234         initRoutingStrategyIds();
235         mPreferredCommunicationDevice = null;
236         updateActiveCommunicationDevice();
237 
238         mSystemServer.registerUserStartedReceiver(mContext);
239     }
240 
getContext()241     /*package*/ Context getContext() {
242         return mContext;
243     }
244 
245     //---------------------------------------------------------------------
246     // Communication from AudioService
247     // All methods are asynchronous and never block
248     // All permission checks are done in AudioService, all incoming calls are considered "safe"
249     // All post* methods are asynchronous
250 
onSystemReady()251     /*package*/ void onSystemReady() {
252         synchronized (mSetModeLock) {
253             synchronized (mDeviceStateLock) {
254                 mAudioModeOwner = mAudioService.getAudioModeOwner();
255                 mBtHelper.onSystemReady();
256             }
257         }
258     }
259 
onAudioServerDied()260     /*package*/ void onAudioServerDied() {
261         // restore devices
262         sendMsgNoDelay(MSG_RESTORE_DEVICES, SENDMSG_REPLACE);
263     }
264 
setForceUse_Async(int useCase, int config, String eventSource)265     /*package*/ void setForceUse_Async(int useCase, int config, String eventSource) {
266         sendIILMsgNoDelay(MSG_IIL_SET_FORCE_USE, SENDMSG_QUEUE,
267                 useCase, config, eventSource);
268     }
269 
toggleHdmiIfConnected_Async()270     /*package*/ void toggleHdmiIfConnected_Async() {
271         sendMsgNoDelay(MSG_TOGGLE_HDMI, SENDMSG_QUEUE);
272     }
273 
274     /**
275      * Handle BluetoothHeadset intents where the action is one of
276      *   {@link BluetoothHeadset#ACTION_ACTIVE_DEVICE_CHANGED} or
277      *   {@link BluetoothHeadset#ACTION_AUDIO_STATE_CHANGED}.
278      * @param intent the Intent received from BT service
279      */
onReceiveBtEvent(@onNull Intent intent)280     private void onReceiveBtEvent(@NonNull Intent intent) {
281         mBtHelper.onReceiveBtEvent(intent);
282     }
283 
284     @GuardedBy("mDeviceStateLock")
onSetBtScoActiveDevice(BluetoothDevice btDevice)285     /*package*/ void onSetBtScoActiveDevice(BluetoothDevice btDevice) {
286         mBtHelper.onSetBtScoActiveDevice(btDevice);
287     }
288 
setBluetoothA2dpOn_Async(boolean on, String source)289     /*package*/ void setBluetoothA2dpOn_Async(boolean on, String source) {
290         boolean wasOn = mBluetoothA2dpEnabled.getAndSet(on);
291         // do not mute music if we do not anticipate a change in A2DP ON state
292         sendLMsgNoDelay(wasOn == on
293                 ? MSG_L_SET_FORCE_BT_A2DP_USE_NO_MUTE : MSG_L_SET_FORCE_BT_A2DP_USE,
294                 SENDMSG_REPLACE, source);
295     }
296 
297     /**
298      * Turns speakerphone on/off
299      * @param on true to enable speakerphone
300      * @param eventSource for logging purposes
301      */
setSpeakerphoneOn( IBinder cb, int uid, boolean on, boolean isPrivileged, String eventSource)302     /*package*/ void setSpeakerphoneOn(
303             IBinder cb, int uid, boolean on, boolean isPrivileged, String eventSource) {
304 
305         if (AudioService.DEBUG_COMM_RTE) {
306             Log.v(TAG, "setSpeakerphoneOn, on: " + on + " uid: " + uid);
307         }
308         postSetCommunicationDeviceForClient(new CommunicationDeviceInfo(
309                 cb, uid, new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_SPEAKER, ""),
310                 on, BtHelper.SCO_MODE_UNDEFINED, eventSource, isPrivileged));
311     }
312 
313     private static final long SET_COMMUNICATION_DEVICE_TIMEOUT_MS = 3000;
314 
315     /** synchronization for setCommunicationDevice() and getCommunicationDevice */
316     private final Object mCommunicationDeviceLock = new Object();
317     @GuardedBy("mCommunicationDeviceLock")
318     private int mCommunicationDeviceUpdateCount = 0;
319 
320     /**
321      * Select device for use for communication use cases.
322      * @param cb Client binder for death detection
323      * @param uid Client uid
324      * @param device Device selected or null to unselect.
325      * @param eventSource for logging purposes
326      * @return false if there is no device and no communication client
327      */
setCommunicationDevice(IBinder cb, int uid, AudioDeviceInfo device, boolean isPrivileged, String eventSource)328     /*package*/ boolean setCommunicationDevice(IBinder cb, int uid, AudioDeviceInfo device,
329                                                boolean isPrivileged, String eventSource) {
330 
331         if (AudioService.DEBUG_COMM_RTE) {
332             Log.v(TAG, "setCommunicationDevice, device: " + device + ", uid: " + uid);
333         }
334 
335         synchronized (mDeviceStateLock) {
336             if (device == null) {
337                 CommunicationRouteClient client = getCommunicationRouteClientForUid(uid);
338                 if (client == null) {
339                     return false;
340                 }
341             }
342         }
343         synchronized (mCommunicationDeviceLock) {
344             mCommunicationDeviceUpdateCount++;
345             AudioDeviceAttributes deviceAttr =
346                     (device != null) ? new AudioDeviceAttributes(device) : null;
347             CommunicationDeviceInfo deviceInfo = new CommunicationDeviceInfo(cb, uid, deviceAttr,
348                     device != null, BtHelper.SCO_MODE_UNDEFINED, eventSource, isPrivileged);
349             postSetCommunicationDeviceForClient(deviceInfo);
350         }
351         return true;
352     }
353 
354     /**
355      * Sets or resets the communication device for matching client. If no client matches and the
356      * request is to reset for a given device (deviceInfo.mOn == false), the method is a noop.
357      * @param deviceInfo information on the device and requester {@link #CommunicationDeviceInfo}
358      */
359     @GuardedBy("mDeviceStateLock")
onSetCommunicationDeviceForClient(CommunicationDeviceInfo deviceInfo)360     /*package*/ void onSetCommunicationDeviceForClient(CommunicationDeviceInfo deviceInfo) {
361         if (AudioService.DEBUG_COMM_RTE) {
362             Log.v(TAG, "onSetCommunicationDeviceForClient: " + deviceInfo);
363         }
364         if (!deviceInfo.mOn) {
365             CommunicationRouteClient client = getCommunicationRouteClientForUid(deviceInfo.mUid);
366             if (client == null || (deviceInfo.mDevice != null
367                     && !deviceInfo.mDevice.equals(client.getDevice()))) {
368                 return;
369             }
370         }
371 
372         AudioDeviceAttributes device = deviceInfo.mOn ? deviceInfo.mDevice : null;
373         setCommunicationRouteForClient(deviceInfo.mCb, deviceInfo.mUid, device,
374                 deviceInfo.mScoAudioMode, deviceInfo.mIsPrivileged, deviceInfo.mEventSource);
375     }
376 
377     @GuardedBy("mDeviceStateLock")
setCommunicationRouteForClient( IBinder cb, int uid, AudioDeviceAttributes device, int scoAudioMode, boolean isPrivileged, String eventSource)378     /*package*/ void setCommunicationRouteForClient(
379                             IBinder cb, int uid, AudioDeviceAttributes device,
380                             int scoAudioMode, boolean isPrivileged, String eventSource) {
381 
382         if (AudioService.DEBUG_COMM_RTE) {
383             Log.v(TAG, "setCommunicationRouteForClient: device: " + device
384                     + ", eventSource: " + eventSource);
385         }
386         AudioService.sDeviceLogger.enqueue((new EventLogger.StringEvent(
387                                         "setCommunicationRouteForClient for uid: " + uid
388                                         + " device: " + device + " isPrivileged: " + isPrivileged
389                                         + " from API: " + eventSource)).printLog(TAG));
390 
391         final boolean wasBtScoRequested = isBluetoothScoRequested();
392         CommunicationRouteClient client;
393 
394         // Save previous client route in case of failure to start BT SCO audio
395         AudioDeviceAttributes prevClientDevice = null;
396         boolean prevPrivileged = false;
397         client = getCommunicationRouteClientForUid(uid);
398         if (client != null) {
399             prevClientDevice = client.getDevice();
400             prevPrivileged = client.isPrivileged();
401         }
402 
403         if (device != null) {
404             client = addCommunicationRouteClient(cb, uid, device, isPrivileged);
405             if (client == null) {
406                 Log.w(TAG, "setCommunicationRouteForClient: could not add client for uid: "
407                         + uid + " and device: " + device);
408             }
409         } else {
410             client = removeCommunicationRouteClient(cb, true);
411         }
412         if (client == null) {
413             return;
414         }
415         if (!mScoManagedByAudio) {
416             boolean isBtScoRequested = isBluetoothScoRequested();
417             if (isBtScoRequested && (!wasBtScoRequested || !isBluetoothScoActive())) {
418                 if (!mBtHelper.startBluetoothSco(scoAudioMode, eventSource)) {
419                     Log.w(TAG, "setCommunicationRouteForClient: failure to start BT SCO for uid: "
420                             + uid);
421                     // clean up or restore previous client selection
422                     if (prevClientDevice != null) {
423                         addCommunicationRouteClient(cb, uid, prevClientDevice, prevPrivileged);
424                     } else {
425                         removeCommunicationRouteClient(cb, true);
426                     }
427                     postBroadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
428                 }
429             } else if (!isBtScoRequested && wasBtScoRequested) {
430                 mBtHelper.stopBluetoothSco(eventSource);
431             }
432         }
433         // In BT classic for communication, the device changes from a2dp to sco device, but for
434         // LE Audio it stays the same and we must trigger the proper stream volume alignment, if
435         // LE Audio communication device is activated after the audio system has already switched to
436         // MODE_IN_CALL mode.
437         if (isBluetoothLeAudioRequested() && device != null) {
438             final int streamType = mAudioService.getBluetoothContextualVolumeStream();
439             final int leAudioVolIndex = getVssVolumeForDevice(streamType, device.getInternalType());
440             final int leAudioMaxVolIndex = getMaxVssVolumeForStream(streamType);
441             if (AudioService.DEBUG_COMM_RTE) {
442                 Log.v(TAG, "setCommunicationRouteForClient restoring LE Audio device volume lvl.");
443             }
444             postSetLeAudioVolumeIndex(leAudioVolIndex, leAudioMaxVolIndex, streamType);
445         }
446 
447         updateCommunicationRoute(eventSource);
448     }
449 
450     /**
451      * Returns the communication client with the highest priority:
452      * - 1) the client which is currently also controlling the audio mode
453      * - 2) the first client in the stack if there is no audio mode owner
454      * - 3) no client otherwise
455      * @return CommunicationRouteClient the client driving the communication use case routing.
456      */
457     @GuardedBy("mDeviceStateLock")
topCommunicationRouteClient()458     private CommunicationRouteClient topCommunicationRouteClient() {
459         for (CommunicationRouteClient crc : mCommunicationRouteClients) {
460             if (crc.getUid() == mAudioModeOwner.mUid) {
461                 return crc;
462             }
463         }
464         if (!mCommunicationRouteClients.isEmpty() && mAudioModeOwner.mPid == 0
465                 && mCommunicationRouteClients.get(0).isActive()) {
466             return mCommunicationRouteClients.get(0);
467         }
468         return null;
469     }
470 
471     /**
472      * Returns the device currently requested for communication use case.
473      * Use the device requested by the communication route client selected by
474      * {@link #topCommunicationRouteClient()} if any or none otherwise.
475      * @return AudioDeviceAttributes the requested device for communication.
476      */
477     @GuardedBy("mDeviceStateLock")
requestedCommunicationDevice()478     private AudioDeviceAttributes requestedCommunicationDevice() {
479         CommunicationRouteClient crc = topCommunicationRouteClient();
480         AudioDeviceAttributes device = crc != null ? crc.getDevice() : null;
481         if (AudioService.DEBUG_COMM_RTE) {
482             Log.v(TAG, "requestedCommunicationDevice: "
483                     + device + " mAudioModeOwner: " + mAudioModeOwner.toString());
484         }
485         return device;
486     }
487 
488     private static final int[] VALID_COMMUNICATION_DEVICE_TYPES = {
489             AudioDeviceInfo.TYPE_BUILTIN_SPEAKER,
490             AudioDeviceInfo.TYPE_BLUETOOTH_SCO,
491             AudioDeviceInfo.TYPE_WIRED_HEADSET,
492             AudioDeviceInfo.TYPE_USB_HEADSET,
493             AudioDeviceInfo.TYPE_BUILTIN_EARPIECE,
494             AudioDeviceInfo.TYPE_WIRED_HEADPHONES,
495             AudioDeviceInfo.TYPE_HEARING_AID,
496             AudioDeviceInfo.TYPE_BLE_HEADSET,
497             AudioDeviceInfo.TYPE_USB_DEVICE,
498             AudioDeviceInfo.TYPE_BLE_SPEAKER,
499             AudioDeviceInfo.TYPE_LINE_ANALOG,
500             AudioDeviceInfo.TYPE_HDMI,
501             AudioDeviceInfo.TYPE_AUX_LINE
502     };
503 
isValidCommunicationDevice(@onNull AudioDeviceInfo device)504     /*package */ static boolean isValidCommunicationDevice(@NonNull AudioDeviceInfo device) {
505         Objects.requireNonNull(device, "device must not be null");
506         return device.isSink() && isValidCommunicationDeviceType(device.getType());
507     }
508 
isValidCommunicationDeviceType(int deviceType)509     private static boolean isValidCommunicationDeviceType(int deviceType) {
510         for (int type : VALID_COMMUNICATION_DEVICE_TYPES) {
511             if (deviceType == type) {
512                 return true;
513             }
514         }
515         return false;
516     }
517 
518     /*package */
postCheckCommunicationDeviceRemoval(@onNull AudioDeviceAttributes device)519     void postCheckCommunicationDeviceRemoval(@NonNull AudioDeviceAttributes device) {
520         if (!isValidCommunicationDeviceType(
521                 AudioDeviceInfo.convertInternalDeviceToDeviceType(device.getInternalType()))) {
522             return;
523         }
524         sendLMsgNoDelay(MSG_L_CHECK_COMMUNICATION_DEVICE_REMOVAL, SENDMSG_QUEUE, device);
525     }
526 
527     @GuardedBy("mDeviceStateLock")
onCheckCommunicationDeviceRemoval(@onNull AudioDeviceAttributes device)528     void onCheckCommunicationDeviceRemoval(@NonNull AudioDeviceAttributes device) {
529         if (AudioService.DEBUG_COMM_RTE) {
530             Log.v(TAG, "onCheckCommunicationDeviceRemoval device: " + device.toString());
531         }
532         for (CommunicationRouteClient crc : mCommunicationRouteClients) {
533             if (device.equals(crc.getDevice())) {
534                 if (AudioService.DEBUG_COMM_RTE) {
535                     Log.v(TAG, "onCheckCommunicationDeviceRemoval removing client: "
536                             + crc.toString());
537                 }
538                 // Cancelling the route for this client will remove it from the stack and update
539                 // the communication route.
540                 CommunicationDeviceInfo deviceInfo = new CommunicationDeviceInfo(
541                         crc.getBinder(), crc.getUid(), device, false,
542                         BtHelper.SCO_MODE_UNDEFINED, "onCheckCommunicationDeviceRemoval",
543                         crc.isPrivileged());
544                 postSetCommunicationDeviceForClient(deviceInfo);
545             }
546         }
547     }
548 
549     // check playback or record activity after 6 seconds for UIDs
550     private static final int CHECK_CLIENT_STATE_DELAY_MS = 6000;
551 
552     /*package */
postCheckCommunicationRouteClientState(int uid, boolean wasActive, int delay)553     void postCheckCommunicationRouteClientState(int uid, boolean wasActive, int delay) {
554         CommunicationRouteClient client = getCommunicationRouteClientForUid(uid);
555         if (client != null) {
556             sendMsgForCheckClientState(MSG_CHECK_COMMUNICATION_ROUTE_CLIENT_STATE,
557                                         SENDMSG_REPLACE,
558                                         uid,
559                                         wasActive ? 1 : 0,
560                                         client,
561                                         delay);
562         }
563     }
564 
565     @GuardedBy("mDeviceStateLock")
onCheckCommunicationRouteClientState(int uid, boolean wasActive)566     void onCheckCommunicationRouteClientState(int uid, boolean wasActive) {
567         CommunicationRouteClient client = getCommunicationRouteClientForUid(uid);
568         if (client == null) {
569             return;
570         }
571         updateCommunicationRouteClientState(client, wasActive);
572     }
573 
574     @GuardedBy("mDeviceStateLock")
updateCommunicationRouteClientState( CommunicationRouteClient client, boolean wasActive)575     /*package*/ void updateCommunicationRouteClientState(
576                             CommunicationRouteClient client, boolean wasActive) {
577         boolean wasBtScoRequested = isBluetoothScoRequested();
578         client.setPlaybackActive(mAudioService.isPlaybackActiveForUid(client.getUid()));
579         client.setRecordingActive(mAudioService.isRecordingActiveForUid(client.getUid()));
580         if (wasActive != client.isActive()) {
581             postUpdateCommunicationRouteClient(
582                     wasBtScoRequested, "updateCommunicationRouteClientState");
583         }
584     }
585 
586     @GuardedBy("mDeviceStateLock")
setForceCommunicationClientStateAndDelayedCheck( CommunicationRouteClient client, boolean forcePlaybackActive, boolean forceRecordingActive)587     /*package*/ void setForceCommunicationClientStateAndDelayedCheck(
588                             CommunicationRouteClient client,
589                             boolean forcePlaybackActive,
590                             boolean forceRecordingActive) {
591         if (client == null) {
592             return;
593         }
594         if (forcePlaybackActive) {
595             client.setPlaybackActive(true);
596         }
597         if (forceRecordingActive) {
598             client.setRecordingActive(true);
599         }
600         postCheckCommunicationRouteClientState(
601                 client.getUid(), client.isActive(), CHECK_CLIENT_STATE_DELAY_MS);
602     }
603 
getAvailableCommunicationDevices()604     /* package */ static List<AudioDeviceInfo> getAvailableCommunicationDevices() {
605         ArrayList<AudioDeviceInfo> commDevices = new ArrayList<>();
606         AudioDeviceInfo[] allDevices =
607                 AudioManager.getDevicesStatic(AudioManager.GET_DEVICES_OUTPUTS);
608         for (AudioDeviceInfo device : allDevices) {
609             if (isValidCommunicationDevice(device)) {
610                 commDevices.add(device);
611             }
612         }
613         return commDevices;
614     }
615 
getCommunicationDeviceOfType(int type)616     private @Nullable AudioDeviceInfo getCommunicationDeviceOfType(int type) {
617         return getAvailableCommunicationDevices().stream().filter(d -> d.getType() == type)
618                 .findFirst().orElse(null);
619     }
620 
621     /**
622      * Returns the device currently requested for communication use case.
623      * @return AudioDeviceInfo the requested device for communication.
624      */
getCommunicationDevice()625     /* package */ AudioDeviceInfo getCommunicationDevice() {
626         synchronized (mCommunicationDeviceLock) {
627             final long start = System.currentTimeMillis();
628             long elapsed = 0;
629             while (mCommunicationDeviceUpdateCount > 0) {
630                 try {
631                     mCommunicationDeviceLock.wait(
632                             SET_COMMUNICATION_DEVICE_TIMEOUT_MS - elapsed);
633                 } catch (InterruptedException e) {
634                     Log.w(TAG, "Interrupted while waiting for communication device update.");
635                 }
636                 elapsed = System.currentTimeMillis() - start;
637                 if (elapsed >= SET_COMMUNICATION_DEVICE_TIMEOUT_MS) {
638                     Log.e(TAG, "Timeout waiting for communication device update.");
639                     break;
640                 }
641             }
642         }
643         synchronized (mDeviceStateLock) {
644             return getCommunicationDeviceInt();
645         }
646     }
647 
648     @GuardedBy("mDeviceStateLock")
getCommunicationDeviceInt()649     private AudioDeviceInfo  getCommunicationDeviceInt() {
650         updateActiveCommunicationDevice();
651         AudioDeviceInfo device = mActiveCommunicationDevice;
652         // make sure we return a valid communication device (i.e. a device that is allowed by
653         // setCommunicationDevice()) for consistency.
654         if (device != null) {
655             // a digital dock is used instead of the speaker in speakerphone mode and should
656             // be reflected as such
657             if (device.getType() == AudioDeviceInfo.TYPE_DOCK) {
658                 device = getCommunicationDeviceOfType(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER);
659             }
660         }
661         // Try to default to earpiece when current communication device is not valid. This can
662         // happen for instance if no call is active. If no earpiece device is available take the
663         // first valid communication device
664         if (device == null || !AudioDeviceBroker.isValidCommunicationDevice(device)) {
665             device = getCommunicationDeviceOfType(AudioDeviceInfo.TYPE_BUILTIN_EARPIECE);
666             if (device == null) {
667                 List<AudioDeviceInfo> commDevices = getAvailableCommunicationDevices();
668                 if (!commDevices.isEmpty()) {
669                     device = commDevices.get(0);
670                 }
671             }
672         }
673         return device;
674     }
675 
676     /**
677      * Updates currently active communication device (mActiveCommunicationDevice).
678      */
679     @GuardedBy("mDeviceStateLock")
updateActiveCommunicationDevice()680     void updateActiveCommunicationDevice() {
681         AudioDeviceAttributes device = preferredCommunicationDevice();
682         if (device == null) {
683             AudioAttributes attr =
684                     AudioProductStrategy.getAudioAttributesForStrategyWithLegacyStreamType(
685                             AudioSystem.STREAM_VOICE_CALL);
686             List<AudioDeviceAttributes> devices = mAudioSystem.getDevicesForAttributes(
687                     attr, false /* forVolume */);
688             if (devices.isEmpty()) {
689                 if (mAudioService.isPlatformVoice()) {
690                     Log.w(TAG,
691                             "updateActiveCommunicationDevice(): no device for phone strategy");
692                 }
693                 mActiveCommunicationDevice = null;
694                 return;
695             }
696             device = devices.get(0);
697         }
698         mActiveCommunicationDevice = AudioManager.getDeviceInfoFromTypeAndAddress(
699                 device.getType(), device.getAddress());
700     }
701 
702     /**
703      * Indicates if the device which type is passed as argument is currently resquested to be used
704      * for communication.
705      * @param deviceType the device type the query applies to.
706      * @return true if this device type is requested for communication.
707      */
isDeviceRequestedForCommunication(int deviceType)708     private boolean isDeviceRequestedForCommunication(int deviceType) {
709         synchronized (mDeviceStateLock) {
710             AudioDeviceAttributes device = requestedCommunicationDevice();
711             return device != null && device.getType() == deviceType;
712         }
713     }
714 
715     /**
716      * Indicates if the device which type is passed as argument is currently either resquested
717      * to be used for communication or selected for an other reason (e.g bluetooth SCO audio
718      * is active for SCO device).
719      * @param deviceType the device type the query applies to.
720      * @return true if this device type is requested for communication.
721      */
isDeviceOnForCommunication(int deviceType)722     private boolean isDeviceOnForCommunication(int deviceType) {
723         synchronized (mDeviceStateLock) {
724             AudioDeviceAttributes device = preferredCommunicationDevice();
725             return device != null && device.getType() == deviceType;
726         }
727     }
728 
729     /**
730      * Indicates if the device which type is passed as argument is active for communication.
731      * Active means not only currently used by audio policy manager for communication strategy
732      * but also explicitly requested for use by communication strategy.
733      * @param deviceType the device type the query applies to.
734      * @return true if this device type is requested for communication.
735      */
isDeviceActiveForCommunication(int deviceType)736     private boolean isDeviceActiveForCommunication(int deviceType) {
737         return mActiveCommunicationDevice != null
738                 && mActiveCommunicationDevice.getType() == deviceType
739                 && mPreferredCommunicationDevice != null
740                 && mPreferredCommunicationDevice.getType() == deviceType;
741     }
742 
743     /**
744      * Indicates if preferred route selection for communication is speakerphone.
745      * @return true if speakerphone is active, false otherwise.
746      */
isSpeakerphoneOn()747     /*package*/ boolean isSpeakerphoneOn() {
748         return isDeviceOnForCommunication(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER);
749     }
750 
isSpeakerphoneActive()751     private boolean isSpeakerphoneActive() {
752         return isDeviceActiveForCommunication(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER);
753     }
754 
755     /**
756      * Helper method on top of isDeviceRequestedForCommunication() indicating if
757      * Bluetooth SCO ON is currently requested or not.
758      * @return true if Bluetooth SCO ON is requested, false otherwise.
759      */
isBluetoothScoRequested()760     /*package*/ boolean isBluetoothScoRequested() {
761         return isDeviceRequestedForCommunication(AudioDeviceInfo.TYPE_BLUETOOTH_SCO);
762     }
763 
764     /**
765      * Helper method on top of isDeviceRequestedForCommunication() indicating if
766      * Bluetooth LE Audio communication device is currently requested or not.
767      * @return true if Bluetooth LE Audio device is requested, false otherwise.
768      */
isBluetoothLeAudioRequested()769     /*package*/ boolean isBluetoothLeAudioRequested() {
770         return isDeviceRequestedForCommunication(AudioDeviceInfo.TYPE_BLE_HEADSET)
771                 || isDeviceRequestedForCommunication(AudioDeviceInfo.TYPE_BLE_SPEAKER);
772     }
773 
774     /**
775      * Indicates if preferred route selection for communication is Bluetooth SCO.
776      * @return true if Bluetooth SCO is preferred , false otherwise.
777      */
isBluetoothScoOn()778     /*package*/ boolean isBluetoothScoOn() {
779         return isDeviceOnForCommunication(AudioDeviceInfo.TYPE_BLUETOOTH_SCO);
780     }
781 
isBluetoothScoActive()782     /*package*/ boolean isBluetoothScoActive() {
783         return isDeviceActiveForCommunication(AudioDeviceInfo.TYPE_BLUETOOTH_SCO);
784     }
785 
isDeviceConnected(@onNull AudioDeviceAttributes device)786     /*package*/ boolean isDeviceConnected(@NonNull AudioDeviceAttributes device) {
787         synchronized (mDeviceStateLock) {
788             return mDeviceInventory.isDeviceConnected(device);
789         }
790     }
791 
setWiredDeviceConnectionState(AudioDeviceAttributes attributes, @AudioService.ConnectionState int state, String caller)792     /*package*/ void setWiredDeviceConnectionState(AudioDeviceAttributes attributes,
793             @AudioService.ConnectionState int state, String caller) {
794         //TODO move logging here just like in setBluetooth* methods
795         synchronized (mDeviceStateLock) {
796             mDeviceInventory.setWiredDeviceConnectionState(attributes, state, caller);
797         }
798     }
799 
setTestDeviceConnectionState(@onNull AudioDeviceAttributes device, @AudioService.ConnectionState int state)800     /*package*/ void setTestDeviceConnectionState(@NonNull AudioDeviceAttributes device,
801             @AudioService.ConnectionState int state) {
802         synchronized (mDeviceStateLock) {
803             mDeviceInventory.setTestDeviceConnectionState(device, state);
804         }
805     }
806 
807     /*package*/ static final class BleVolumeInfo {
808         final int mIndex;
809         final int mMaxIndex;
810         final int mStreamType;
811 
BleVolumeInfo(int index, int maxIndex, int streamType)812         BleVolumeInfo(int index, int maxIndex, int streamType) {
813             mIndex = index;
814             mMaxIndex = maxIndex;
815             mStreamType = streamType;
816         }
817     };
818 
819     /*package*/ static final class BtDeviceChangedData {
820         final @Nullable BluetoothDevice mNewDevice;
821         final @Nullable BluetoothDevice mPreviousDevice;
822         final @NonNull BluetoothProfileConnectionInfo mInfo;
823         final @NonNull String mEventSource;
824 
BtDeviceChangedData(@ullable BluetoothDevice newDevice, @Nullable BluetoothDevice previousDevice, @NonNull BluetoothProfileConnectionInfo info, @NonNull String eventSource)825         BtDeviceChangedData(@Nullable BluetoothDevice newDevice,
826                 @Nullable BluetoothDevice previousDevice,
827                 @NonNull BluetoothProfileConnectionInfo info, @NonNull String eventSource) {
828             mNewDevice = newDevice;
829             mPreviousDevice = previousDevice;
830             mInfo = info;
831             mEventSource = eventSource;
832         }
833 
834         @Override
toString()835         public String toString() {
836             return "BtDeviceChangedData profile=" + BluetoothProfile.getProfileName(
837                     mInfo.getProfile())
838                 + ", switch device: [" + mPreviousDevice + "] -> [" + mNewDevice + "]";
839         }
840     }
841 
842     /*package*/ static final class BtDeviceInfo {
843         final @NonNull BluetoothDevice mDevice;
844         final @AudioService.BtProfileConnectionState int mState;
845         final @AudioService.BtProfile int mProfile;
846         final boolean mSupprNoisy;
847         final int mVolume;
848         final boolean mIsLeOutput;
849         final @NonNull String mEventSource;
850         final int mAudioSystemDevice;
851         final int mMusicDevice;
852 
BtDeviceInfo(@onNull BtDeviceChangedData d, @NonNull BluetoothDevice device, int state, int audioDevice, @AudioSystem.AudioFormatNativeEnumForBtCodec int codec)853         BtDeviceInfo(@NonNull BtDeviceChangedData d, @NonNull BluetoothDevice device, int state,
854                     int audioDevice, @AudioSystem.AudioFormatNativeEnumForBtCodec int codec) {
855             mDevice = device;
856             mState = state;
857             mProfile = d.mInfo.getProfile();
858             mSupprNoisy = d.mInfo.isSuppressNoisyIntent();
859             mVolume = d.mInfo.getVolume();
860             mIsLeOutput = d.mInfo.isLeOutput();
861             mEventSource = d.mEventSource;
862             mAudioSystemDevice = audioDevice;
863             mMusicDevice = AudioSystem.DEVICE_NONE;
864         }
865 
866         // constructor used by AudioDeviceBroker to search similar message
BtDeviceInfo(@onNull BluetoothDevice device, int profile)867         BtDeviceInfo(@NonNull BluetoothDevice device, int profile) {
868             mDevice = device;
869             mProfile = profile;
870             mEventSource = "";
871             mMusicDevice = AudioSystem.DEVICE_NONE;
872             mAudioSystemDevice = 0;
873             mState = 0;
874             mSupprNoisy = false;
875             mVolume = -1;
876             mIsLeOutput = false;
877         }
878 
879         // constructor used by AudioDeviceInventory when config change failed
BtDeviceInfo(@onNull BluetoothDevice device, int profile, int state, int musicDevice, int audioSystemDevice)880         BtDeviceInfo(@NonNull BluetoothDevice device, int profile, int state, int musicDevice,
881                     int audioSystemDevice) {
882             mDevice = device;
883             mProfile = profile;
884             mEventSource = "";
885             mMusicDevice = musicDevice;
886             mAudioSystemDevice = audioSystemDevice;
887             mState = state;
888             mSupprNoisy = false;
889             mVolume = -1;
890             mIsLeOutput = false;
891         }
892 
BtDeviceInfo(@onNull BtDeviceInfo src, int state)893         BtDeviceInfo(@NonNull BtDeviceInfo src, int state) {
894             mDevice = src.mDevice;
895             mState = state;
896             mProfile = src.mProfile;
897             mSupprNoisy = src.mSupprNoisy;
898             mVolume = src.mVolume;
899             mIsLeOutput = src.mIsLeOutput;
900             mEventSource = src.mEventSource;
901             mAudioSystemDevice = src.mAudioSystemDevice;
902             mMusicDevice = src.mMusicDevice;
903         }
904 
905         // redefine equality op so we can match messages intended for this device
906         @Override
equals(Object o)907         public boolean equals(Object o) {
908             if (o == null) {
909                 return false;
910             }
911             if (this == o) {
912                 return true;
913             }
914             if (o instanceof BtDeviceInfo) {
915                 return mProfile == ((BtDeviceInfo) o).mProfile
916                     && mDevice.equals(((BtDeviceInfo) o).mDevice);
917             }
918             return false;
919         }
920 
921         @Override
hashCode()922         public int hashCode() {
923             // only hashing on the fields used in equals()
924             return Objects.hash(mProfile, mDevice);
925         }
926 
927         @Override
toString()928         public String toString() {
929             return "BtDeviceInfo: device=" + mDevice.toString()
930                             + " state=" + mState
931                             + " prof=" + mProfile
932                             + " supprNoisy=" + mSupprNoisy
933                             + " volume=" + mVolume
934                             + " isLeOutput=" + mIsLeOutput
935                             + " eventSource=" + mEventSource
936                             + " audioSystemDevice=" + mAudioSystemDevice
937                             + " musicDevice=" + mMusicDevice;
938         }
939     }
940 
createBtDeviceInfo(@onNull BtDeviceChangedData d, @NonNull BluetoothDevice device, int state)941     BtDeviceInfo createBtDeviceInfo(@NonNull BtDeviceChangedData d, @NonNull BluetoothDevice device,
942                 int state) {
943         int audioDevice;
944         int codec = AudioSystem.AUDIO_FORMAT_DEFAULT;
945         switch (d.mInfo.getProfile()) {
946             case BluetoothProfile.A2DP_SINK:
947                 audioDevice = AudioSystem.DEVICE_IN_BLUETOOTH_A2DP;
948                 break;
949             case BluetoothProfile.A2DP:
950                 audioDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP;
951                 break;
952             case BluetoothProfile.HEARING_AID:
953                 audioDevice = AudioSystem.DEVICE_OUT_HEARING_AID;
954                 break;
955             case BluetoothProfile.LE_AUDIO:
956                 if (d.mInfo.isLeOutput()) {
957                     audioDevice = AudioSystem.DEVICE_OUT_BLE_HEADSET;
958                 } else {
959                     audioDevice = AudioSystem.DEVICE_IN_BLE_HEADSET;
960                 }
961                 break;
962             case BluetoothProfile.LE_AUDIO_BROADCAST:
963                 audioDevice = AudioSystem.DEVICE_OUT_BLE_BROADCAST;
964                 break;
965             case BluetoothProfile.HEADSET:
966                 // the actual device type is not important at this point and
967                 // will be set by BtHelper.handleBtScoActiveDeviceChange()
968                 audioDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO;
969                 break;
970             default: throw new IllegalArgumentException("Invalid profile " + d.mInfo.getProfile());
971         }
972         return new BtDeviceInfo(d, device, state, audioDevice, codec);
973     }
974 
btMediaMetricRecord(@onNull BluetoothDevice device, String state, @NonNull BtDeviceChangedData data)975     private void btMediaMetricRecord(@NonNull BluetoothDevice device, String state,
976             @NonNull BtDeviceChangedData data) {
977         final String name = TextUtils.emptyIfNull(device.getName());
978         new MediaMetrics.Item(MediaMetrics.Name.AUDIO_DEVICE + MediaMetrics.SEPARATOR
979                 + "queueOnBluetoothActiveDeviceChanged")
980             .set(MediaMetrics.Property.STATE, state)
981             .set(MediaMetrics.Property.STATUS, data.mInfo.getProfile())
982             .set(MediaMetrics.Property.NAME, name)
983             .record();
984     }
985 
986     /**
987      * will block on mDeviceStateLock, which is held during an A2DP (dis) connection
988      * not just a simple message post
989      * @param data struct with the (dis)connection information
990      */
queueOnBluetoothActiveDeviceChanged(@onNull BtDeviceChangedData data)991     /*package*/ void queueOnBluetoothActiveDeviceChanged(@NonNull BtDeviceChangedData data) {
992         if (data.mPreviousDevice != null
993                 && data.mPreviousDevice.equals(data.mNewDevice)) {
994             final String name = TextUtils.emptyIfNull(data.mNewDevice.getName());
995             new MediaMetrics.Item(MediaMetrics.Name.AUDIO_DEVICE + MediaMetrics.SEPARATOR
996                     + "queueOnBluetoothActiveDeviceChanged_update")
997                     .set(MediaMetrics.Property.NAME, name)
998                     .set(MediaMetrics.Property.STATUS, data.mInfo.getProfile())
999                     .record();
1000             synchronized (mDeviceStateLock) {
1001                 postBluetoothDeviceConfigChange(createBtDeviceInfo(data, data.mNewDevice,
1002                         BluetoothProfile.STATE_CONNECTED));
1003             }
1004         } else {
1005             synchronized (mDeviceStateLock) {
1006                 if (data.mPreviousDevice != null) {
1007                     btMediaMetricRecord(data.mPreviousDevice, MediaMetrics.Value.DISCONNECTED,
1008                             data);
1009                     sendLMsgNoDelay(MSG_L_BT_ACTIVE_DEVICE_CHANGE_EXT, SENDMSG_QUEUE,
1010                             createBtDeviceInfo(data, data.mPreviousDevice,
1011                                     BluetoothProfile.STATE_DISCONNECTED));
1012                 }
1013                 if (data.mNewDevice != null) {
1014                     btMediaMetricRecord(data.mNewDevice, MediaMetrics.Value.CONNECTED, data);
1015                     sendLMsgNoDelay(MSG_L_BT_ACTIVE_DEVICE_CHANGE_EXT, SENDMSG_QUEUE,
1016                             createBtDeviceInfo(data, data.mNewDevice,
1017                                     BluetoothProfile.STATE_CONNECTED));
1018                 }
1019             }
1020         }
1021     }
1022 
1023     // Lock protecting state variable related to Bluetooth audio state
1024     private final Object mBluetoothAudioStateLock = new Object();
1025 
1026     // Current Bluetooth SCO audio active state indicated by BtHelper via setBluetoothScoOn().
1027     @GuardedBy("mBluetoothAudioStateLock")
1028     private boolean mBluetoothScoOn;
1029     // value of BT_SCO parameter currently applied to audio HAL.
1030     @GuardedBy("mBluetoothAudioStateLock")
1031     private boolean mBluetoothScoOnApplied;
1032 
1033     // A2DP suspend state requested by AudioManager.setA2dpSuspended() API.
1034     @GuardedBy("mBluetoothAudioStateLock")
1035     private boolean mBluetoothA2dpSuspendedExt;
1036     // A2DP suspend state requested by AudioDeviceInventory.
1037     @GuardedBy("mBluetoothAudioStateLock")
1038     private boolean mBluetoothA2dpSuspendedInt;
1039     // value of BT_A2dpSuspendedSCO parameter currently applied to audio HAL.
1040 
1041     @GuardedBy("mBluetoothAudioStateLock")
1042     private boolean mBluetoothA2dpSuspendedApplied;
1043 
1044     // LE Audio suspend state requested by AudioManager.setLeAudioSuspended() API.
1045     @GuardedBy("mBluetoothAudioStateLock")
1046     private boolean mBluetoothLeSuspendedExt;
1047     // LE Audio suspend state requested by AudioDeviceInventory.
1048     @GuardedBy("mBluetoothAudioStateLock")
1049     private boolean mBluetoothLeSuspendedInt;
1050     // value of LeAudioSuspended parameter currently applied to audio HAL.
1051     @GuardedBy("mBluetoothAudioStateLock")
1052     private boolean mBluetoothLeSuspendedApplied;
1053 
initAudioHalBluetoothState()1054     private void initAudioHalBluetoothState() {
1055         synchronized (mBluetoothAudioStateLock) {
1056             mBluetoothScoOnApplied = false;
1057             mBluetoothA2dpSuspendedApplied = false;
1058             mBluetoothLeSuspendedApplied = false;
1059             reapplyAudioHalBluetoothState();
1060         }
1061     }
1062 
1063     @GuardedBy("mBluetoothAudioStateLock")
updateAudioHalBluetoothState()1064     private void updateAudioHalBluetoothState() {
1065         if (mBluetoothScoOn != mBluetoothScoOnApplied) {
1066             if (AudioService.DEBUG_COMM_RTE) {
1067                 Log.v(TAG, "updateAudioHalBluetoothState() mBluetoothScoOn: "
1068                         + mBluetoothScoOn + ", mBluetoothScoOnApplied: " + mBluetoothScoOnApplied);
1069             }
1070             if (mBluetoothScoOn) {
1071                 if (!mBluetoothA2dpSuspendedApplied) {
1072                     AudioSystem.setParameters("A2dpSuspended=true");
1073                     mBluetoothA2dpSuspendedApplied = true;
1074                 }
1075                 if (!mBluetoothLeSuspendedApplied) {
1076                     AudioSystem.setParameters("LeAudioSuspended=true");
1077                     mBluetoothLeSuspendedApplied = true;
1078                 }
1079                 AudioSystem.setParameters("BT_SCO=on");
1080             } else {
1081                 AudioSystem.setParameters("BT_SCO=off");
1082             }
1083             mBluetoothScoOnApplied = mBluetoothScoOn;
1084         }
1085         if (!mBluetoothScoOnApplied) {
1086             if ((mBluetoothA2dpSuspendedExt || mBluetoothA2dpSuspendedInt)
1087                     != mBluetoothA2dpSuspendedApplied) {
1088                 if (AudioService.DEBUG_COMM_RTE) {
1089                     Log.v(TAG, "updateAudioHalBluetoothState() mBluetoothA2dpSuspendedExt: "
1090                             + mBluetoothA2dpSuspendedExt
1091                             + ", mBluetoothA2dpSuspendedInt: " + mBluetoothA2dpSuspendedInt
1092                             + ", mBluetoothA2dpSuspendedApplied: "
1093                             + mBluetoothA2dpSuspendedApplied);
1094                 }
1095                 mBluetoothA2dpSuspendedApplied =
1096                         mBluetoothA2dpSuspendedExt || mBluetoothA2dpSuspendedInt;
1097                 if (mBluetoothA2dpSuspendedApplied) {
1098                     AudioSystem.setParameters("A2dpSuspended=true");
1099                 } else {
1100                     AudioSystem.setParameters("A2dpSuspended=false");
1101                 }
1102             }
1103             if ((mBluetoothLeSuspendedExt || mBluetoothLeSuspendedInt)
1104                     != mBluetoothLeSuspendedApplied) {
1105                 if (AudioService.DEBUG_COMM_RTE) {
1106                     Log.v(TAG, "updateAudioHalBluetoothState() mBluetoothLeSuspendedExt: "
1107                             + mBluetoothLeSuspendedExt
1108                             + ", mBluetoothLeSuspendedInt: " + mBluetoothLeSuspendedInt
1109                             + ", mBluetoothLeSuspendedApplied: " + mBluetoothLeSuspendedApplied);
1110                 }
1111                 mBluetoothLeSuspendedApplied =
1112                         mBluetoothLeSuspendedExt || mBluetoothLeSuspendedInt;
1113                 if (mBluetoothLeSuspendedApplied) {
1114                     AudioSystem.setParameters("LeAudioSuspended=true");
1115                 } else {
1116                     AudioSystem.setParameters("LeAudioSuspended=false");
1117                 }
1118             }
1119         }
1120     }
1121 
1122     @GuardedBy("mBluetoothAudioStateLock")
reapplyAudioHalBluetoothState()1123     private void reapplyAudioHalBluetoothState() {
1124         if (AudioService.DEBUG_COMM_RTE) {
1125             Log.v(TAG, "reapplyAudioHalBluetoothState() mBluetoothScoOnApplied: "
1126                     + mBluetoothScoOnApplied + ", mBluetoothA2dpSuspendedApplied: "
1127                     + mBluetoothA2dpSuspendedApplied + ", mBluetoothLeSuspendedApplied: "
1128                     + mBluetoothLeSuspendedApplied);
1129         }
1130         // Note: the order of parameters is important.
1131         if (mBluetoothScoOnApplied) {
1132             AudioSystem.setParameters("A2dpSuspended=true");
1133             AudioSystem.setParameters("LeAudioSuspended=true");
1134             AudioSystem.setParameters("BT_SCO=on");
1135         } else {
1136             AudioSystem.setParameters("BT_SCO=off");
1137             if (mBluetoothA2dpSuspendedApplied) {
1138                 AudioSystem.setParameters("A2dpSuspended=true");
1139             } else {
1140                 AudioSystem.setParameters("A2dpSuspended=false");
1141             }
1142             if (mBluetoothLeSuspendedApplied) {
1143                 AudioSystem.setParameters("LeAudioSuspended=true");
1144             } else {
1145                 AudioSystem.setParameters("LeAudioSuspended=false");
1146             }
1147         }
1148     }
1149 
setBluetoothScoOn(boolean on, String eventSource)1150     /*package*/ void setBluetoothScoOn(boolean on, String eventSource) {
1151         if (AudioService.DEBUG_COMM_RTE) {
1152             Log.v(TAG, "setBluetoothScoOn: " + on + " " + eventSource);
1153         }
1154         synchronized (mBluetoothAudioStateLock) {
1155             mBluetoothScoOn = on;
1156             updateAudioHalBluetoothState();
1157             postUpdateCommunicationRouteClient(isBluetoothScoRequested(), eventSource);
1158         }
1159     }
1160 
setA2dpSuspended(boolean enable, boolean internal, String eventSource)1161     /*package*/ void setA2dpSuspended(boolean enable, boolean internal, String eventSource) {
1162         synchronized (mBluetoothAudioStateLock) {
1163             if (AudioService.DEBUG_COMM_RTE) {
1164                 Log.v(TAG, "setA2dpSuspended source: " + eventSource + ", enable: "
1165                         + enable + ", internal: " + internal
1166                         + ", mBluetoothA2dpSuspendedInt: " + mBluetoothA2dpSuspendedInt
1167                         + ", mBluetoothA2dpSuspendedExt: " + mBluetoothA2dpSuspendedExt);
1168             }
1169             if (internal) {
1170                 mBluetoothA2dpSuspendedInt = enable;
1171             } else {
1172                 mBluetoothA2dpSuspendedExt = enable;
1173             }
1174             updateAudioHalBluetoothState();
1175         }
1176     }
1177 
clearA2dpSuspended(boolean internalOnly)1178     /*package*/ void clearA2dpSuspended(boolean internalOnly) {
1179         if (AudioService.DEBUG_COMM_RTE) {
1180             Log.v(TAG, "clearA2dpSuspended, internalOnly: " + internalOnly);
1181         }
1182         synchronized (mBluetoothAudioStateLock) {
1183             mBluetoothA2dpSuspendedInt = false;
1184             if (!internalOnly) {
1185                 mBluetoothA2dpSuspendedExt = false;
1186             }
1187             updateAudioHalBluetoothState();
1188         }
1189     }
1190 
setLeAudioSuspended(boolean enable, boolean internal, String eventSource)1191     /*package*/ void setLeAudioSuspended(boolean enable, boolean internal, String eventSource) {
1192         synchronized (mBluetoothAudioStateLock) {
1193             if (AudioService.DEBUG_COMM_RTE) {
1194                 Log.v(TAG, "setLeAudioSuspended source: " + eventSource + ", enable: "
1195                         + enable + ", internal: " + internal
1196                         + ", mBluetoothLeSuspendedInt: " + mBluetoothA2dpSuspendedInt
1197                         + ", mBluetoothLeSuspendedExt: " + mBluetoothA2dpSuspendedExt);
1198             }
1199             if (internal) {
1200                 mBluetoothLeSuspendedInt = enable;
1201             } else {
1202                 mBluetoothLeSuspendedExt = enable;
1203             }
1204             updateAudioHalBluetoothState();
1205         }
1206     }
1207 
clearLeAudioSuspended(boolean internalOnly)1208     /*package*/ void clearLeAudioSuspended(boolean internalOnly) {
1209         if (AudioService.DEBUG_COMM_RTE) {
1210             Log.v(TAG, "clearLeAudioSuspended, internalOnly: " + internalOnly);
1211         }
1212         synchronized (mBluetoothAudioStateLock) {
1213             mBluetoothLeSuspendedInt = false;
1214             if (!internalOnly) {
1215                 mBluetoothLeSuspendedExt = false;
1216             }
1217             updateAudioHalBluetoothState();
1218         }
1219     }
1220 
startWatchingRoutes(IAudioRoutesObserver observer)1221     /*package*/ AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) {
1222         synchronized (mDeviceStateLock) {
1223             return mDeviceInventory.startWatchingRoutes(observer);
1224         }
1225     }
1226 
getCurAudioRoutes()1227     /*package*/ AudioRoutesInfo getCurAudioRoutes() {
1228         synchronized (mDeviceStateLock) {
1229             return mDeviceInventory.getCurAudioRoutes();
1230         }
1231     }
1232 
isBluetoothA2dpOn()1233     /*package*/ boolean isBluetoothA2dpOn() {
1234         return mBluetoothA2dpEnabled.get();
1235     }
1236 
postSetAvrcpAbsoluteVolumeIndex(int index)1237     /*package*/ void postSetAvrcpAbsoluteVolumeIndex(int index) {
1238         sendIMsgNoDelay(MSG_I_SET_AVRCP_ABSOLUTE_VOLUME, SENDMSG_REPLACE, index);
1239     }
1240 
postSetHearingAidVolumeIndex(int index, int streamType)1241     /*package*/ void postSetHearingAidVolumeIndex(int index, int streamType) {
1242         sendIIMsgNoDelay(MSG_II_SET_HEARING_AID_VOLUME, SENDMSG_REPLACE, index, streamType);
1243     }
1244 
postSetLeAudioVolumeIndex(int index, int maxIndex, int streamType)1245      /*package*/ void postSetLeAudioVolumeIndex(int index, int maxIndex, int streamType) {
1246         BleVolumeInfo info = new BleVolumeInfo(index, maxIndex, streamType);
1247         sendLMsgNoDelay(MSG_II_SET_LE_AUDIO_OUT_VOLUME, SENDMSG_REPLACE, info);
1248     }
1249 
postSetModeOwner(int mode, int pid, int uid)1250     /*package*/ void postSetModeOwner(int mode, int pid, int uid) {
1251         sendLMsgNoDelay(MSG_I_SET_MODE_OWNER, SENDMSG_REPLACE,
1252                 new AudioModeInfo(mode, pid, uid));
1253     }
1254 
postBluetoothDeviceConfigChange(@onNull BtDeviceInfo info)1255     /*package*/ void postBluetoothDeviceConfigChange(@NonNull BtDeviceInfo info) {
1256         sendLMsgNoDelay(MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE, SENDMSG_QUEUE, info);
1257     }
1258 
startBluetoothScoForClient(IBinder cb, int uid, int scoAudioMode, boolean isPrivileged, @NonNull String eventSource)1259     /*package*/ void startBluetoothScoForClient(IBinder cb, int uid, int scoAudioMode,
1260                                                 boolean isPrivileged, @NonNull String eventSource) {
1261 
1262         if (AudioService.DEBUG_COMM_RTE) {
1263             Log.v(TAG, "startBluetoothScoForClient, uid: " + uid);
1264         }
1265         postSetCommunicationDeviceForClient(new CommunicationDeviceInfo(
1266                 cb, uid, new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO, ""),
1267                 true, scoAudioMode, eventSource, isPrivileged));
1268     }
1269 
stopBluetoothScoForClient( IBinder cb, int uid, boolean isPrivileged, @NonNull String eventSource)1270     /*package*/ void stopBluetoothScoForClient(
1271                         IBinder cb, int uid, boolean isPrivileged, @NonNull String eventSource) {
1272 
1273         if (AudioService.DEBUG_COMM_RTE) {
1274             Log.v(TAG, "stopBluetoothScoForClient, uid: " + uid);
1275         }
1276         postSetCommunicationDeviceForClient(new CommunicationDeviceInfo(
1277                 cb, uid, new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO, ""),
1278                 false, BtHelper.SCO_MODE_UNDEFINED, eventSource, isPrivileged));
1279     }
1280 
setPreferredDevicesForStrategySync(int strategy, @NonNull List<AudioDeviceAttributes> devices)1281     /*package*/ int setPreferredDevicesForStrategySync(int strategy,
1282             @NonNull List<AudioDeviceAttributes> devices) {
1283         return mDeviceInventory.setPreferredDevicesForStrategyAndSave(strategy, devices);
1284     }
1285 
removePreferredDevicesForStrategySync(int strategy)1286     /*package*/ int removePreferredDevicesForStrategySync(int strategy) {
1287         return mDeviceInventory.removePreferredDevicesForStrategyAndSave(strategy);
1288     }
1289 
setDeviceAsNonDefaultForStrategySync(int strategy, @NonNull AudioDeviceAttributes device)1290     /*package*/ int setDeviceAsNonDefaultForStrategySync(int strategy,
1291             @NonNull AudioDeviceAttributes device) {
1292         return mDeviceInventory.setDeviceAsNonDefaultForStrategyAndSave(strategy, device);
1293     }
1294 
removeDeviceAsNonDefaultForStrategySync(int strategy, @NonNull AudioDeviceAttributes device)1295     /*package*/ int removeDeviceAsNonDefaultForStrategySync(int strategy,
1296             @NonNull AudioDeviceAttributes device) {
1297         return mDeviceInventory.removeDeviceAsNonDefaultForStrategyAndSave(strategy, device);
1298     }
1299 
registerStrategyPreferredDevicesDispatcher( @onNull IStrategyPreferredDevicesDispatcher dispatcher, boolean isPrivileged)1300     /*package*/ void registerStrategyPreferredDevicesDispatcher(
1301             @NonNull IStrategyPreferredDevicesDispatcher dispatcher, boolean isPrivileged) {
1302         mDeviceInventory.registerStrategyPreferredDevicesDispatcher(dispatcher, isPrivileged);
1303     }
1304 
unregisterStrategyPreferredDevicesDispatcher( @onNull IStrategyPreferredDevicesDispatcher dispatcher)1305     /*package*/ void unregisterStrategyPreferredDevicesDispatcher(
1306             @NonNull IStrategyPreferredDevicesDispatcher dispatcher) {
1307         mDeviceInventory.unregisterStrategyPreferredDevicesDispatcher(dispatcher);
1308     }
1309 
registerStrategyNonDefaultDevicesDispatcher( @onNull IStrategyNonDefaultDevicesDispatcher dispatcher, boolean isPrivileged)1310     /*package*/ void registerStrategyNonDefaultDevicesDispatcher(
1311             @NonNull IStrategyNonDefaultDevicesDispatcher dispatcher, boolean isPrivileged) {
1312         mDeviceInventory.registerStrategyNonDefaultDevicesDispatcher(dispatcher, isPrivileged);
1313     }
1314 
unregisterStrategyNonDefaultDevicesDispatcher( @onNull IStrategyNonDefaultDevicesDispatcher dispatcher)1315     /*package*/ void unregisterStrategyNonDefaultDevicesDispatcher(
1316             @NonNull IStrategyNonDefaultDevicesDispatcher dispatcher) {
1317         mDeviceInventory.unregisterStrategyNonDefaultDevicesDispatcher(dispatcher);
1318     }
1319 
setPreferredDevicesForCapturePresetSync(int capturePreset, @NonNull List<AudioDeviceAttributes> devices)1320     /*package*/ int setPreferredDevicesForCapturePresetSync(int capturePreset,
1321             @NonNull List<AudioDeviceAttributes> devices) {
1322         return mDeviceInventory.setPreferredDevicesForCapturePresetAndSave(capturePreset, devices);
1323     }
1324 
clearPreferredDevicesForCapturePresetSync(int capturePreset)1325     /*package*/ int clearPreferredDevicesForCapturePresetSync(int capturePreset) {
1326         return mDeviceInventory.clearPreferredDevicesForCapturePresetAndSave(capturePreset);
1327     }
1328 
registerCapturePresetDevicesRoleDispatcher( @onNull ICapturePresetDevicesRoleDispatcher dispatcher, boolean isPrivileged)1329     /*package*/ void registerCapturePresetDevicesRoleDispatcher(
1330             @NonNull ICapturePresetDevicesRoleDispatcher dispatcher, boolean isPrivileged) {
1331         mDeviceInventory.registerCapturePresetDevicesRoleDispatcher(dispatcher, isPrivileged);
1332     }
1333 
unregisterCapturePresetDevicesRoleDispatcher( @onNull ICapturePresetDevicesRoleDispatcher dispatcher)1334     /*package*/ void unregisterCapturePresetDevicesRoleDispatcher(
1335             @NonNull ICapturePresetDevicesRoleDispatcher dispatcher) {
1336         mDeviceInventory.unregisterCapturePresetDevicesRoleDispatcher(dispatcher);
1337     }
1338 
anonymizeAudioDeviceAttributesListUnchecked( List<AudioDeviceAttributes> devices)1339     /* package */ List<AudioDeviceAttributes> anonymizeAudioDeviceAttributesListUnchecked(
1340             List<AudioDeviceAttributes> devices) {
1341         return mAudioService.anonymizeAudioDeviceAttributesListUnchecked(devices);
1342     }
1343 
registerCommunicationDeviceDispatcher( @onNull ICommunicationDeviceDispatcher dispatcher)1344     /*package*/ void registerCommunicationDeviceDispatcher(
1345             @NonNull ICommunicationDeviceDispatcher dispatcher) {
1346         mCommDevDispatchers.register(dispatcher);
1347     }
1348 
unregisterCommunicationDeviceDispatcher( @onNull ICommunicationDeviceDispatcher dispatcher)1349     /*package*/ void unregisterCommunicationDeviceDispatcher(
1350             @NonNull ICommunicationDeviceDispatcher dispatcher) {
1351         mCommDevDispatchers.unregister(dispatcher);
1352     }
1353 
1354     // Monitoring of communication device
1355     final RemoteCallbackList<ICommunicationDeviceDispatcher> mCommDevDispatchers =
1356             new RemoteCallbackList<ICommunicationDeviceDispatcher>();
1357 
1358     // portId of the device currently selected for communication: avoids broadcasting changes
1359     // when same communication route is applied
1360     @GuardedBy("mDeviceStateLock")
1361     int mCurCommunicationPortId = -1;
1362 
1363     @GuardedBy("mDeviceStateLock")
dispatchCommunicationDevice()1364     private void dispatchCommunicationDevice() {
1365         AudioDeviceInfo device = getCommunicationDeviceInt();
1366         int portId = device != null ? device.getId() : 0;
1367         if (portId == mCurCommunicationPortId) {
1368             return;
1369         }
1370         mCurCommunicationPortId = portId;
1371 
1372         final int nbDispatchers = mCommDevDispatchers.beginBroadcast();
1373         for (int i = 0; i < nbDispatchers; i++) {
1374             try {
1375                 mCommDevDispatchers.getBroadcastItem(i)
1376                         .dispatchCommunicationDeviceChanged(portId);
1377             } catch (RemoteException e) {
1378                 Log.e(TAG, "dispatchCommunicationDevice error", e);
1379             }
1380         }
1381         mCommDevDispatchers.finishBroadcast();
1382     }
1383 
1384 
1385     //---------------------------------------------------------------------
1386     // Communication with (to) AudioService
1387     //TODO check whether the AudioService methods are candidates to move here
postAccessoryPlugMediaUnmute(int device)1388     /*package*/ void postAccessoryPlugMediaUnmute(int device) {
1389         mAudioService.postAccessoryPlugMediaUnmute(device);
1390     }
1391 
getVssVolumeForDevice(int streamType, int device)1392     /*package*/ int getVssVolumeForDevice(int streamType, int device) {
1393         return mAudioService.getVssVolumeForDevice(streamType, device);
1394     }
1395 
getMaxVssVolumeForStream(int streamType)1396     /*package*/ int getMaxVssVolumeForStream(int streamType) {
1397         return mAudioService.getMaxVssVolumeForStream(streamType);
1398     }
1399 
getDeviceForStream(int streamType)1400     /*package*/ int getDeviceForStream(int streamType) {
1401         return mAudioService.getDeviceForStream(streamType);
1402     }
1403 
postApplyVolumeOnDevice(int streamType, int device, String caller)1404     /*package*/ void postApplyVolumeOnDevice(int streamType, int device, String caller) {
1405         mAudioService.postApplyVolumeOnDevice(streamType, device, caller);
1406     }
1407 
postSetVolumeIndexOnDevice(int streamType, int vssVolIndex, int device, String caller)1408     /*package*/ void postSetVolumeIndexOnDevice(int streamType, int vssVolIndex, int device,
1409                                                 String caller) {
1410         mAudioService.postSetVolumeIndexOnDevice(streamType, vssVolIndex, device, caller);
1411     }
1412 
postObserveDevicesForAllStreams()1413     /*packages*/ void postObserveDevicesForAllStreams() {
1414         mAudioService.postObserveDevicesForAllStreams();
1415     }
1416 
isInCommunication()1417     /*package*/ boolean isInCommunication() {
1418         return mAudioService.isInCommunication();
1419     }
1420 
hasMediaDynamicPolicy()1421     /*package*/ boolean hasMediaDynamicPolicy() {
1422         return mAudioService.hasMediaDynamicPolicy();
1423     }
1424 
getContentResolver()1425     /*package*/ ContentResolver getContentResolver() {
1426         return mAudioService.getContentResolver();
1427     }
1428 
checkMusicActive(int deviceType, String caller)1429     /*package*/ void checkMusicActive(int deviceType, String caller) {
1430         mAudioService.checkMusicActive(deviceType, caller);
1431     }
1432 
checkVolumeCecOnHdmiConnection( @udioService.ConnectionState int state, String caller)1433     /*package*/ void checkVolumeCecOnHdmiConnection(
1434             @AudioService.ConnectionState  int state, String caller) {
1435         mAudioService.postCheckVolumeCecOnHdmiConnection(state, caller);
1436     }
1437 
hasAudioFocusUsers()1438     /*package*/ boolean hasAudioFocusUsers() {
1439         return mAudioService.hasAudioFocusUsers();
1440     }
1441 
postInitSpatializerHeadTrackingSensors()1442     /*package*/ void postInitSpatializerHeadTrackingSensors() {
1443         mAudioService.postInitSpatializerHeadTrackingSensors();
1444     }
1445 
1446     //---------------------------------------------------------------------
1447     // Message handling on behalf of helper classes.
1448     // Each of these methods posts a message to mBrokerHandler message queue.
postBroadcastScoConnectionState(int state)1449     /*package*/ void postBroadcastScoConnectionState(int state) {
1450         sendIMsgNoDelay(MSG_I_BROADCAST_BT_CONNECTION_STATE, SENDMSG_QUEUE, state);
1451     }
1452 
postBroadcastBecomingNoisy()1453     /*package*/ void postBroadcastBecomingNoisy() {
1454         sendMsgNoDelay(MSG_BROADCAST_AUDIO_BECOMING_NOISY, SENDMSG_REPLACE);
1455     }
1456 
postBluetoothActiveDevice(BtDeviceInfo info, int delay)1457     /*package*/ void postBluetoothActiveDevice(BtDeviceInfo info, int delay) {
1458         sendLMsg(MSG_L_SET_BT_ACTIVE_DEVICE, SENDMSG_QUEUE, info, delay);
1459     }
1460 
postSetWiredDeviceConnectionState( AudioDeviceInventory.WiredDeviceConnectionState connectionState, int delay)1461     /*package*/ void postSetWiredDeviceConnectionState(
1462             AudioDeviceInventory.WiredDeviceConnectionState connectionState, int delay) {
1463         sendLMsg(MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE, SENDMSG_QUEUE, connectionState, delay);
1464     }
1465 
postBtProfileDisconnected(int profile)1466     /*package*/ void postBtProfileDisconnected(int profile) {
1467         sendIMsgNoDelay(MSG_I_BT_SERVICE_DISCONNECTED_PROFILE, SENDMSG_QUEUE, profile);
1468     }
1469 
postBtProfileConnected(int profile, BluetoothProfile proxy)1470     /*package*/ void postBtProfileConnected(int profile, BluetoothProfile proxy) {
1471         sendILMsgNoDelay(MSG_IL_BT_SERVICE_CONNECTED_PROFILE, SENDMSG_QUEUE, profile, proxy);
1472     }
1473 
postCommunicationRouteClientDied(CommunicationRouteClient client)1474     /*package*/ void postCommunicationRouteClientDied(CommunicationRouteClient client) {
1475         sendLMsgNoDelay(MSG_L_COMMUNICATION_ROUTE_CLIENT_DIED, SENDMSG_QUEUE, client);
1476     }
1477 
postSaveSetPreferredDevicesForStrategy(int strategy, List<AudioDeviceAttributes> devices)1478     /*package*/ void postSaveSetPreferredDevicesForStrategy(int strategy,
1479                                                             List<AudioDeviceAttributes> devices)
1480     {
1481         sendILMsgNoDelay(MSG_IL_SAVE_PREF_DEVICES_FOR_STRATEGY, SENDMSG_QUEUE, strategy, devices);
1482     }
1483 
postSaveRemovePreferredDevicesForStrategy(int strategy)1484     /*package*/ void postSaveRemovePreferredDevicesForStrategy(int strategy) {
1485         sendIMsgNoDelay(MSG_I_SAVE_REMOVE_PREF_DEVICES_FOR_STRATEGY, SENDMSG_QUEUE, strategy);
1486     }
1487 
postSaveSetDeviceAsNonDefaultForStrategy( int strategy, AudioDeviceAttributes device)1488     /*package*/ void postSaveSetDeviceAsNonDefaultForStrategy(
1489             int strategy, AudioDeviceAttributes device) {
1490         sendILMsgNoDelay(MSG_IL_SAVE_NDEF_DEVICE_FOR_STRATEGY, SENDMSG_QUEUE, strategy, device);
1491     }
1492 
postSaveRemoveDeviceAsNonDefaultForStrategy( int strategy, AudioDeviceAttributes device)1493     /*package*/ void postSaveRemoveDeviceAsNonDefaultForStrategy(
1494             int strategy, AudioDeviceAttributes device) {
1495         sendILMsgNoDelay(
1496                 MSG_IL_SAVE_REMOVE_NDEF_DEVICE_FOR_STRATEGY, SENDMSG_QUEUE, strategy, device);
1497     }
1498 
postSaveSetPreferredDevicesForCapturePreset( int capturePreset, List<AudioDeviceAttributes> devices)1499     /*package*/ void postSaveSetPreferredDevicesForCapturePreset(
1500             int capturePreset, List<AudioDeviceAttributes> devices) {
1501         sendILMsgNoDelay(
1502                 MSG_IL_SAVE_PREF_DEVICES_FOR_CAPTURE_PRESET, SENDMSG_QUEUE, capturePreset, devices);
1503     }
1504 
postSaveClearPreferredDevicesForCapturePreset(int capturePreset)1505     /*package*/ void postSaveClearPreferredDevicesForCapturePreset(int capturePreset) {
1506         sendIMsgNoDelay(
1507                 MSG_I_SAVE_CLEAR_PREF_DEVICES_FOR_CAPTURE_PRESET, SENDMSG_QUEUE, capturePreset);
1508     }
1509 
postUpdateCommunicationRouteClient( boolean wasBtScoRequested, String eventSource)1510     /*package*/ void postUpdateCommunicationRouteClient(
1511             boolean wasBtScoRequested, String eventSource) {
1512         sendILMsgNoDelay(MSG_IL_UPDATE_COMMUNICATION_ROUTE_CLIENT, SENDMSG_QUEUE,
1513                 wasBtScoRequested ? 1 : 0, eventSource);
1514     }
1515 
postSetCommunicationDeviceForClient(CommunicationDeviceInfo info)1516     /*package*/ void postSetCommunicationDeviceForClient(CommunicationDeviceInfo info) {
1517         sendLMsgNoDelay(MSG_L_SET_COMMUNICATION_DEVICE_FOR_CLIENT, SENDMSG_QUEUE, info);
1518     }
1519 
postNotifyPreferredAudioProfileApplied(BluetoothDevice btDevice)1520     /*package*/ void postNotifyPreferredAudioProfileApplied(BluetoothDevice btDevice) {
1521         sendLMsgNoDelay(MSG_L_NOTIFY_PREFERRED_AUDIOPROFILE_APPLIED, SENDMSG_QUEUE, btDevice);
1522     }
1523 
postReceiveBtEvent(Intent intent)1524     /*package*/ void postReceiveBtEvent(Intent intent) {
1525         sendLMsgNoDelay(MSG_L_RECEIVED_BT_EVENT, SENDMSG_QUEUE, intent);
1526     }
1527 
postUpdateLeAudioGroupAddresses(int groupId)1528     /*package*/ void postUpdateLeAudioGroupAddresses(int groupId) {
1529         sendIMsgNoDelay(
1530                 MSG_I_UPDATE_LE_AUDIO_GROUP_ADDRESSES, SENDMSG_QUEUE, groupId);
1531     }
1532 
postSynchronizeAdiDevicesInInventory(AdiDeviceState deviceState)1533     /*package*/ void postSynchronizeAdiDevicesInInventory(AdiDeviceState deviceState) {
1534         sendLMsgNoDelay(MSG_L_SYNCHRONIZE_ADI_DEVICES_IN_INVENTORY, SENDMSG_QUEUE, deviceState);
1535     }
1536 
postUpdatedAdiDeviceState(AdiDeviceState deviceState, boolean initSA)1537     /*package*/ void postUpdatedAdiDeviceState(AdiDeviceState deviceState, boolean initSA) {
1538         sendILMsgNoDelay(
1539                 MSG_IL_UPDATED_ADI_DEVICE_STATE, SENDMSG_QUEUE, initSA ? 1 : 0, deviceState);
1540     }
1541 
1542     /*package*/ static final class CommunicationDeviceInfo {
1543         final @NonNull IBinder mCb; // Identifies the requesting client for death handler
1544         final int mUid; // Requester UID
1545         final @Nullable AudioDeviceAttributes mDevice; // Device being set or reset.
1546         final boolean mOn; // true if setting, false if resetting
1547         final int mScoAudioMode; // only used for SCO: requested audio mode
1548         final boolean mIsPrivileged; // true if the client app has MODIFY_PHONE_STATE permission
1549         final @NonNull String mEventSource; // caller identifier for logging
1550 
CommunicationDeviceInfo(@onNull IBinder cb, int uid, @Nullable AudioDeviceAttributes device, boolean on, int scoAudioMode, @NonNull String eventSource, boolean isPrivileged)1551         CommunicationDeviceInfo(@NonNull IBinder cb, int uid,
1552                 @Nullable AudioDeviceAttributes device, boolean on, int scoAudioMode,
1553                 @NonNull String eventSource, boolean isPrivileged) {
1554             mCb = cb;
1555             mUid = uid;
1556             mDevice = device;
1557             mOn = on;
1558             mScoAudioMode = scoAudioMode;
1559             mIsPrivileged = isPrivileged;
1560             mEventSource = eventSource;
1561         }
1562 
1563         // redefine equality op so we can match messages intended for this client
1564         @Override
equals(Object o)1565         public boolean equals(Object o) {
1566             if (o == null) {
1567                 return false;
1568             }
1569             if (this == o) {
1570                 return true;
1571             }
1572             if (!(o instanceof CommunicationDeviceInfo)) {
1573                 return false;
1574             }
1575 
1576             return mCb.equals(((CommunicationDeviceInfo) o).mCb)
1577                     && mUid == ((CommunicationDeviceInfo) o).mUid;
1578         }
1579 
1580         @Override
hashCode()1581         public int hashCode() {
1582             // only hashing on the fields used in equals()
1583             return Objects.hash(mCb.hashCode(), mUid);
1584         }
1585 
1586         @Override
toString()1587         public String toString() {
1588             return "CommunicationDeviceInfo mCb=" + mCb.toString()
1589                     + " mUid=" + mUid
1590                     + " mDevice=[" + (mDevice != null ? mDevice.toString() : "null") + "]"
1591                     + " mOn=" + mOn
1592                     + " mScoAudioMode=" + mScoAudioMode
1593                     + " mIsPrivileged=" + mIsPrivileged
1594                     + " mEventSource=" + mEventSource;
1595         }
1596     }
1597 
1598     //---------------------------------------------------------------------
1599     // Method forwarding between the helper classes (BtHelper, AudioDeviceInventory)
1600     // only call from a "handle"* method or "on"* method
1601 
1602     // Handles request to override default use of A2DP for media.
1603     //@GuardedBy("mConnectedDevices")
setBluetoothA2dpOnInt(boolean on, boolean fromA2dp, String source)1604     /*package*/ void setBluetoothA2dpOnInt(boolean on, boolean fromA2dp, String source) {
1605         // for logging only
1606         final String eventSource = "setBluetoothA2dpOn(" + on
1607                 + ") from u/pid:" + Binder.getCallingUid() + "/"
1608                 + Binder.getCallingPid() + " src:" + source;
1609 
1610         mBluetoothA2dpEnabled.set(on);
1611         onSetForceUse(
1612                 AudioSystem.FOR_MEDIA,
1613                 on ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP,
1614                 fromA2dp,
1615                 eventSource);
1616     }
1617 
handleDeviceConnection(@onNull AudioDeviceAttributes attributes, boolean connect, @Nullable BluetoothDevice btDevice)1618     /*package*/ boolean handleDeviceConnection(@NonNull AudioDeviceAttributes attributes,
1619                                 boolean connect, @Nullable BluetoothDevice btDevice) {
1620         synchronized (mDeviceStateLock) {
1621             return mDeviceInventory.handleDeviceConnection(
1622                     attributes, connect, false /*for test*/, btDevice);
1623         }
1624     }
1625 
handleFailureToConnectToBtHeadsetService(int delay)1626     /*package*/ void handleFailureToConnectToBtHeadsetService(int delay) {
1627         sendMsg(MSG_BT_HEADSET_CNCT_FAILED, SENDMSG_REPLACE, delay);
1628     }
1629 
handleCancelFailureToConnectToBtHeadsetService()1630     /*package*/ void handleCancelFailureToConnectToBtHeadsetService() {
1631         mBrokerHandler.removeMessages(MSG_BT_HEADSET_CNCT_FAILED);
1632     }
1633 
postReportNewRoutes(boolean fromA2dp)1634     /*package*/ void postReportNewRoutes(boolean fromA2dp) {
1635         sendMsgNoDelay(fromA2dp ? MSG_REPORT_NEW_ROUTES_A2DP : MSG_REPORT_NEW_ROUTES, SENDMSG_NOOP);
1636     }
1637 
1638     // must be called synchronized on mConnectedDevices
hasScheduledA2dpConnection(BluetoothDevice btDevice)1639     /*package*/ boolean hasScheduledA2dpConnection(BluetoothDevice btDevice) {
1640         final BtDeviceInfo devInfoToCheck = new BtDeviceInfo(btDevice, BluetoothProfile.A2DP);
1641         return mBrokerHandler.hasEqualMessages(MSG_L_SET_BT_ACTIVE_DEVICE, devInfoToCheck);
1642     }
1643 
setA2dpTimeout(String address, int a2dpCodec, int delayMs)1644     /*package*/ void setA2dpTimeout(String address, int a2dpCodec, int delayMs) {
1645         sendILMsg(MSG_IL_BTA2DP_TIMEOUT, SENDMSG_QUEUE, a2dpCodec, address, delayMs);
1646     }
1647 
setLeAudioTimeout(String address, int device, int codec, int delayMs)1648     /*package*/ void setLeAudioTimeout(String address, int device, int codec, int delayMs) {
1649         sendIILMsg(MSG_IIL_BTLEAUDIO_TIMEOUT, SENDMSG_QUEUE, device, codec, address, delayMs);
1650     }
1651 
setAvrcpAbsoluteVolumeSupported(boolean supported)1652     /*package*/ void setAvrcpAbsoluteVolumeSupported(boolean supported) {
1653         synchronized (mDeviceStateLock) {
1654             mBtHelper.setAvrcpAbsoluteVolumeSupported(supported);
1655         }
1656     }
1657 
clearAvrcpAbsoluteVolumeSupported()1658     /*package*/ void clearAvrcpAbsoluteVolumeSupported() {
1659         setAvrcpAbsoluteVolumeSupported(false);
1660         mAudioService.setAvrcpAbsoluteVolumeSupported(false);
1661     }
1662 
getBluetoothA2dpEnabled()1663     /*package*/ boolean getBluetoothA2dpEnabled() {
1664         return mBluetoothA2dpEnabled.get();
1665     }
1666 
getLeAudioDeviceGroupId(BluetoothDevice device)1667     /*package*/ int getLeAudioDeviceGroupId(BluetoothDevice device) {
1668         return mBtHelper.getLeAudioDeviceGroupId(device);
1669     }
1670 
getLeAudioGroupAddresses(int groupId)1671     /*package*/ List<Pair<String, String>> getLeAudioGroupAddresses(int groupId) {
1672         return mBtHelper.getLeAudioGroupAddresses(groupId);
1673     }
1674 
broadcastStickyIntentToCurrentProfileGroup(Intent intent)1675     /*package*/ void broadcastStickyIntentToCurrentProfileGroup(Intent intent) {
1676         mSystemServer.broadcastStickyIntentToCurrentProfileGroup(intent);
1677     }
1678 
dump(PrintWriter pw, String prefix)1679     /*package*/ void dump(PrintWriter pw, String prefix) {
1680         if (mBrokerHandler != null) {
1681             pw.println(prefix + "Message handler (watch for unhandled messages):");
1682             mBrokerHandler.dump(new PrintWriterPrinter(pw), prefix + "  ");
1683         } else {
1684             pw.println("Message handler is null");
1685         }
1686 
1687         mDeviceInventory.dump(pw, prefix);
1688 
1689         pw.println("\n" + prefix + "Communication route clients:");
1690         mCommunicationRouteClients.forEach((cl) -> {
1691             pw.println("  " + prefix + cl.toString()); });
1692 
1693         pw.println("\n" + prefix + "Computed Preferred communication device: "
1694                 +  preferredCommunicationDevice());
1695         pw.println("\n" + prefix + "Applied Preferred communication device: "
1696                 +  mPreferredCommunicationDevice);
1697         pw.println(prefix + "Active communication device: "
1698                 +  ((mActiveCommunicationDevice == null) ? "None"
1699                         : new AudioDeviceAttributes(mActiveCommunicationDevice)));
1700 
1701         pw.println(prefix + "mCommunicationStrategyId: "
1702                 +  mCommunicationStrategyId);
1703 
1704         pw.println(prefix + "mAccessibilityStrategyId: "
1705                 +  mAccessibilityStrategyId);
1706 
1707         pw.println("\n" + prefix + "mAudioModeOwner: " + mAudioModeOwner);
1708 
1709         pw.println("\n" + prefix + "mScoManagedByAudio: " + mScoManagedByAudio);
1710 
1711         mBtHelper.dump(pw, prefix);
1712     }
1713 
1714     //---------------------------------------------------------------------
1715     // Internal handling of messages
1716     // These methods are ALL synchronous, in response to message handling in BrokerHandler
1717     // Blocking in any of those will block the message queue
1718 
onSetForceUse(int useCase, int config, boolean fromA2dp, String eventSource)1719     private void onSetForceUse(int useCase, int config, boolean fromA2dp, String eventSource) {
1720         if (useCase == AudioSystem.FOR_MEDIA) {
1721             postReportNewRoutes(fromA2dp);
1722         }
1723         AudioService.sForceUseLogger.enqueue(
1724                 new AudioServiceEvents.ForceUseEvent(useCase, config, eventSource));
1725         new MediaMetrics.Item(MediaMetrics.Name.AUDIO_FORCE_USE + MediaMetrics.SEPARATOR
1726                 + AudioSystem.forceUseUsageToString(useCase))
1727                 .set(MediaMetrics.Property.EVENT, "onSetForceUse")
1728                 .set(MediaMetrics.Property.FORCE_USE_DUE_TO, eventSource)
1729                 .set(MediaMetrics.Property.FORCE_USE_MODE,
1730                         AudioSystem.forceUseConfigToString(config))
1731                 .record();
1732 
1733         if (AudioService.DEBUG_COMM_RTE) {
1734             Log.v(TAG, "onSetForceUse(useCase<" + useCase + ">, config<" + config + ">, fromA2dp<"
1735                     + fromA2dp + ">, eventSource<" + eventSource + ">)");
1736         }
1737         mAudioSystem.setForceUse(useCase, config);
1738     }
1739 
onSendBecomingNoisyIntent()1740     private void onSendBecomingNoisyIntent() {
1741         AudioService.sDeviceLogger.enqueue((new EventLogger.StringEvent(
1742                 "broadcast ACTION_AUDIO_BECOMING_NOISY")).printLog(TAG));
1743         mSystemServer.sendDeviceBecomingNoisyIntent();
1744     }
1745 
1746     //---------------------------------------------------------------------
1747     // Message handling
1748     private BrokerHandler mBrokerHandler;
1749     private BrokerThread mBrokerThread;
1750     private PowerManager.WakeLock mBrokerEventWakeLock;
1751 
setupMessaging(Context ctxt)1752     private void setupMessaging(Context ctxt) {
1753         final PowerManager pm = (PowerManager) ctxt.getSystemService(Context.POWER_SERVICE);
1754         mBrokerEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
1755                 "handleAudioDeviceEvent");
1756         mBrokerThread = new BrokerThread();
1757         mBrokerThread.start();
1758         waitForBrokerHandlerCreation();
1759     }
1760 
waitForBrokerHandlerCreation()1761     private void waitForBrokerHandlerCreation() {
1762         synchronized (this) {
1763             while (mBrokerHandler == null) {
1764                 try {
1765                     wait();
1766                 } catch (InterruptedException e) {
1767                     Log.e(TAG, "Interruption while waiting on BrokerHandler");
1768                 }
1769             }
1770         }
1771     }
1772 
1773     /** Class that handles the device broker's message queue */
1774     private class BrokerThread extends Thread {
BrokerThread()1775         BrokerThread() {
1776             super("AudioDeviceBroker");
1777         }
1778 
1779         @Override
run()1780         public void run() {
1781             // Set this thread up so the handler will work on it
1782             Looper.prepare();
1783 
1784             synchronized (AudioDeviceBroker.this) {
1785                 mBrokerHandler = new BrokerHandler();
1786 
1787                 // Notify that the handler has been created
1788                 AudioDeviceBroker.this.notify();
1789             }
1790 
1791             Looper.loop();
1792         }
1793     }
1794 
1795     /** Class that handles the message queue */
1796     private class BrokerHandler extends Handler {
1797 
1798         @Override
handleMessage(Message msg)1799         public void handleMessage(Message msg) {
1800             int muteCheckDelayMs = BTA2DP_MUTE_CHECK_DELAY_MS;
1801             switch (msg.what) {
1802                 case MSG_RESTORE_DEVICES:
1803                     synchronized (mSetModeLock) {
1804                         synchronized (mDeviceStateLock) {
1805                             initRoutingStrategyIds();
1806                             updateActiveCommunicationDevice();
1807                             mDeviceInventory.onRestoreDevices();
1808                             synchronized (mBluetoothAudioStateLock) {
1809                                 reapplyAudioHalBluetoothState();
1810                             }
1811                             mBtHelper.onAudioServerDiedRestoreA2dp();
1812                             updateCommunicationRoute("MSG_RESTORE_DEVICES");
1813                         }
1814                     }
1815                     break;
1816                 case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE:
1817                     synchronized (mDeviceStateLock) {
1818                         mDeviceInventory.onSetWiredDeviceConnectionState(
1819                                 (AudioDeviceInventory.WiredDeviceConnectionState) msg.obj);
1820                     }
1821                     break;
1822                 case MSG_I_BROADCAST_BT_CONNECTION_STATE:
1823                     synchronized (mDeviceStateLock) {
1824                         mBtHelper.onBroadcastScoConnectionState(msg.arg1);
1825                     }
1826                     break;
1827                 case MSG_IIL_SET_FORCE_USE: // intended fall-through
1828                     onSetForceUse(msg.arg1, msg.arg2, false, (String) msg.obj);
1829                     break;
1830                 case MSG_L_SET_FORCE_BT_A2DP_USE:
1831                 case MSG_L_SET_FORCE_BT_A2DP_USE_NO_MUTE:
1832                     int forcedUsage = mBluetoothA2dpEnabled.get()
1833                             ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP;
1834                     onSetForceUse(AudioSystem.FOR_MEDIA, forcedUsage, true, (String) msg.obj);
1835                     break;
1836                 case MSG_REPORT_NEW_ROUTES:
1837                 case MSG_REPORT_NEW_ROUTES_A2DP:
1838                     synchronized (mDeviceStateLock) {
1839                         mDeviceInventory.onReportNewRoutes();
1840                     }
1841                     break;
1842                 case MSG_L_SET_BT_ACTIVE_DEVICE: {
1843                     final BtDeviceInfo btInfo = (BtDeviceInfo) msg.obj;
1844                     if (btInfo.mState == BluetoothProfile.STATE_CONNECTED
1845                             && !mBtHelper.isProfilePoxyConnected(btInfo.mProfile)) {
1846                         AudioService.sDeviceLogger.enqueue((new EventLogger.StringEvent(
1847                                 "msg: MSG_L_SET_BT_ACTIVE_DEVICE "
1848                                         + "received with null profile proxy: "
1849                                         + btInfo)).printLog(TAG));
1850                     } else {
1851                         final Pair<Integer, Boolean> codecAndChanged =
1852                                 mBtHelper.getCodecWithFallback(btInfo.mDevice,
1853                                         btInfo.mProfile, btInfo.mIsLeOutput,
1854                                         "MSG_L_SET_BT_ACTIVE_DEVICE");
1855                         synchronized (mSetModeLock) {
1856                             synchronized (mDeviceStateLock) {
1857                                 mDeviceInventory.onSetBtActiveDevice(btInfo, codecAndChanged.first,
1858                                         (btInfo.mProfile != BluetoothProfile.LE_AUDIO
1859                                                 || btInfo.mIsLeOutput)
1860                                             ? mAudioService.getBluetoothContextualVolumeStream()
1861                                             : AudioSystem.STREAM_DEFAULT);
1862                                 if (btInfo.mProfile == BluetoothProfile.LE_AUDIO
1863                                         || btInfo.mProfile == BluetoothProfile.HEARING_AID
1864                                         || (mScoManagedByAudio
1865                                             && btInfo.mProfile == BluetoothProfile.HEADSET)) {
1866                                     onUpdateCommunicationRouteClient(isBluetoothScoRequested(),
1867                                             "setBluetoothActiveDevice");
1868                                 }
1869                             }
1870                         }
1871                     }
1872                 } break;
1873                 case MSG_BT_HEADSET_CNCT_FAILED:
1874                     synchronized (mSetModeLock) {
1875                         synchronized (mDeviceStateLock) {
1876                             mBtHelper.resetBluetoothSco();
1877                         }
1878                     }
1879                     break;
1880                 case MSG_IL_BTA2DP_TIMEOUT:
1881                     // msg.obj  == address of BTA2DP device
1882                     synchronized (mDeviceStateLock) {
1883                         mDeviceInventory.onMakeA2dpDeviceUnavailableNow(
1884                                 (String) msg.obj, msg.arg1);
1885                     }
1886                     break;
1887                 case MSG_IIL_BTLEAUDIO_TIMEOUT:
1888                     // msg.obj  == address of LE Audio device
1889                     synchronized (mDeviceStateLock) {
1890                         mDeviceInventory.onMakeLeAudioDeviceUnavailableNow(
1891                                 (String) msg.obj, msg.arg1, msg.arg2);
1892                     }
1893                     break;
1894                 case MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE: {
1895                     final BtDeviceInfo btInfo = (BtDeviceInfo) msg.obj;
1896                     final Pair<Integer, Boolean> codecAndChanged = mBtHelper.getCodecWithFallback(
1897                             btInfo.mDevice, btInfo.mProfile, btInfo.mIsLeOutput,
1898                             "MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE");
1899                     synchronized (mDeviceStateLock) {
1900                         muteCheckDelayMs += mDeviceInventory.onBluetoothDeviceConfigChange(btInfo,
1901                                 codecAndChanged.first, codecAndChanged.second,
1902                                 BtHelper.EVENT_DEVICE_CONFIG_CHANGE);
1903                     }
1904                 } break;
1905                 case MSG_BROADCAST_AUDIO_BECOMING_NOISY:
1906                     onSendBecomingNoisyIntent();
1907                     break;
1908                 case MSG_II_SET_HEARING_AID_VOLUME:
1909                     synchronized (mDeviceStateLock) {
1910                         mBtHelper.setHearingAidVolume(msg.arg1, msg.arg2,
1911                                 mDeviceInventory.isHearingAidConnected());
1912                     }
1913                     break;
1914                 case MSG_II_SET_LE_AUDIO_OUT_VOLUME: {
1915                     final BleVolumeInfo info = (BleVolumeInfo) msg.obj;
1916                     synchronized (mDeviceStateLock) {
1917                         mBtHelper.setLeAudioVolume(info.mIndex, info.mMaxIndex, info.mStreamType);
1918                     }
1919                 } break;
1920                 case MSG_I_SET_AVRCP_ABSOLUTE_VOLUME:
1921                     synchronized (mDeviceStateLock) {
1922                         mBtHelper.setAvrcpAbsoluteVolumeIndex(msg.arg1);
1923                     }
1924                     break;
1925                 case MSG_I_SET_MODE_OWNER:
1926                     synchronized (mSetModeLock) {
1927                         synchronized (mDeviceStateLock) {
1928                             boolean wasBtScoRequested = isBluetoothScoRequested();
1929                             mAudioModeOwner = (AudioModeInfo) msg.obj;
1930                             if (mAudioModeOwner.mMode != AudioSystem.MODE_RINGTONE) {
1931                                 onUpdateCommunicationRouteClient(
1932                                         wasBtScoRequested, "setNewModeOwner");
1933                             }
1934                         }
1935                     }
1936                     break;
1937 
1938                 case MSG_L_SET_COMMUNICATION_DEVICE_FOR_CLIENT:
1939                     CommunicationDeviceInfo deviceInfo = (CommunicationDeviceInfo) msg.obj;
1940                     synchronized (mSetModeLock) {
1941                         synchronized (mDeviceStateLock) {
1942                             onSetCommunicationDeviceForClient(deviceInfo);
1943                         }
1944                     }
1945                     synchronized (mCommunicationDeviceLock) {
1946                         if (mCommunicationDeviceUpdateCount > 0) {
1947                             mCommunicationDeviceUpdateCount--;
1948                         } else {
1949                             Log.e(TAG, "mCommunicationDeviceUpdateCount already 0 in"
1950                                     + " MSG_L_SET_COMMUNICATION_DEVICE_FOR_CLIENT");
1951                         }
1952                         mCommunicationDeviceLock.notify();
1953                     }
1954                     break;
1955 
1956                 case MSG_IL_UPDATE_COMMUNICATION_ROUTE_CLIENT:
1957                     synchronized (mSetModeLock) {
1958                         synchronized (mDeviceStateLock) {
1959                             onUpdateCommunicationRouteClient(msg.arg1 == 1, (String) msg.obj);
1960                         }
1961                     }
1962                     break;
1963 
1964                 case MSG_L_COMMUNICATION_ROUTE_CLIENT_DIED:
1965                     synchronized (mSetModeLock) {
1966                         synchronized (mDeviceStateLock) {
1967                             onCommunicationRouteClientDied((CommunicationRouteClient) msg.obj);
1968                         }
1969                     }
1970                     break;
1971 
1972                 case MSG_L_RECEIVED_BT_EVENT:
1973                     synchronized (mSetModeLock) {
1974                         synchronized (mDeviceStateLock) {
1975                             onReceiveBtEvent((Intent) msg.obj);
1976                         }
1977                     }
1978                     break;
1979 
1980                 case MSG_TOGGLE_HDMI:
1981                     synchronized (mDeviceStateLock) {
1982                         mDeviceInventory.onToggleHdmi();
1983                     }
1984                     break;
1985                 case MSG_I_BT_SERVICE_DISCONNECTED_PROFILE:
1986                     synchronized (mSetModeLock) {
1987                         synchronized (mDeviceStateLock) {
1988                             mBtHelper.onBtProfileDisconnected(msg.arg1);
1989                             mDeviceInventory.onBtProfileDisconnected(msg.arg1);
1990                         }
1991                     }
1992                     break;
1993                 case MSG_IL_BT_SERVICE_CONNECTED_PROFILE:
1994                     synchronized (mSetModeLock) {
1995                         synchronized (mDeviceStateLock) {
1996                             mBtHelper.onBtProfileConnected(msg.arg1, (BluetoothProfile) msg.obj);
1997                         }
1998                     }
1999                     break;
2000                 case MSG_L_BT_ACTIVE_DEVICE_CHANGE_EXT: {
2001                     final BtDeviceInfo btInfo = (BtDeviceInfo) msg.obj;
2002                     if (btInfo.mDevice == null) break;
2003                     AudioService.sDeviceLogger.enqueue((new EventLogger.StringEvent(
2004                             "msg: MSG_L_BT_ACTIVE_DEVICE_CHANGE_EXT " + btInfo)).printLog(TAG));
2005                     synchronized (mDeviceStateLock) {
2006                         mDeviceInventory.setBluetoothActiveDevice(btInfo);
2007                     }
2008                 } break;
2009                 case MSG_IL_SAVE_PREF_DEVICES_FOR_STRATEGY: {
2010                     final int strategy = msg.arg1;
2011                     final List<AudioDeviceAttributes> devices =
2012                             (List<AudioDeviceAttributes>) msg.obj;
2013                     mDeviceInventory.onSaveSetPreferredDevices(strategy, devices);
2014                 } break;
2015                 case MSG_I_SAVE_REMOVE_PREF_DEVICES_FOR_STRATEGY: {
2016                     final int strategy = msg.arg1;
2017                     mDeviceInventory.onSaveRemovePreferredDevices(strategy);
2018                 } break;
2019                 case MSG_IL_SAVE_NDEF_DEVICE_FOR_STRATEGY: {
2020                     final int strategy = msg.arg1;
2021                     final AudioDeviceAttributes device = (AudioDeviceAttributes) msg.obj;
2022                     mDeviceInventory.onSaveSetDeviceAsNonDefault(strategy, device);
2023                 } break;
2024                 case MSG_IL_SAVE_REMOVE_NDEF_DEVICE_FOR_STRATEGY: {
2025                     final int strategy = msg.arg1;
2026                     final AudioDeviceAttributes device = (AudioDeviceAttributes) msg.obj;
2027                     mDeviceInventory.onSaveRemoveDeviceAsNonDefault(strategy, device);
2028                 } break;
2029                 case MSG_CHECK_MUTE_MUSIC:
2030                     checkMessagesMuteMusic(0);
2031                     break;
2032                 case MSG_IL_SAVE_PREF_DEVICES_FOR_CAPTURE_PRESET: {
2033                     final int capturePreset = msg.arg1;
2034                     final List<AudioDeviceAttributes> devices =
2035                             (List<AudioDeviceAttributes>) msg.obj;
2036                     mDeviceInventory.onSaveSetPreferredDevicesForCapturePreset(
2037                             capturePreset, devices);
2038                 } break;
2039                 case MSG_I_SAVE_CLEAR_PREF_DEVICES_FOR_CAPTURE_PRESET: {
2040                     final int capturePreset = msg.arg1;
2041                     mDeviceInventory.onSaveClearPreferredDevicesForCapturePreset(capturePreset);
2042                 } break;
2043                 case MSG_L_NOTIFY_PREFERRED_AUDIOPROFILE_APPLIED: {
2044                     final BluetoothDevice btDevice = (BluetoothDevice) msg.obj;
2045                     BtHelper.onNotifyPreferredAudioProfileApplied(btDevice);
2046                 } break;
2047                 case MSG_L_CHECK_COMMUNICATION_DEVICE_REMOVAL: {
2048                     synchronized (mSetModeLock) {
2049                         synchronized (mDeviceStateLock) {
2050                             onCheckCommunicationDeviceRemoval((AudioDeviceAttributes) msg.obj);
2051                         }
2052                     }
2053                 } break;
2054                 case MSG_PERSIST_AUDIO_DEVICE_SETTINGS:
2055                     onPersistAudioDeviceSettings();
2056                     break;
2057 
2058                 case MSG_CHECK_COMMUNICATION_ROUTE_CLIENT_STATE: {
2059                     synchronized (mDeviceStateLock) {
2060                         onCheckCommunicationRouteClientState(msg.arg1, msg.arg2 == 1);
2061                     }
2062                 } break;
2063 
2064                 case MSG_I_UPDATE_LE_AUDIO_GROUP_ADDRESSES:
2065                     synchronized (mSetModeLock) {
2066                         synchronized (mDeviceStateLock) {
2067                             mDeviceInventory.onUpdateLeAudioGroupAddresses(msg.arg1);
2068                         }
2069                     } break;
2070 
2071                 case MSG_L_SYNCHRONIZE_ADI_DEVICES_IN_INVENTORY:
2072                     synchronized (mSetModeLock) {
2073                         synchronized (mDeviceStateLock) {
2074                             mDeviceInventory.onSynchronizeAdiDevicesInInventory(
2075                                     (AdiDeviceState) msg.obj);
2076                         }
2077                     } break;
2078 
2079                 case MSG_IL_UPDATED_ADI_DEVICE_STATE:
2080                     mAudioService.onUpdatedAdiDeviceState((AdiDeviceState) msg.obj, msg.arg1 == 1);
2081                     break;
2082 
2083                 default:
2084                     Log.wtf(TAG, "Invalid message " + msg.what);
2085             }
2086 
2087             // Give some time to Bluetooth service to post a connection message
2088             // in case of active device switch
2089             if (MESSAGES_MUTE_MUSIC.contains(msg.what)) {
2090                 sendMsg(MSG_CHECK_MUTE_MUSIC, SENDMSG_REPLACE, muteCheckDelayMs);
2091             }
2092 
2093             if (isMessageHandledUnderWakelock(msg.what)) {
2094                 try {
2095                     mBrokerEventWakeLock.release();
2096                 } catch (Exception e) {
2097                     Log.e(TAG, "Exception releasing wakelock", e);
2098                 }
2099             }
2100         }
2101     }
2102 
2103     // List of all messages. If a message has be handled under wakelock, add it to
2104     //    the isMessageHandledUnderWakelock(int) method
2105     // Naming of msg indicates arguments, using JNI argument grammar
2106     // (e.g. II indicates two int args, IL indicates int and Obj arg)
2107     private static final int MSG_RESTORE_DEVICES = 1;
2108     private static final int MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE = 2;
2109     private static final int MSG_I_BROADCAST_BT_CONNECTION_STATE = 3;
2110     private static final int MSG_IIL_SET_FORCE_USE = 4;
2111     private static final int MSG_L_SET_FORCE_BT_A2DP_USE = 5;
2112     private static final int MSG_TOGGLE_HDMI = 6;
2113     private static final int MSG_L_SET_BT_ACTIVE_DEVICE = 7;
2114     private static final int MSG_BT_HEADSET_CNCT_FAILED = 9;
2115     private static final int MSG_IL_BTA2DP_TIMEOUT = 10;
2116 
2117     // process change of A2DP device configuration, obj is BluetoothDevice
2118     private static final int MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE = 11;
2119 
2120     private static final int MSG_BROADCAST_AUDIO_BECOMING_NOISY = 12;
2121     private static final int MSG_REPORT_NEW_ROUTES = 13;
2122     private static final int MSG_II_SET_HEARING_AID_VOLUME = 14;
2123     private static final int MSG_I_SET_AVRCP_ABSOLUTE_VOLUME = 15;
2124     private static final int MSG_I_SET_MODE_OWNER = 16;
2125 
2126     private static final int MSG_I_BT_SERVICE_DISCONNECTED_PROFILE = 22;
2127     private static final int MSG_IL_BT_SERVICE_CONNECTED_PROFILE = 23;
2128 
2129     // process external command to (dis)connect an A2DP device, obj is BtDeviceConnectionInfo
2130     private static final int MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT = 29;
2131 
2132     // process external command to (dis)connect a hearing aid device
2133     private static final int MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT = 31;
2134 
2135     private static final int MSG_IL_SAVE_PREF_DEVICES_FOR_STRATEGY = 32;
2136     private static final int MSG_I_SAVE_REMOVE_PREF_DEVICES_FOR_STRATEGY = 33;
2137 
2138     private static final int MSG_L_COMMUNICATION_ROUTE_CLIENT_DIED = 34;
2139     private static final int MSG_CHECK_MUTE_MUSIC = 35;
2140     private static final int MSG_REPORT_NEW_ROUTES_A2DP = 36;
2141 
2142     private static final int MSG_IL_SAVE_PREF_DEVICES_FOR_CAPTURE_PRESET = 37;
2143     private static final int MSG_I_SAVE_CLEAR_PREF_DEVICES_FOR_CAPTURE_PRESET = 38;
2144 
2145     private static final int MSG_L_SET_COMMUNICATION_DEVICE_FOR_CLIENT = 42;
2146     private static final int MSG_IL_UPDATE_COMMUNICATION_ROUTE_CLIENT = 43;
2147 
2148     private static final int MSG_L_BT_ACTIVE_DEVICE_CHANGE_EXT = 45;
2149     //
2150     // process set volume for Le Audio, obj is BleVolumeInfo
2151     private static final int MSG_II_SET_LE_AUDIO_OUT_VOLUME = 46;
2152 
2153     private static final int MSG_IL_SAVE_NDEF_DEVICE_FOR_STRATEGY = 47;
2154     private static final int MSG_IL_SAVE_REMOVE_NDEF_DEVICE_FOR_STRATEGY = 48;
2155     private static final int MSG_IIL_BTLEAUDIO_TIMEOUT = 49;
2156 
2157     private static final int MSG_L_NOTIFY_PREFERRED_AUDIOPROFILE_APPLIED = 52;
2158     private static final int MSG_L_CHECK_COMMUNICATION_DEVICE_REMOVAL = 53;
2159 
2160     private static final int MSG_PERSIST_AUDIO_DEVICE_SETTINGS = 54;
2161 
2162     private static final int MSG_L_RECEIVED_BT_EVENT = 55;
2163 
2164     private static final int MSG_CHECK_COMMUNICATION_ROUTE_CLIENT_STATE = 56;
2165     private static final int MSG_I_UPDATE_LE_AUDIO_GROUP_ADDRESSES = 57;
2166     private static final int MSG_L_SYNCHRONIZE_ADI_DEVICES_IN_INVENTORY = 58;
2167     private static final int MSG_IL_UPDATED_ADI_DEVICE_STATE = 59;
2168     private static final int MSG_L_SET_FORCE_BT_A2DP_USE_NO_MUTE = 60;
2169 
isMessageHandledUnderWakelock(int msgId)2170     private static boolean isMessageHandledUnderWakelock(int msgId) {
2171         switch(msgId) {
2172             case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE:
2173             case MSG_L_SET_BT_ACTIVE_DEVICE:
2174             case MSG_IL_BTA2DP_TIMEOUT:
2175             case MSG_IIL_BTLEAUDIO_TIMEOUT:
2176             case MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE:
2177             case MSG_TOGGLE_HDMI:
2178             case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT:
2179             case MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT:
2180             case MSG_CHECK_MUTE_MUSIC:
2181                 return true;
2182             default:
2183                 return false;
2184         }
2185     }
2186 
2187     // Message helper methods
2188 
2189     // sendMsg() flags
2190     /** If the msg is already queued, replace it with this one. */
2191     private static final int SENDMSG_REPLACE = 0;
2192     /** If the msg is already queued, ignore this one and leave the old. */
2193     private static final int SENDMSG_NOOP = 1;
2194     /** If the msg is already queued, queue this one and leave the old. */
2195     private static final int SENDMSG_QUEUE = 2;
2196 
sendMsg(int msg, int existingMsgPolicy, int delay)2197     private void sendMsg(int msg, int existingMsgPolicy, int delay) {
2198         sendIILMsg(msg, existingMsgPolicy, 0, 0, null, delay);
2199     }
2200 
sendILMsg(int msg, int existingMsgPolicy, int arg, Object obj, int delay)2201     private void sendILMsg(int msg, int existingMsgPolicy, int arg, Object obj, int delay) {
2202         sendIILMsg(msg, existingMsgPolicy, arg, 0, obj, delay);
2203     }
2204 
sendLMsg(int msg, int existingMsgPolicy, Object obj, int delay)2205     private void sendLMsg(int msg, int existingMsgPolicy, Object obj, int delay) {
2206         sendIILMsg(msg, existingMsgPolicy, 0, 0, obj, delay);
2207     }
2208 
sendMsgNoDelay(int msg, int existingMsgPolicy)2209     private void sendMsgNoDelay(int msg, int existingMsgPolicy) {
2210         sendIILMsg(msg, existingMsgPolicy, 0, 0, null, 0);
2211     }
2212 
sendIMsgNoDelay(int msg, int existingMsgPolicy, int arg)2213     private void sendIMsgNoDelay(int msg, int existingMsgPolicy, int arg) {
2214         sendIILMsg(msg, existingMsgPolicy, arg, 0, null, 0);
2215     }
2216 
sendIIMsgNoDelay(int msg, int existingMsgPolicy, int arg1, int arg2)2217     private void sendIIMsgNoDelay(int msg, int existingMsgPolicy, int arg1, int arg2) {
2218         sendIILMsg(msg, existingMsgPolicy, arg1, arg2, null, 0);
2219     }
2220 
sendILMsgNoDelay(int msg, int existingMsgPolicy, int arg, Object obj)2221     private void sendILMsgNoDelay(int msg, int existingMsgPolicy, int arg, Object obj) {
2222         sendIILMsg(msg, existingMsgPolicy, arg, 0, obj, 0);
2223     }
2224 
sendLMsgNoDelay(int msg, int existingMsgPolicy, Object obj)2225     private void sendLMsgNoDelay(int msg, int existingMsgPolicy, Object obj) {
2226         sendIILMsg(msg, existingMsgPolicy, 0, 0, obj, 0);
2227     }
2228 
sendIILMsgNoDelay(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj)2229     private void sendIILMsgNoDelay(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj) {
2230         sendIILMsg(msg, existingMsgPolicy, arg1, arg2, obj, 0);
2231     }
2232 
sendIILMsg(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj, int delay)2233     private void sendIILMsg(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj,
2234                             int delay) {
2235         if (existingMsgPolicy == SENDMSG_REPLACE) {
2236             mBrokerHandler.removeMessages(msg);
2237         } else if (existingMsgPolicy == SENDMSG_NOOP && mBrokerHandler.hasMessages(msg)) {
2238             return;
2239         }
2240 
2241         if (isMessageHandledUnderWakelock(msg)) {
2242             final long identity = Binder.clearCallingIdentity();
2243             try {
2244                 mBrokerEventWakeLock.acquire(BROKER_WAKELOCK_TIMEOUT_MS);
2245             } catch (Exception e) {
2246                 Log.e(TAG, "Exception acquiring wakelock", e);
2247             } finally {
2248                 Binder.restoreCallingIdentity(identity);
2249             }
2250         }
2251 
2252         if (MESSAGES_MUTE_MUSIC.contains(msg)) {
2253             checkMessagesMuteMusic(msg);
2254         }
2255 
2256         synchronized (sLastDeviceConnectionMsgTimeLock) {
2257             long time = SystemClock.uptimeMillis() + delay;
2258 
2259             switch (msg) {
2260                 case MSG_L_SET_BT_ACTIVE_DEVICE:
2261                 case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE:
2262                 case MSG_IL_BTA2DP_TIMEOUT:
2263                 case MSG_IIL_BTLEAUDIO_TIMEOUT:
2264                 case MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE:
2265                     if (sLastDeviceConnectMsgTime >= time) {
2266                         // add a little delay to make sure messages are ordered as expected
2267                         time = sLastDeviceConnectMsgTime + 30;
2268                     }
2269                     sLastDeviceConnectMsgTime = time;
2270                     break;
2271                 default:
2272                     break;
2273             }
2274             mBrokerHandler.sendMessageAtTime(mBrokerHandler.obtainMessage(msg, arg1, arg2, obj),
2275                     time);
2276         }
2277     }
2278 
removeMsgForCheckClientState(int uid)2279     private void removeMsgForCheckClientState(int uid) {
2280         CommunicationRouteClient crc = getCommunicationRouteClientForUid(uid);
2281         if (crc != null) {
2282             mBrokerHandler.removeEqualMessages(MSG_CHECK_COMMUNICATION_ROUTE_CLIENT_STATE, crc);
2283         }
2284     }
2285 
sendMsgForCheckClientState(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj, int delay)2286     private void sendMsgForCheckClientState(int msg, int existingMsgPolicy,
2287                                             int arg1, int arg2, Object obj, int delay) {
2288         if ((existingMsgPolicy == SENDMSG_REPLACE) && (obj != null)) {
2289             mBrokerHandler.removeEqualMessages(msg, obj);
2290         }
2291 
2292         long time = SystemClock.uptimeMillis() + delay;
2293         mBrokerHandler.sendMessageAtTime(mBrokerHandler.obtainMessage(msg, arg1, arg2, obj), time);
2294     }
2295 
2296     /** List of messages for which music is muted while processing is pending */
2297     private static final Set<Integer> MESSAGES_MUTE_MUSIC;
2298     static {
2299         MESSAGES_MUTE_MUSIC = new HashSet<>();
2300         MESSAGES_MUTE_MUSIC.add(MSG_L_SET_BT_ACTIVE_DEVICE);
2301         MESSAGES_MUTE_MUSIC.add(MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE);
2302         MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT);
2303         MESSAGES_MUTE_MUSIC.add(MSG_L_SET_FORCE_BT_A2DP_USE);
2304     }
2305 
2306     private AtomicBoolean mMusicMuted = new AtomicBoolean(false);
2307 
hasIntersection(Set<T> a, Set<T> b)2308     private static <T> boolean hasIntersection(Set<T> a, Set<T> b) {
2309         for (T e : a) {
2310             if (b.contains(e)) return true;
2311         }
2312         return false;
2313     }
2314 
messageMutesMusic(int message)2315     boolean messageMutesMusic(int message) {
2316         if (message == 0) {
2317             return false;
2318         }
2319         // Do not mute on bluetooth event if music is playing on a wired headset.
2320         if ((message == MSG_L_SET_BT_ACTIVE_DEVICE
2321                 || message == MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT
2322                 || message == MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE)
2323                 && AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0)
2324                 && hasIntersection(mDeviceInventory.DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET,
2325                         mAudioService.getDeviceSetForStream(AudioSystem.STREAM_MUSIC))) {
2326             return false;
2327         }
2328         return true;
2329     }
2330 
2331     /** Mutes or unmutes music according to pending A2DP messages */
checkMessagesMuteMusic(int message)2332     private void checkMessagesMuteMusic(int message) {
2333         boolean mute = messageMutesMusic(message);
2334         if (!mute) {
2335             for (int msg : MESSAGES_MUTE_MUSIC) {
2336                 if (mBrokerHandler.hasMessages(msg)) {
2337                     if (messageMutesMusic(msg)) {
2338                         mute = true;
2339                         break;
2340                     }
2341                 }
2342             }
2343         }
2344 
2345         if (mute != mMusicMuted.getAndSet(mute)) {
2346             mAudioService.setMusicMute(mute);
2347         }
2348     }
2349 
2350     // List of applications requesting a specific route for communication.
2351     @GuardedBy("mDeviceStateLock")
2352     private final @NonNull LinkedList<CommunicationRouteClient> mCommunicationRouteClients =
2353             new LinkedList<CommunicationRouteClient>();
2354 
2355     private class CommunicationRouteClient implements IBinder.DeathRecipient {
2356         private final IBinder mCb;
2357         private final int mUid;
2358         private final boolean mIsPrivileged;
2359         private AudioDeviceAttributes mDevice;
2360         private boolean mPlaybackActive;
2361         private boolean mRecordingActive;
2362 
CommunicationRouteClient(IBinder cb, int uid, AudioDeviceAttributes device, boolean isPrivileged)2363         CommunicationRouteClient(IBinder cb, int uid, AudioDeviceAttributes device,
2364                                  boolean isPrivileged) {
2365             mCb = cb;
2366             mUid = uid;
2367             mDevice = device;
2368             mIsPrivileged = isPrivileged;
2369             mPlaybackActive = mAudioService.isPlaybackActiveForUid(uid);
2370             mRecordingActive = mAudioService.isRecordingActiveForUid(uid);
2371         }
2372 
registerDeathRecipient()2373         public boolean registerDeathRecipient() {
2374             boolean status = false;
2375             try {
2376                 mCb.linkToDeath(this, 0);
2377                 status = true;
2378             } catch (RemoteException e) {
2379                 Log.w(TAG, "CommunicationRouteClient could not link to " + mCb + " binder death");
2380             }
2381             return status;
2382         }
2383 
unregisterDeathRecipient()2384         public void unregisterDeathRecipient() {
2385             try {
2386                 mCb.unlinkToDeath(this, 0);
2387             } catch (NoSuchElementException e) {
2388                 Log.w(TAG, "CommunicationRouteClient could not unlink to " + mCb + " binder death");
2389             }
2390         }
2391 
2392         @Override
binderDied()2393         public void binderDied() {
2394             postCommunicationRouteClientDied(this);
2395         }
2396 
getBinder()2397         IBinder getBinder() {
2398             return mCb;
2399         }
2400 
getUid()2401         int getUid() {
2402             return mUid;
2403         }
2404 
isPrivileged()2405         boolean isPrivileged() {
2406             return mIsPrivileged;
2407         }
2408 
getDevice()2409         AudioDeviceAttributes getDevice() {
2410             return mDevice;
2411         }
2412 
setPlaybackActive(boolean active)2413         public void setPlaybackActive(boolean active) {
2414             mPlaybackActive = active;
2415         }
2416 
setRecordingActive(boolean active)2417         public void setRecordingActive(boolean active) {
2418             mRecordingActive = active;
2419         }
2420 
isActive()2421         public boolean isActive() {
2422             return mIsPrivileged || mRecordingActive || mPlaybackActive;
2423         }
2424 
2425         @Override
toString()2426         public String toString() {
2427             return "[CommunicationRouteClient: mUid: " + mUid
2428                     + " mDevice: " + mDevice.toString()
2429                     + " mIsPrivileged: " + mIsPrivileged
2430                     + " mPlaybackActive: " + mPlaybackActive
2431                     + " mRecordingActive: " + mRecordingActive + "]";
2432         }
2433     }
2434 
2435     // @GuardedBy("mSetModeLock")
2436     @GuardedBy("mDeviceStateLock")
onCommunicationRouteClientDied(CommunicationRouteClient client)2437     private void onCommunicationRouteClientDied(CommunicationRouteClient client) {
2438         if (client == null) {
2439             return;
2440         }
2441         Log.w(TAG, "Communication client died");
2442         setCommunicationRouteForClient(client.getBinder(), client.getUid(), null,
2443                 BtHelper.SCO_MODE_UNDEFINED, client.isPrivileged(),
2444                 "onCommunicationRouteClientDied");
2445     }
2446 
2447     /**
2448      * Determines which preferred device for phone strategy should be sent to audio policy manager
2449      * as a function of current SCO audio activation state and active communication route requests.
2450      * SCO audio state has the highest priority as it can result from external activation by
2451      * telephony service.
2452      * @return selected forced usage for communication.
2453      */
2454     @GuardedBy("mDeviceStateLock")
preferredCommunicationDevice()2455     @Nullable private AudioDeviceAttributes preferredCommunicationDevice() {
2456         boolean btSCoOn = mBtHelper.isBluetoothScoOn();
2457         synchronized (mBluetoothAudioStateLock) {
2458             btSCoOn = btSCoOn && mBluetoothScoOn;
2459         }
2460 
2461         if (btSCoOn) {
2462             // Use the SCO device known to BtHelper so that it matches exactly
2463             // what has been communicated to audio policy manager. The device
2464             // returned by requestedCommunicationDevice() can be a placeholder SCO device if legacy
2465             // APIs are used to start SCO audio.
2466             AudioDeviceAttributes device = mBtHelper.getHeadsetAudioDevice();
2467             if (device != null) {
2468                 return device;
2469             }
2470         }
2471         AudioDeviceAttributes device = requestedCommunicationDevice();
2472         if (device == null || device.getType() == AudioDeviceInfo.TYPE_BLUETOOTH_SCO) {
2473             // Do not indicate BT SCO selection if SCO is requested but SCO is not ON
2474             return null;
2475         }
2476         return device;
2477     }
2478 
2479     /**
2480      * Configures audio policy manager and audio HAL according to active communication route.
2481      * Always called from message Handler.
2482      */
2483     // @GuardedBy("mSetModeLock")
2484     @GuardedBy("mDeviceStateLock")
updateCommunicationRoute(String eventSource)2485     private void updateCommunicationRoute(String eventSource) {
2486         AudioDeviceAttributes preferredCommunicationDevice = preferredCommunicationDevice();
2487         if (AudioService.DEBUG_COMM_RTE) {
2488             Log.v(TAG, "updateCommunicationRoute, preferredCommunicationDevice: "
2489                     + preferredCommunicationDevice + " eventSource: " + eventSource);
2490         }
2491         AudioService.sDeviceLogger.enqueue((new EventLogger.StringEvent(
2492                 "updateCommunicationRoute, preferredCommunicationDevice: "
2493                 + preferredCommunicationDevice + " eventSource: " + eventSource)));
2494 
2495         if (preferredCommunicationDevice == null) {
2496             AudioDeviceAttributes defaultDevice = getDefaultCommunicationDevice();
2497             if (defaultDevice != null) {
2498                 mDeviceInventory.setPreferredDevicesForStrategyInt(
2499                         mCommunicationStrategyId, Arrays.asList(defaultDevice));
2500                 mDeviceInventory.setPreferredDevicesForStrategyInt(
2501                         mAccessibilityStrategyId, Arrays.asList(defaultDevice));
2502             } else {
2503                 mDeviceInventory.removePreferredDevicesForStrategyInt(mCommunicationStrategyId);
2504                 mDeviceInventory.removePreferredDevicesForStrategyInt(mAccessibilityStrategyId);
2505             }
2506             mDeviceInventory.applyConnectedDevicesRoles();
2507             mDeviceInventory.reapplyExternalDevicesRoles();
2508         } else {
2509             mDeviceInventory.setPreferredDevicesForStrategyInt(
2510                     mCommunicationStrategyId, Arrays.asList(preferredCommunicationDevice));
2511             mDeviceInventory.setPreferredDevicesForStrategyInt(
2512                     mAccessibilityStrategyId, Arrays.asList(preferredCommunicationDevice));
2513         }
2514         onUpdatePhoneStrategyDevice(preferredCommunicationDevice);
2515     }
2516 
2517     /**
2518      * Select new communication device from communication route client at the top of the stack
2519      * and restore communication route including restarting SCO audio if needed.
2520      */
2521     // @GuardedBy("mSetModeLock")
2522     @GuardedBy("mDeviceStateLock")
onUpdateCommunicationRouteClient(boolean wasBtScoRequested, String eventSource)2523     private void onUpdateCommunicationRouteClient(boolean wasBtScoRequested, String eventSource) {
2524         CommunicationRouteClient crc = topCommunicationRouteClient();
2525         if (AudioService.DEBUG_COMM_RTE) {
2526             Log.v(TAG, "onUpdateCommunicationRouteClient, crc: " + crc
2527                     + " wasBtScoRequested: " + wasBtScoRequested + " eventSource: " + eventSource);
2528         }
2529         if (crc != null) {
2530             setCommunicationRouteForClient(crc.getBinder(), crc.getUid(), crc.getDevice(),
2531                     BtHelper.SCO_MODE_UNDEFINED, crc.isPrivileged(), eventSource);
2532         } else {
2533             if (!mScoManagedByAudio && !isBluetoothScoRequested() && wasBtScoRequested) {
2534                 mBtHelper.stopBluetoothSco(eventSource);
2535             }
2536             updateCommunicationRoute(eventSource);
2537         }
2538     }
2539 
2540     // @GuardedBy("mSetModeLock")
2541     @GuardedBy("mDeviceStateLock")
onUpdatePhoneStrategyDevice(AudioDeviceAttributes device)2542     private void onUpdatePhoneStrategyDevice(AudioDeviceAttributes device) {
2543         boolean wasSpeakerphoneActive = isSpeakerphoneActive();
2544         mPreferredCommunicationDevice = device;
2545         updateActiveCommunicationDevice();
2546         if (wasSpeakerphoneActive != isSpeakerphoneActive()) {
2547             try {
2548                 mContext.sendBroadcastAsUser(
2549                         new Intent(AudioManager.ACTION_SPEAKERPHONE_STATE_CHANGED)
2550                                 .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY),
2551                                           UserHandle.ALL);
2552             } catch (Exception e) {
2553                 Log.w(TAG, "failed to broadcast ACTION_SPEAKERPHONE_STATE_CHANGED: " + e);
2554             }
2555         }
2556         mAudioService.postUpdateRingerModeServiceInt();
2557         dispatchCommunicationDevice();
2558     }
2559 
2560     @GuardedBy("mDeviceStateLock")
removeCommunicationRouteClient( IBinder cb, boolean unregister)2561     private CommunicationRouteClient removeCommunicationRouteClient(
2562                     IBinder cb, boolean unregister) {
2563         for (CommunicationRouteClient cl : mCommunicationRouteClients) {
2564             if (cl.getBinder() == cb) {
2565                 if (unregister) {
2566                     cl.unregisterDeathRecipient();
2567                 }
2568                 removeMsgForCheckClientState(cl.getUid());
2569                 mCommunicationRouteClients.remove(cl);
2570                 return cl;
2571             }
2572         }
2573         return null;
2574     }
2575 
2576     @GuardedBy("mDeviceStateLock")
addCommunicationRouteClient(IBinder cb, int uid, AudioDeviceAttributes device, boolean isPrivileged)2577     private CommunicationRouteClient addCommunicationRouteClient(IBinder cb, int uid,
2578                 AudioDeviceAttributes device, boolean isPrivileged) {
2579         // always insert new request at first position
2580         removeCommunicationRouteClient(cb, true);
2581         CommunicationRouteClient client =
2582                 new CommunicationRouteClient(cb, uid, device, isPrivileged);
2583         if (client.registerDeathRecipient()) {
2584             mCommunicationRouteClients.add(0, client);
2585             if (!client.isActive()) {
2586                 // initialize the inactive client's state as active and check it after 6 seconds
2587                 setForceCommunicationClientStateAndDelayedCheck(
2588                         client,
2589                         !mAudioService.isPlaybackActiveForUid(client.getUid()),
2590                         !mAudioService.isRecordingActiveForUid(client.getUid()));
2591             }
2592             return client;
2593         }
2594         return null;
2595     }
2596 
2597     @GuardedBy("mDeviceStateLock")
getCommunicationRouteClientForUid(int uid)2598     private CommunicationRouteClient getCommunicationRouteClientForUid(int uid) {
2599         for (CommunicationRouteClient cl : mCommunicationRouteClients) {
2600             if (cl.getUid() == uid) {
2601                 return cl;
2602             }
2603         }
2604         return null;
2605     }
2606 
2607     @GuardedBy("mDeviceStateLock")
2608     // LE Audio: For system server (Telecom) and APKs targeting S and above, we let the audio
2609     // policy routing rules select the default communication device.
2610     // For older APKs, we force LE Audio headset when connected as those APKs cannot select a LE
2611     // Audiodevice explicitly.
communnicationDeviceLeAudioCompatOn()2612     private boolean communnicationDeviceLeAudioCompatOn() {
2613         return mAudioModeOwner.mMode == AudioSystem.MODE_IN_COMMUNICATION
2614                 && !(CompatChanges.isChangeEnabled(
2615                         USE_SET_COMMUNICATION_DEVICE, mAudioModeOwner.mUid)
2616                      || mAudioModeOwner.mUid == android.os.Process.SYSTEM_UID);
2617     }
2618 
2619     @GuardedBy("mDeviceStateLock")
2620     // Hearing Aid: For system server (Telecom) and IN_CALL mode we let the audio
2621     // policy routing rules select the default communication device.
2622     // For 3p apps and IN_COMMUNICATION mode we force Hearing aid when connected to maintain
2623     // backwards compatibility
communnicationDeviceHaCompatOn()2624     private boolean communnicationDeviceHaCompatOn() {
2625         return mAudioModeOwner.mMode == AudioSystem.MODE_IN_COMMUNICATION
2626                 && !(mAudioModeOwner.mUid == android.os.Process.SYSTEM_UID);
2627     }
2628 
2629     @GuardedBy("mDeviceStateLock")
getDefaultCommunicationDevice()2630     AudioDeviceAttributes getDefaultCommunicationDevice() {
2631         AudioDeviceAttributes device = null;
2632         // If both LE and Hearing Aid are active (thie should not happen),
2633         // priority to Hearing Aid.
2634         if (communnicationDeviceHaCompatOn()) {
2635             device = mDeviceInventory.getDeviceOfType(AudioSystem.DEVICE_OUT_HEARING_AID);
2636         }
2637         if (device == null && communnicationDeviceLeAudioCompatOn()) {
2638             device = mDeviceInventory.getDeviceOfType(AudioSystem.DEVICE_OUT_BLE_HEADSET);
2639         }
2640         return device;
2641     }
2642 
updateCommunicationRouteClientsActivity( List<AudioPlaybackConfiguration> playbackConfigs, List<AudioRecordingConfiguration> recordConfigs)2643     void updateCommunicationRouteClientsActivity(
2644             List<AudioPlaybackConfiguration> playbackConfigs,
2645             List<AudioRecordingConfiguration> recordConfigs) {
2646         synchronized (mSetModeLock) {
2647             synchronized (mDeviceStateLock) {
2648                 for (CommunicationRouteClient crc : mCommunicationRouteClients) {
2649                     boolean wasActive = crc.isActive();
2650                     boolean updateClientState = false;
2651                     if (playbackConfigs != null) {
2652                         crc.setPlaybackActive(false);
2653                         for (AudioPlaybackConfiguration config : playbackConfigs) {
2654                             if (config.getClientUid() == crc.getUid()
2655                                     && config.isActive()) {
2656                                 crc.setPlaybackActive(true);
2657                                 updateClientState = true;
2658                                 break;
2659                             }
2660                         }
2661                     }
2662                     if (recordConfigs != null) {
2663                         crc.setRecordingActive(false);
2664                         for (AudioRecordingConfiguration config : recordConfigs) {
2665                             if (config.getClientUid() == crc.getUid()
2666                                     && !config.isClientSilenced()) {
2667                                 crc.setRecordingActive(true);
2668                                 updateClientState = true;
2669                                 break;
2670                             }
2671                         }
2672                     }
2673                     if (updateClientState) {
2674                         removeMsgForCheckClientState(crc.getUid());
2675                         updateCommunicationRouteClientState(crc, wasActive);
2676                     } else {
2677                         if (wasActive) {
2678                             setForceCommunicationClientStateAndDelayedCheck(
2679                                     crc,
2680                                     playbackConfigs != null /* forcePlaybackActive */,
2681                                     recordConfigs != null /* forceRecordingActive */);
2682                         }
2683                     }
2684                 }
2685             }
2686         }
2687     }
2688 
getDeviceIdentityAddresses(AudioDeviceAttributes device)2689     List<String> getDeviceIdentityAddresses(AudioDeviceAttributes device) {
2690         synchronized (mDeviceStateLock) {
2691             return mDeviceInventory.getDeviceIdentityAddresses(device);
2692         }
2693     }
2694 
dispatchPreferredMixerAttributesChangedCausedByDeviceRemoved(AudioDeviceInfo info)2695     void dispatchPreferredMixerAttributesChangedCausedByDeviceRemoved(AudioDeviceInfo info) {
2696         // Currently, only media usage will be allowed to set preferred mixer attributes
2697         mAudioService.dispatchPreferredMixerAttributesChanged(
2698                 new AudioAttributes.Builder()
2699                         .setUsage(AudioAttributes.USAGE_MEDIA).build(),
2700                 info.getId(),
2701                 null /*mixerAttributes*/);
2702     }
2703 
2704     /**
2705      * post a message to persist the audio device settings.
2706      * Message is delayed by 1s on purpose in case of successive changes in quick succession (at
2707      * init time for instance)
2708      * Note this method is made public to work around a Mockito bug where it needs to be public
2709      * in order to be mocked by a test a the same package
2710      * (see https://code.google.com/archive/p/mockito/issues/127)
2711      */
postPersistAudioDeviceSettings()2712     public void postPersistAudioDeviceSettings() {
2713         sendMsg(MSG_PERSIST_AUDIO_DEVICE_SETTINGS, SENDMSG_REPLACE, /*delay*/ 1000);
2714     }
2715 
onPersistAudioDeviceSettings()2716     void onPersistAudioDeviceSettings() {
2717         final String deviceSettings = mDeviceInventory.getDeviceSettings();
2718         Log.v(TAG, "onPersistAudioDeviceSettings AdiDeviceState: " + deviceSettings);
2719         String currentSettings = readDeviceSettings();
2720         if (deviceSettings.equals(currentSettings)) {
2721             return;
2722         }
2723         final SettingsAdapter settingsAdapter = mAudioService.getSettings();
2724         try {
2725             boolean res = settingsAdapter.putSecureStringForUser(mAudioService.getContentResolver(),
2726                     Settings.Secure.AUDIO_DEVICE_INVENTORY,
2727                     deviceSettings, UserHandle.USER_CURRENT);
2728             if (!res) {
2729                 Log.e(TAG, "error saving AdiDeviceState: " + deviceSettings);
2730             }
2731         } catch (IllegalArgumentException e) {
2732             Log.e(TAG, "error saving AdiDeviceState: " + deviceSettings, e);
2733         }
2734     }
2735 
readDeviceSettings()2736     private String readDeviceSettings() {
2737         final SettingsAdapter settingsAdapter = mAudioService.getSettings();
2738         final ContentResolver contentResolver = mAudioService.getContentResolver();
2739         return settingsAdapter.getSecureStringForUser(contentResolver,
2740                 Settings.Secure.AUDIO_DEVICE_INVENTORY, UserHandle.USER_CURRENT);
2741     }
2742 
onReadAudioDeviceSettings()2743     void onReadAudioDeviceSettings() {
2744         final SettingsAdapter settingsAdapter = mAudioService.getSettings();
2745         final ContentResolver contentResolver = mAudioService.getContentResolver();
2746         String settings = readDeviceSettings();
2747         if (settings == null) {
2748             Log.i(TAG, "reading AdiDeviceState from legacy key"
2749                     + Settings.Secure.SPATIAL_AUDIO_ENABLED);
2750             // legacy string format for key SPATIAL_AUDIO_ENABLED has the same order of fields like
2751             // the strings for key AUDIO_DEVICE_INVENTORY. This will ensure to construct valid
2752             // device settings when calling {@link #setDeviceSettings()}
2753             settings = settingsAdapter.getSecureStringForUser(contentResolver,
2754                     Settings.Secure.SPATIAL_AUDIO_ENABLED, UserHandle.USER_CURRENT);
2755             if (settings == null) {
2756                 Log.i(TAG, "no AdiDeviceState stored with legacy key");
2757             } else if (!settings.equals("")) {
2758                 // Delete old key value and update the new key
2759                 if (!settingsAdapter.putSecureStringForUser(contentResolver,
2760                         Settings.Secure.SPATIAL_AUDIO_ENABLED,
2761                         /*value=*/"",
2762                         UserHandle.USER_CURRENT)) {
2763                     Log.w(TAG, "cannot erase the legacy AdiDeviceState with key "
2764                             + Settings.Secure.SPATIAL_AUDIO_ENABLED);
2765                 }
2766                 if (!settingsAdapter.putSecureStringForUser(contentResolver,
2767                         Settings.Secure.AUDIO_DEVICE_INVENTORY,
2768                         settings,
2769                         UserHandle.USER_CURRENT)) {
2770                     Log.e(TAG, "error updating the new AdiDeviceState with key "
2771                             + Settings.Secure.AUDIO_DEVICE_INVENTORY);
2772                 }
2773             }
2774         }
2775 
2776         if (settings != null && !settings.equals("")) {
2777             setDeviceSettings(settings);
2778         }
2779     }
2780 
setDeviceSettings(String settings)2781     void setDeviceSettings(String settings) {
2782         mDeviceInventory.setDeviceSettings(settings);
2783     }
2784 
2785     /** Test only method. */
getDeviceSettings()2786     String getDeviceSettings() {
2787         return mDeviceInventory.getDeviceSettings();
2788     }
2789 
getImmutableDeviceInventory()2790     Collection<AdiDeviceState> getImmutableDeviceInventory() {
2791         return mDeviceInventory.getImmutableDeviceInventory();
2792     }
2793 
addOrUpdateDeviceSAStateInInventory(AdiDeviceState deviceState, boolean syncInventory)2794     void addOrUpdateDeviceSAStateInInventory(AdiDeviceState deviceState, boolean syncInventory) {
2795         mDeviceInventory.addOrUpdateDeviceSAStateInInventory(deviceState, syncInventory);
2796     }
2797 
addOrUpdateBtAudioDeviceCategoryInInventory( AdiDeviceState deviceState, boolean syncInventory)2798     void addOrUpdateBtAudioDeviceCategoryInInventory(
2799             AdiDeviceState deviceState, boolean syncInventory) {
2800         mDeviceInventory.addOrUpdateAudioDeviceCategoryInInventory(deviceState, syncInventory);
2801     }
2802 
2803     @Nullable
findDeviceStateForAudioDeviceAttributes(AudioDeviceAttributes ada, int canonicalType)2804     AdiDeviceState findDeviceStateForAudioDeviceAttributes(AudioDeviceAttributes ada,
2805             int canonicalType) {
2806         return mDeviceInventory.findDeviceStateForAudioDeviceAttributes(ada, canonicalType);
2807     }
2808 
2809     @Nullable
findBtDeviceStateForAddress(String address, int deviceType)2810     AdiDeviceState findBtDeviceStateForAddress(String address, int deviceType) {
2811         return mDeviceInventory.findBtDeviceStateForAddress(address, deviceType);
2812     }
2813 
addAudioDeviceWithCategoryInInventoryIfNeeded(@onNull String address, @AudioDeviceCategory int btAudioDeviceCategory)2814     void addAudioDeviceWithCategoryInInventoryIfNeeded(@NonNull String address,
2815             @AudioDeviceCategory int btAudioDeviceCategory) {
2816         mDeviceInventory.addAudioDeviceWithCategoryInInventoryIfNeeded(address,
2817                 btAudioDeviceCategory);
2818     }
2819 
2820     @AudioDeviceCategory
getAndUpdateBtAdiDeviceStateCategoryForAddress(@onNull String address)2821     int getAndUpdateBtAdiDeviceStateCategoryForAddress(@NonNull String address) {
2822         return mDeviceInventory.getAndUpdateBtAdiDeviceStateCategoryForAddress(address);
2823     }
2824 
isBluetoothAudioDeviceCategoryFixed(@onNull String address)2825     boolean isBluetoothAudioDeviceCategoryFixed(@NonNull String address) {
2826         return mDeviceInventory.isBluetoothAudioDeviceCategoryFixed(address);
2827     }
2828 
isSADevice(AdiDeviceState deviceState)2829     /*package*/ boolean isSADevice(AdiDeviceState deviceState) {
2830         return mAudioService.isSADevice(deviceState);
2831     }
2832 
2833     //------------------------------------------------
2834     // for testing purposes only
clearDeviceInventory()2835     void clearDeviceInventory() {
2836         mDeviceInventory.clearDeviceInventory();
2837     }
2838 
2839 }
2840