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