• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)1252     /*package*/ void registerStrategyPreferredDevicesDispatcher(
1253             @NonNull IStrategyPreferredDevicesDispatcher dispatcher) {
1254         mDeviceInventory.registerStrategyPreferredDevicesDispatcher(dispatcher);
1255     }
1256 
unregisterStrategyPreferredDevicesDispatcher( @onNull IStrategyPreferredDevicesDispatcher dispatcher)1257     /*package*/ void unregisterStrategyPreferredDevicesDispatcher(
1258             @NonNull IStrategyPreferredDevicesDispatcher dispatcher) {
1259         mDeviceInventory.unregisterStrategyPreferredDevicesDispatcher(dispatcher);
1260     }
1261 
registerStrategyNonDefaultDevicesDispatcher( @onNull IStrategyNonDefaultDevicesDispatcher dispatcher)1262     /*package*/ void registerStrategyNonDefaultDevicesDispatcher(
1263             @NonNull IStrategyNonDefaultDevicesDispatcher dispatcher) {
1264         mDeviceInventory.registerStrategyNonDefaultDevicesDispatcher(dispatcher);
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)1281     /*package*/ void registerCapturePresetDevicesRoleDispatcher(
1282             @NonNull ICapturePresetDevicesRoleDispatcher dispatcher) {
1283         mDeviceInventory.registerCapturePresetDevicesRoleDispatcher(dispatcher);
1284     }
1285 
unregisterCapturePresetDevicesRoleDispatcher( @onNull ICapturePresetDevicesRoleDispatcher dispatcher)1286     /*package*/ void unregisterCapturePresetDevicesRoleDispatcher(
1287             @NonNull ICapturePresetDevicesRoleDispatcher dispatcher) {
1288         mDeviceInventory.unregisterCapturePresetDevicesRoleDispatcher(dispatcher);
1289     }
1290 
registerCommunicationDeviceDispatcher( @onNull ICommunicationDeviceDispatcher dispatcher)1291     /*package*/ void registerCommunicationDeviceDispatcher(
1292             @NonNull ICommunicationDeviceDispatcher dispatcher) {
1293         mCommDevDispatchers.register(dispatcher);
1294     }
1295 
unregisterCommunicationDeviceDispatcher( @onNull ICommunicationDeviceDispatcher dispatcher)1296     /*package*/ void unregisterCommunicationDeviceDispatcher(
1297             @NonNull ICommunicationDeviceDispatcher dispatcher) {
1298         mCommDevDispatchers.unregister(dispatcher);
1299     }
1300 
1301     // Monitoring of communication device
1302     final RemoteCallbackList<ICommunicationDeviceDispatcher> mCommDevDispatchers =
1303             new RemoteCallbackList<ICommunicationDeviceDispatcher>();
1304 
1305     // portId of the device currently selected for communication: avoids broadcasting changes
1306     // when same communication route is applied
1307     @GuardedBy("mDeviceStateLock")
1308     int mCurCommunicationPortId = -1;
1309 
1310     @GuardedBy("mDeviceStateLock")
dispatchCommunicationDevice()1311     private void dispatchCommunicationDevice() {
1312         AudioDeviceInfo device = getCommunicationDevice();
1313         int portId = device != null ? device.getId() : 0;
1314         if (portId == mCurCommunicationPortId) {
1315             return;
1316         }
1317         mCurCommunicationPortId = portId;
1318 
1319         final int nbDispatchers = mCommDevDispatchers.beginBroadcast();
1320         for (int i = 0; i < nbDispatchers; i++) {
1321             try {
1322                 mCommDevDispatchers.getBroadcastItem(i)
1323                         .dispatchCommunicationDeviceChanged(portId);
1324             } catch (RemoteException e) {
1325             }
1326         }
1327         mCommDevDispatchers.finishBroadcast();
1328     }
1329 
1330 
1331     //---------------------------------------------------------------------
1332     // Communication with (to) AudioService
1333     //TODO check whether the AudioService methods are candidates to move here
postAccessoryPlugMediaUnmute(int device)1334     /*package*/ void postAccessoryPlugMediaUnmute(int device) {
1335         mAudioService.postAccessoryPlugMediaUnmute(device);
1336     }
1337 
getVssVolumeForDevice(int streamType, int device)1338     /*package*/ int getVssVolumeForDevice(int streamType, int device) {
1339         return mAudioService.getVssVolumeForDevice(streamType, device);
1340     }
1341 
getMaxVssVolumeForStream(int streamType)1342     /*package*/ int getMaxVssVolumeForStream(int streamType) {
1343         return mAudioService.getMaxVssVolumeForStream(streamType);
1344     }
1345 
getDeviceForStream(int streamType)1346     /*package*/ int getDeviceForStream(int streamType) {
1347         return mAudioService.getDeviceForStream(streamType);
1348     }
1349 
postApplyVolumeOnDevice(int streamType, int device, String caller)1350     /*package*/ void postApplyVolumeOnDevice(int streamType, int device, String caller) {
1351         mAudioService.postApplyVolumeOnDevice(streamType, device, caller);
1352     }
1353 
postSetVolumeIndexOnDevice(int streamType, int vssVolIndex, int device, String caller)1354     /*package*/ void postSetVolumeIndexOnDevice(int streamType, int vssVolIndex, int device,
1355                                                 String caller) {
1356         mAudioService.postSetVolumeIndexOnDevice(streamType, vssVolIndex, device, caller);
1357     }
1358 
postObserveDevicesForAllStreams()1359     /*packages*/ void postObserveDevicesForAllStreams() {
1360         mAudioService.postObserveDevicesForAllStreams();
1361     }
1362 
isInCommunication()1363     /*package*/ boolean isInCommunication() {
1364         return mAudioService.isInCommunication();
1365     }
1366 
hasMediaDynamicPolicy()1367     /*package*/ boolean hasMediaDynamicPolicy() {
1368         return mAudioService.hasMediaDynamicPolicy();
1369     }
1370 
getContentResolver()1371     /*package*/ ContentResolver getContentResolver() {
1372         return mAudioService.getContentResolver();
1373     }
1374 
checkMusicActive(int deviceType, String caller)1375     /*package*/ void checkMusicActive(int deviceType, String caller) {
1376         mAudioService.checkMusicActive(deviceType, caller);
1377     }
1378 
checkVolumeCecOnHdmiConnection( @udioService.ConnectionState int state, String caller)1379     /*package*/ void checkVolumeCecOnHdmiConnection(
1380             @AudioService.ConnectionState  int state, String caller) {
1381         mAudioService.postCheckVolumeCecOnHdmiConnection(state, caller);
1382     }
1383 
hasAudioFocusUsers()1384     /*package*/ boolean hasAudioFocusUsers() {
1385         return mAudioService.hasAudioFocusUsers();
1386     }
1387 
1388     //---------------------------------------------------------------------
1389     // Message handling on behalf of helper classes.
1390     // Each of these methods posts a message to mBrokerHandler message queue.
postBroadcastScoConnectionState(int state)1391     /*package*/ void postBroadcastScoConnectionState(int state) {
1392         sendIMsgNoDelay(MSG_I_BROADCAST_BT_CONNECTION_STATE, SENDMSG_QUEUE, state);
1393     }
1394 
postBroadcastBecomingNoisy()1395     /*package*/ void postBroadcastBecomingNoisy() {
1396         sendMsgNoDelay(MSG_BROADCAST_AUDIO_BECOMING_NOISY, SENDMSG_REPLACE);
1397     }
1398 
1399     @GuardedBy("mDeviceStateLock")
postBluetoothActiveDevice(BtDeviceInfo info, int delay)1400     /*package*/ void postBluetoothActiveDevice(BtDeviceInfo info, int delay) {
1401         sendLMsg(MSG_L_SET_BT_ACTIVE_DEVICE, SENDMSG_QUEUE, info, delay);
1402     }
1403 
postSetWiredDeviceConnectionState( AudioDeviceInventory.WiredDeviceConnectionState connectionState, int delay)1404     /*package*/ void postSetWiredDeviceConnectionState(
1405             AudioDeviceInventory.WiredDeviceConnectionState connectionState, int delay) {
1406         sendLMsg(MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE, SENDMSG_QUEUE, connectionState, delay);
1407     }
1408 
postBtProfileDisconnected(int profile)1409     /*package*/ void postBtProfileDisconnected(int profile) {
1410         sendIMsgNoDelay(MSG_I_BT_SERVICE_DISCONNECTED_PROFILE, SENDMSG_QUEUE, profile);
1411     }
1412 
postBtProfileConnected(int profile, BluetoothProfile proxy)1413     /*package*/ void postBtProfileConnected(int profile, BluetoothProfile proxy) {
1414         sendILMsgNoDelay(MSG_IL_BT_SERVICE_CONNECTED_PROFILE, SENDMSG_QUEUE, profile, proxy);
1415     }
1416 
postCommunicationRouteClientDied(CommunicationRouteClient client)1417     /*package*/ void postCommunicationRouteClientDied(CommunicationRouteClient client) {
1418         sendLMsgNoDelay(MSG_L_COMMUNICATION_ROUTE_CLIENT_DIED, SENDMSG_QUEUE, client);
1419     }
1420 
postSaveSetPreferredDevicesForStrategy(int strategy, List<AudioDeviceAttributes> devices)1421     /*package*/ void postSaveSetPreferredDevicesForStrategy(int strategy,
1422                                                             List<AudioDeviceAttributes> devices)
1423     {
1424         sendILMsgNoDelay(MSG_IL_SAVE_PREF_DEVICES_FOR_STRATEGY, SENDMSG_QUEUE, strategy, devices);
1425     }
1426 
postSaveRemovePreferredDevicesForStrategy(int strategy)1427     /*package*/ void postSaveRemovePreferredDevicesForStrategy(int strategy) {
1428         sendIMsgNoDelay(MSG_I_SAVE_REMOVE_PREF_DEVICES_FOR_STRATEGY, SENDMSG_QUEUE, strategy);
1429     }
1430 
postSaveSetDeviceAsNonDefaultForStrategy( int strategy, AudioDeviceAttributes device)1431     /*package*/ void postSaveSetDeviceAsNonDefaultForStrategy(
1432             int strategy, AudioDeviceAttributes device) {
1433         sendILMsgNoDelay(MSG_IL_SAVE_NDEF_DEVICE_FOR_STRATEGY, SENDMSG_QUEUE, strategy, device);
1434     }
1435 
postSaveRemoveDeviceAsNonDefaultForStrategy( int strategy, AudioDeviceAttributes device)1436     /*package*/ void postSaveRemoveDeviceAsNonDefaultForStrategy(
1437             int strategy, AudioDeviceAttributes device) {
1438         sendILMsgNoDelay(
1439                 MSG_IL_SAVE_REMOVE_NDEF_DEVICE_FOR_STRATEGY, SENDMSG_QUEUE, strategy, device);
1440     }
1441 
postSaveSetPreferredDevicesForCapturePreset( int capturePreset, List<AudioDeviceAttributes> devices)1442     /*package*/ void postSaveSetPreferredDevicesForCapturePreset(
1443             int capturePreset, List<AudioDeviceAttributes> devices) {
1444         sendILMsgNoDelay(
1445                 MSG_IL_SAVE_PREF_DEVICES_FOR_CAPTURE_PRESET, SENDMSG_QUEUE, capturePreset, devices);
1446     }
1447 
postSaveClearPreferredDevicesForCapturePreset(int capturePreset)1448     /*package*/ void postSaveClearPreferredDevicesForCapturePreset(int capturePreset) {
1449         sendIMsgNoDelay(
1450                 MSG_I_SAVE_CLEAR_PREF_DEVICES_FOR_CAPTURE_PRESET, SENDMSG_QUEUE, capturePreset);
1451     }
1452 
postUpdateCommunicationRouteClient( boolean wasBtScoRequested, String eventSource)1453     /*package*/ void postUpdateCommunicationRouteClient(
1454             boolean wasBtScoRequested, String eventSource) {
1455         sendILMsgNoDelay(MSG_IL_UPDATE_COMMUNICATION_ROUTE_CLIENT, SENDMSG_QUEUE,
1456                 wasBtScoRequested ? 1 : 0, eventSource);
1457     }
1458 
postSetCommunicationDeviceForClient(CommunicationDeviceInfo info)1459     /*package*/ void postSetCommunicationDeviceForClient(CommunicationDeviceInfo info) {
1460         sendLMsgNoDelay(MSG_L_SET_COMMUNICATION_DEVICE_FOR_CLIENT, SENDMSG_QUEUE, info);
1461     }
1462 
postNotifyPreferredAudioProfileApplied(BluetoothDevice btDevice)1463     /*package*/ void postNotifyPreferredAudioProfileApplied(BluetoothDevice btDevice) {
1464         sendLMsgNoDelay(MSG_L_NOTIFY_PREFERRED_AUDIOPROFILE_APPLIED, SENDMSG_QUEUE, btDevice);
1465     }
1466 
postReceiveBtEvent(Intent intent)1467     /*package*/ void postReceiveBtEvent(Intent intent) {
1468         sendLMsgNoDelay(MSG_L_RECEIVED_BT_EVENT, SENDMSG_QUEUE, intent);
1469     }
1470 
1471     /*package*/ static final class CommunicationDeviceInfo {
1472         final @NonNull IBinder mCb; // Identifies the requesting client for death handler
1473         final int mUid; // Requester UID
1474         final @Nullable AudioDeviceAttributes mDevice; // Device being set or reset.
1475         final boolean mOn; // true if setting, false if resetting
1476         final int mScoAudioMode; // only used for SCO: requested audio mode
1477         final boolean mIsPrivileged; // true if the client app has MODIFY_PHONE_STATE permission
1478         final @NonNull String mEventSource; // caller identifier for logging
1479         boolean mWaitForStatus; // true if the caller waits for a completion status (API dependent)
1480         boolean mStatus = false; // completion status only used if mWaitForStatus is true
1481 
CommunicationDeviceInfo(@onNull IBinder cb, int uid, @Nullable AudioDeviceAttributes device, boolean on, int scoAudioMode, @NonNull String eventSource, boolean waitForStatus, boolean isPrivileged)1482         CommunicationDeviceInfo(@NonNull IBinder cb, int uid,
1483                 @Nullable AudioDeviceAttributes device, boolean on, int scoAudioMode,
1484                 @NonNull String eventSource, boolean waitForStatus, boolean isPrivileged) {
1485             mCb = cb;
1486             mUid = uid;
1487             mDevice = device;
1488             mOn = on;
1489             mScoAudioMode = scoAudioMode;
1490             mIsPrivileged = isPrivileged;
1491             mEventSource = eventSource;
1492             mWaitForStatus = waitForStatus;
1493         }
1494 
1495         // redefine equality op so we can match messages intended for this client
1496         @Override
equals(Object o)1497         public boolean equals(Object o) {
1498             if (o == null) {
1499                 return false;
1500             }
1501             if (this == o) {
1502                 return true;
1503             }
1504             if (!(o instanceof CommunicationDeviceInfo)) {
1505                 return false;
1506             }
1507 
1508             return mCb.equals(((CommunicationDeviceInfo) o).mCb)
1509                     && mUid == ((CommunicationDeviceInfo) o).mUid;
1510         }
1511 
1512         @Override
toString()1513         public String toString() {
1514             return "CommunicationDeviceInfo mCb=" + mCb.toString()
1515                     + " mUid=" + mUid
1516                     + " mDevice=[" + (mDevice != null ? mDevice.toString() : "null") + "]"
1517                     + " mOn=" + mOn
1518                     + " mScoAudioMode=" + mScoAudioMode
1519                     + " mIsPrivileged=" + mIsPrivileged
1520                     + " mEventSource=" + mEventSource
1521                     + " mWaitForStatus=" + mWaitForStatus
1522                     + " mStatus=" + mStatus;
1523         }
1524     }
1525 
1526     //---------------------------------------------------------------------
1527     // Method forwarding between the helper classes (BtHelper, AudioDeviceInventory)
1528     // only call from a "handle"* method or "on"* method
1529 
1530     // Handles request to override default use of A2DP for media.
1531     //@GuardedBy("mConnectedDevices")
setBluetoothA2dpOnInt(boolean on, boolean fromA2dp, String source)1532     /*package*/ void setBluetoothA2dpOnInt(boolean on, boolean fromA2dp, String source) {
1533         // for logging only
1534         final String eventSource = new StringBuilder("setBluetoothA2dpOn(").append(on)
1535                 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
1536                 .append(Binder.getCallingPid()).append(" src:").append(source).toString();
1537 
1538         synchronized (mDeviceStateLock) {
1539             mBluetoothA2dpEnabled = on;
1540             mBrokerHandler.removeMessages(MSG_IIL_SET_FORCE_BT_A2DP_USE);
1541             onSetForceUse(
1542                     AudioSystem.FOR_MEDIA,
1543                     mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP,
1544                     fromA2dp,
1545                     eventSource);
1546         }
1547     }
1548 
handleDeviceConnection(@onNull AudioDeviceAttributes attributes, boolean connect, @Nullable BluetoothDevice btDevice)1549     /*package*/ boolean handleDeviceConnection(@NonNull AudioDeviceAttributes attributes,
1550                                 boolean connect, @Nullable BluetoothDevice btDevice) {
1551         synchronized (mDeviceStateLock) {
1552             return mDeviceInventory.handleDeviceConnection(
1553                     attributes, connect, false /*for test*/, btDevice);
1554         }
1555     }
1556 
handleFailureToConnectToBtHeadsetService(int delay)1557     /*package*/ void handleFailureToConnectToBtHeadsetService(int delay) {
1558         sendMsg(MSG_BT_HEADSET_CNCT_FAILED, SENDMSG_REPLACE, delay);
1559     }
1560 
handleCancelFailureToConnectToBtHeadsetService()1561     /*package*/ void handleCancelFailureToConnectToBtHeadsetService() {
1562         mBrokerHandler.removeMessages(MSG_BT_HEADSET_CNCT_FAILED);
1563     }
1564 
postReportNewRoutes(boolean fromA2dp)1565     /*package*/ void postReportNewRoutes(boolean fromA2dp) {
1566         sendMsgNoDelay(fromA2dp ? MSG_REPORT_NEW_ROUTES_A2DP : MSG_REPORT_NEW_ROUTES, SENDMSG_NOOP);
1567     }
1568 
1569     // must be called synchronized on mConnectedDevices
hasScheduledA2dpConnection(BluetoothDevice btDevice)1570     /*package*/ boolean hasScheduledA2dpConnection(BluetoothDevice btDevice) {
1571         final BtDeviceInfo devInfoToCheck = new BtDeviceInfo(btDevice, BluetoothProfile.A2DP);
1572         return mBrokerHandler.hasEqualMessages(MSG_L_SET_BT_ACTIVE_DEVICE, devInfoToCheck);
1573     }
1574 
setA2dpTimeout(String address, int a2dpCodec, int delayMs)1575     /*package*/ void setA2dpTimeout(String address, int a2dpCodec, int delayMs) {
1576         sendILMsg(MSG_IL_BTA2DP_TIMEOUT, SENDMSG_QUEUE, a2dpCodec, address, delayMs);
1577     }
1578 
setLeAudioTimeout(String address, int device, int delayMs)1579     /*package*/ void setLeAudioTimeout(String address, int device, int delayMs) {
1580         sendILMsg(MSG_IL_BTLEAUDIO_TIMEOUT, SENDMSG_QUEUE, device, address, delayMs);
1581     }
1582 
setAvrcpAbsoluteVolumeSupported(boolean supported)1583     /*package*/ void setAvrcpAbsoluteVolumeSupported(boolean supported) {
1584         synchronized (mDeviceStateLock) {
1585             mBtHelper.setAvrcpAbsoluteVolumeSupported(supported);
1586         }
1587     }
1588 
clearAvrcpAbsoluteVolumeSupported()1589     /*package*/ void clearAvrcpAbsoluteVolumeSupported() {
1590         setAvrcpAbsoluteVolumeSupported(false);
1591         mAudioService.setAvrcpAbsoluteVolumeSupported(false);
1592     }
1593 
getBluetoothA2dpEnabled()1594     /*package*/ boolean getBluetoothA2dpEnabled() {
1595         synchronized (mDeviceStateLock) {
1596             return mBluetoothA2dpEnabled;
1597         }
1598     }
1599 
broadcastStickyIntentToCurrentProfileGroup(Intent intent)1600     /*package*/ void broadcastStickyIntentToCurrentProfileGroup(Intent intent) {
1601         mSystemServer.broadcastStickyIntentToCurrentProfileGroup(intent);
1602     }
1603 
dump(PrintWriter pw, String prefix)1604     /*package*/ void dump(PrintWriter pw, String prefix) {
1605         if (mBrokerHandler != null) {
1606             pw.println(prefix + "Message handler (watch for unhandled messages):");
1607             mBrokerHandler.dump(new PrintWriterPrinter(pw), prefix + "  ");
1608         } else {
1609             pw.println("Message handler is null");
1610         }
1611 
1612         mDeviceInventory.dump(pw, prefix);
1613 
1614         pw.println("\n" + prefix + "Communication route clients:");
1615         mCommunicationRouteClients.forEach((cl) -> {
1616             pw.println("  " + prefix + cl.toString()); });
1617 
1618         pw.println("\n" + prefix + "Computed Preferred communication device: "
1619                 +  preferredCommunicationDevice());
1620         pw.println("\n" + prefix + "Applied Preferred communication device: "
1621                 +  mPreferredCommunicationDevice);
1622         pw.println(prefix + "Active communication device: "
1623                 +  ((mActiveCommunicationDevice == null) ? "None"
1624                         : new AudioDeviceAttributes(mActiveCommunicationDevice)));
1625 
1626         pw.println(prefix + "mCommunicationStrategyId: "
1627                 +  mCommunicationStrategyId);
1628 
1629         pw.println(prefix + "mAccessibilityStrategyId: "
1630                 +  mAccessibilityStrategyId);
1631 
1632         pw.println("\n" + prefix + "mAudioModeOwner: " + mAudioModeOwner);
1633 
1634         mBtHelper.dump(pw, prefix);
1635     }
1636 
1637     //---------------------------------------------------------------------
1638     // Internal handling of messages
1639     // These methods are ALL synchronous, in response to message handling in BrokerHandler
1640     // Blocking in any of those will block the message queue
1641 
onSetForceUse(int useCase, int config, boolean fromA2dp, String eventSource)1642     private void onSetForceUse(int useCase, int config, boolean fromA2dp, String eventSource) {
1643         if (useCase == AudioSystem.FOR_MEDIA) {
1644             postReportNewRoutes(fromA2dp);
1645         }
1646         AudioService.sForceUseLogger.enqueue(
1647                 new AudioServiceEvents.ForceUseEvent(useCase, config, eventSource));
1648         new MediaMetrics.Item(MediaMetrics.Name.AUDIO_FORCE_USE + MediaMetrics.SEPARATOR
1649                 + AudioSystem.forceUseUsageToString(useCase))
1650                 .set(MediaMetrics.Property.EVENT, "onSetForceUse")
1651                 .set(MediaMetrics.Property.FORCE_USE_DUE_TO, eventSource)
1652                 .set(MediaMetrics.Property.FORCE_USE_MODE,
1653                         AudioSystem.forceUseConfigToString(config))
1654                 .record();
1655 
1656         if (AudioService.DEBUG_COMM_RTE) {
1657             Log.v(TAG, "onSetForceUse(useCase<" + useCase + ">, config<" + config + ">, fromA2dp<"
1658                     + fromA2dp + ">, eventSource<" + eventSource + ">)");
1659         }
1660         mAudioSystem.setForceUse(useCase, config);
1661     }
1662 
onSendBecomingNoisyIntent()1663     private void onSendBecomingNoisyIntent() {
1664         AudioService.sDeviceLogger.enqueue((new EventLogger.StringEvent(
1665                 "broadcast ACTION_AUDIO_BECOMING_NOISY")).printLog(TAG));
1666         mSystemServer.sendDeviceBecomingNoisyIntent();
1667     }
1668 
1669     //---------------------------------------------------------------------
1670     // Message handling
1671     private BrokerHandler mBrokerHandler;
1672     private BrokerThread mBrokerThread;
1673     private PowerManager.WakeLock mBrokerEventWakeLock;
1674 
setupMessaging(Context ctxt)1675     private void setupMessaging(Context ctxt) {
1676         final PowerManager pm = (PowerManager) ctxt.getSystemService(Context.POWER_SERVICE);
1677         mBrokerEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
1678                 "handleAudioDeviceEvent");
1679         mBrokerThread = new BrokerThread();
1680         mBrokerThread.start();
1681         waitForBrokerHandlerCreation();
1682     }
1683 
waitForBrokerHandlerCreation()1684     private void waitForBrokerHandlerCreation() {
1685         synchronized (this) {
1686             while (mBrokerHandler == null) {
1687                 try {
1688                     wait();
1689                 } catch (InterruptedException e) {
1690                     Log.e(TAG, "Interruption while waiting on BrokerHandler");
1691                 }
1692             }
1693         }
1694     }
1695 
1696     /** Class that handles the device broker's message queue */
1697     private class BrokerThread extends Thread {
BrokerThread()1698         BrokerThread() {
1699             super("AudioDeviceBroker");
1700         }
1701 
1702         @Override
run()1703         public void run() {
1704             // Set this thread up so the handler will work on it
1705             Looper.prepare();
1706 
1707             synchronized (AudioDeviceBroker.this) {
1708                 mBrokerHandler = new BrokerHandler();
1709 
1710                 // Notify that the handler has been created
1711                 AudioDeviceBroker.this.notify();
1712             }
1713 
1714             Looper.loop();
1715         }
1716     }
1717 
1718     /** Class that handles the message queue */
1719     private class BrokerHandler extends Handler {
1720 
1721         @Override
handleMessage(Message msg)1722         public void handleMessage(Message msg) {
1723             switch (msg.what) {
1724                 case MSG_RESTORE_DEVICES:
1725                     synchronized (mSetModeLock) {
1726                         synchronized (mDeviceStateLock) {
1727                             initRoutingStrategyIds();
1728                             updateActiveCommunicationDevice();
1729                             mDeviceInventory.onRestoreDevices();
1730                             mBtHelper.onAudioServerDiedRestoreA2dp();
1731                             updateCommunicationRoute("MSG_RESTORE_DEVICES");
1732                         }
1733                     }
1734                     break;
1735                 case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE:
1736                     synchronized (mDeviceStateLock) {
1737                         mDeviceInventory.onSetWiredDeviceConnectionState(
1738                                 (AudioDeviceInventory.WiredDeviceConnectionState) msg.obj);
1739                     }
1740                     break;
1741                 case MSG_I_BROADCAST_BT_CONNECTION_STATE:
1742                     synchronized (mDeviceStateLock) {
1743                         mBtHelper.onBroadcastScoConnectionState(msg.arg1);
1744                     }
1745                     break;
1746                 case MSG_IIL_SET_FORCE_USE: // intended fall-through
1747                 case MSG_IIL_SET_FORCE_BT_A2DP_USE:
1748                     onSetForceUse(msg.arg1, msg.arg2,
1749                                   (msg.what == MSG_IIL_SET_FORCE_BT_A2DP_USE), (String) msg.obj);
1750                     break;
1751                 case MSG_REPORT_NEW_ROUTES:
1752                 case MSG_REPORT_NEW_ROUTES_A2DP:
1753                     synchronized (mDeviceStateLock) {
1754                         mDeviceInventory.onReportNewRoutes();
1755                     }
1756                     break;
1757                 case MSG_L_SET_BT_ACTIVE_DEVICE:
1758                     synchronized (mSetModeLock) {
1759                         synchronized (mDeviceStateLock) {
1760                             final BtDeviceInfo btInfo = (BtDeviceInfo) msg.obj;
1761                             @AudioSystem.AudioFormatNativeEnumForBtCodec final int codec =
1762                                     mBtHelper.getA2dpCodecWithFallbackToSBC(
1763                                             btInfo.mDevice, "MSG_L_SET_BT_ACTIVE_DEVICE");
1764                             mDeviceInventory.onSetBtActiveDevice(btInfo, codec,
1765                                     (btInfo.mProfile
1766                                             != BluetoothProfile.LE_AUDIO || btInfo.mIsLeOutput)
1767                                             ? mAudioService.getBluetoothContextualVolumeStream()
1768                                             : AudioSystem.STREAM_DEFAULT);
1769                             if (btInfo.mProfile == BluetoothProfile.LE_AUDIO
1770                                     || btInfo.mProfile == BluetoothProfile.HEARING_AID) {
1771                                 onUpdateCommunicationRouteClient(isBluetoothScoRequested(),
1772                                         "setBluetoothActiveDevice");
1773                             }
1774                         }
1775                     }
1776                     break;
1777                 case MSG_BT_HEADSET_CNCT_FAILED:
1778                     synchronized (mSetModeLock) {
1779                         synchronized (mDeviceStateLock) {
1780                             mBtHelper.resetBluetoothSco();
1781                         }
1782                     }
1783                     break;
1784                 case MSG_IL_BTA2DP_TIMEOUT:
1785                     // msg.obj  == address of BTA2DP device
1786                     synchronized (mDeviceStateLock) {
1787                         mDeviceInventory.onMakeA2dpDeviceUnavailableNow((String) msg.obj, msg.arg1);
1788                     }
1789                     break;
1790                 case MSG_IL_BTLEAUDIO_TIMEOUT:
1791                     // msg.obj  == address of LE Audio device
1792                     synchronized (mDeviceStateLock) {
1793                         mDeviceInventory.onMakeLeAudioDeviceUnavailableNow(
1794                                 (String) msg.obj, msg.arg1);
1795                     }
1796                     break;
1797                 case MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE: {
1798                     final BtDeviceInfo btInfo = (BtDeviceInfo) msg.obj;
1799                     synchronized (mDeviceStateLock) {
1800                         @AudioSystem.AudioFormatNativeEnumForBtCodec final int codec =
1801                                 mBtHelper.getA2dpCodecWithFallbackToSBC(
1802                                         btInfo.mDevice, "MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE");
1803                         mDeviceInventory.onBluetoothDeviceConfigChange(
1804                                 btInfo, codec, BtHelper.EVENT_DEVICE_CONFIG_CHANGE);
1805                     }
1806                 } break;
1807                 case MSG_BROADCAST_AUDIO_BECOMING_NOISY:
1808                     onSendBecomingNoisyIntent();
1809                     break;
1810                 case MSG_II_SET_HEARING_AID_VOLUME:
1811                     synchronized (mDeviceStateLock) {
1812                         mBtHelper.setHearingAidVolume(msg.arg1, msg.arg2,
1813                                 mDeviceInventory.isHearingAidConnected());
1814                     }
1815                     break;
1816                 case MSG_II_SET_LE_AUDIO_OUT_VOLUME: {
1817                     final BleVolumeInfo info = (BleVolumeInfo) msg.obj;
1818                     synchronized (mDeviceStateLock) {
1819                         mBtHelper.setLeAudioVolume(info.mIndex, info.mMaxIndex, info.mStreamType);
1820                     }
1821                 } break;
1822                 case MSG_I_SET_AVRCP_ABSOLUTE_VOLUME:
1823                     synchronized (mDeviceStateLock) {
1824                         mBtHelper.setAvrcpAbsoluteVolumeIndex(msg.arg1);
1825                     }
1826                     break;
1827                 case MSG_I_SET_MODE_OWNER:
1828                     synchronized (mSetModeLock) {
1829                         synchronized (mDeviceStateLock) {
1830                             boolean wasBtScoRequested = isBluetoothScoRequested();
1831                             mAudioModeOwner = (AudioModeInfo) msg.obj;
1832                             if (mAudioModeOwner.mMode != AudioSystem.MODE_RINGTONE) {
1833                                 onUpdateCommunicationRouteClient(
1834                                         wasBtScoRequested, "setNewModeOwner");
1835                             }
1836                         }
1837                     }
1838                     break;
1839 
1840                 case MSG_L_SET_COMMUNICATION_DEVICE_FOR_CLIENT:
1841                     CommunicationDeviceInfo deviceInfo = (CommunicationDeviceInfo) msg.obj;
1842                     boolean status;
1843                     synchronized (mSetModeLock) {
1844                         synchronized (mDeviceStateLock) {
1845                             status = onSetCommunicationDeviceForClient(deviceInfo);
1846                         }
1847                     }
1848                     synchronized (deviceInfo) {
1849                         if (deviceInfo.mWaitForStatus) {
1850                             deviceInfo.mStatus = status;
1851                             deviceInfo.mWaitForStatus = false;
1852                             deviceInfo.notify();
1853                         }
1854                     }
1855                     break;
1856 
1857                 case MSG_IL_UPDATE_COMMUNICATION_ROUTE_CLIENT:
1858                     synchronized (mSetModeLock) {
1859                         synchronized (mDeviceStateLock) {
1860                             onUpdateCommunicationRouteClient(msg.arg1 == 1, (String) msg.obj);
1861                         }
1862                     }
1863                     break;
1864 
1865                 case MSG_L_COMMUNICATION_ROUTE_CLIENT_DIED:
1866                     synchronized (mSetModeLock) {
1867                         synchronized (mDeviceStateLock) {
1868                             onCommunicationRouteClientDied((CommunicationRouteClient) msg.obj);
1869                         }
1870                     }
1871                     break;
1872 
1873                 case MSG_L_RECEIVED_BT_EVENT:
1874                     synchronized (mSetModeLock) {
1875                         synchronized (mDeviceStateLock) {
1876                             onReceiveBtEvent((Intent) msg.obj);
1877                         }
1878                     }
1879                     break;
1880 
1881                 case MSG_TOGGLE_HDMI:
1882                     synchronized (mDeviceStateLock) {
1883                         mDeviceInventory.onToggleHdmi();
1884                     }
1885                     break;
1886                 case MSG_I_BT_SERVICE_DISCONNECTED_PROFILE:
1887                     synchronized (mSetModeLock) {
1888                         synchronized (mDeviceStateLock) {
1889                             mBtHelper.onBtProfileDisconnected(msg.arg1);
1890                             mDeviceInventory.onBtProfileDisconnected(msg.arg1);
1891                         }
1892                     }
1893                     break;
1894                 case MSG_IL_BT_SERVICE_CONNECTED_PROFILE:
1895                     synchronized (mSetModeLock) {
1896                         synchronized (mDeviceStateLock) {
1897                             mBtHelper.onBtProfileConnected(msg.arg1, (BluetoothProfile) msg.obj);
1898                         }
1899                     }
1900                     break;
1901                 case MSG_L_BT_ACTIVE_DEVICE_CHANGE_EXT: {
1902                     final BtDeviceInfo btInfo = (BtDeviceInfo) msg.obj;
1903                     if (btInfo.mDevice == null) break;
1904                     AudioService.sDeviceLogger.enqueue((new EventLogger.StringEvent(
1905                             "msg: onBluetoothActiveDeviceChange " + btInfo)).printLog(TAG));
1906                     synchronized (mDeviceStateLock) {
1907                         mDeviceInventory.setBluetoothActiveDevice(btInfo);
1908                     }
1909                 } break;
1910                 case MSG_IL_SAVE_PREF_DEVICES_FOR_STRATEGY: {
1911                     final int strategy = msg.arg1;
1912                     final List<AudioDeviceAttributes> devices =
1913                             (List<AudioDeviceAttributes>) msg.obj;
1914                     mDeviceInventory.onSaveSetPreferredDevices(strategy, devices);
1915                 } break;
1916                 case MSG_I_SAVE_REMOVE_PREF_DEVICES_FOR_STRATEGY: {
1917                     final int strategy = msg.arg1;
1918                     mDeviceInventory.onSaveRemovePreferredDevices(strategy);
1919                 } break;
1920                 case MSG_IL_SAVE_NDEF_DEVICE_FOR_STRATEGY: {
1921                     final int strategy = msg.arg1;
1922                     final AudioDeviceAttributes device = (AudioDeviceAttributes) msg.obj;
1923                     mDeviceInventory.onSaveSetDeviceAsNonDefault(strategy, device);
1924                 } break;
1925                 case MSG_IL_SAVE_REMOVE_NDEF_DEVICE_FOR_STRATEGY: {
1926                     final int strategy = msg.arg1;
1927                     final AudioDeviceAttributes device = (AudioDeviceAttributes) msg.obj;
1928                     mDeviceInventory.onSaveRemoveDeviceAsNonDefault(strategy, device);
1929                 } break;
1930                 case MSG_CHECK_MUTE_MUSIC:
1931                     checkMessagesMuteMusic(0);
1932                     break;
1933                 case MSG_IL_SAVE_PREF_DEVICES_FOR_CAPTURE_PRESET: {
1934                     final int capturePreset = msg.arg1;
1935                     final List<AudioDeviceAttributes> devices =
1936                             (List<AudioDeviceAttributes>) msg.obj;
1937                     mDeviceInventory.onSaveSetPreferredDevicesForCapturePreset(
1938                             capturePreset, devices);
1939                 } break;
1940                 case MSG_I_SAVE_CLEAR_PREF_DEVICES_FOR_CAPTURE_PRESET: {
1941                     final int capturePreset = msg.arg1;
1942                     mDeviceInventory.onSaveClearPreferredDevicesForCapturePreset(capturePreset);
1943                 } break;
1944                 case MSG_L_NOTIFY_PREFERRED_AUDIOPROFILE_APPLIED: {
1945                     final BluetoothDevice btDevice = (BluetoothDevice) msg.obj;
1946                     BtHelper.onNotifyPreferredAudioProfileApplied(btDevice);
1947                 } break;
1948 
1949                 case MSG_L_CHECK_COMMUNICATION_DEVICE_REMOVAL: {
1950                     synchronized (mSetModeLock) {
1951                         synchronized (mDeviceStateLock) {
1952                             onCheckCommunicationDeviceRemoval((AudioDeviceAttributes) msg.obj);
1953                         }
1954                     }
1955                 } break;
1956 
1957                 case MSG_PERSIST_AUDIO_DEVICE_SETTINGS:
1958                     onPersistAudioDeviceSettings();
1959                     break;
1960 
1961                 case MSG_CHECK_COMMUNICATION_ROUTE_CLIENT_STATE: {
1962                     synchronized (mDeviceStateLock) {
1963                         onCheckCommunicationRouteClientState(msg.arg1, msg.arg2 == 1);
1964                     }
1965                 } break;
1966                 default:
1967                     Log.wtf(TAG, "Invalid message " + msg.what);
1968             }
1969 
1970             // Give some time to Bluetooth service to post a connection message
1971             // in case of active device switch
1972             if (MESSAGES_MUTE_MUSIC.contains(msg.what)) {
1973                 sendMsg(MSG_CHECK_MUTE_MUSIC, SENDMSG_REPLACE, BTA2DP_MUTE_CHECK_DELAY_MS);
1974             }
1975 
1976             if (isMessageHandledUnderWakelock(msg.what)) {
1977                 try {
1978                     mBrokerEventWakeLock.release();
1979                 } catch (Exception e) {
1980                     Log.e(TAG, "Exception releasing wakelock", e);
1981                 }
1982             }
1983         }
1984     }
1985 
1986     // List of all messages. If a message has be handled under wakelock, add it to
1987     //    the isMessageHandledUnderWakelock(int) method
1988     // Naming of msg indicates arguments, using JNI argument grammar
1989     // (e.g. II indicates two int args, IL indicates int and Obj arg)
1990     private static final int MSG_RESTORE_DEVICES = 1;
1991     private static final int MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE = 2;
1992     private static final int MSG_I_BROADCAST_BT_CONNECTION_STATE = 3;
1993     private static final int MSG_IIL_SET_FORCE_USE = 4;
1994     private static final int MSG_IIL_SET_FORCE_BT_A2DP_USE = 5;
1995     private static final int MSG_TOGGLE_HDMI = 6;
1996     private static final int MSG_L_SET_BT_ACTIVE_DEVICE = 7;
1997     private static final int MSG_BT_HEADSET_CNCT_FAILED = 9;
1998     private static final int MSG_IL_BTA2DP_TIMEOUT = 10;
1999 
2000     // process change of A2DP device configuration, obj is BluetoothDevice
2001     private static final int MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE = 11;
2002 
2003     private static final int MSG_BROADCAST_AUDIO_BECOMING_NOISY = 12;
2004     private static final int MSG_REPORT_NEW_ROUTES = 13;
2005     private static final int MSG_II_SET_HEARING_AID_VOLUME = 14;
2006     private static final int MSG_I_SET_AVRCP_ABSOLUTE_VOLUME = 15;
2007     private static final int MSG_I_SET_MODE_OWNER = 16;
2008 
2009     private static final int MSG_I_BT_SERVICE_DISCONNECTED_PROFILE = 22;
2010     private static final int MSG_IL_BT_SERVICE_CONNECTED_PROFILE = 23;
2011 
2012     // process external command to (dis)connect an A2DP device, obj is BtDeviceConnectionInfo
2013     private static final int MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT = 29;
2014 
2015     // process external command to (dis)connect a hearing aid device
2016     private static final int MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT = 31;
2017 
2018     private static final int MSG_IL_SAVE_PREF_DEVICES_FOR_STRATEGY = 32;
2019     private static final int MSG_I_SAVE_REMOVE_PREF_DEVICES_FOR_STRATEGY = 33;
2020 
2021     private static final int MSG_L_COMMUNICATION_ROUTE_CLIENT_DIED = 34;
2022     private static final int MSG_CHECK_MUTE_MUSIC = 35;
2023     private static final int MSG_REPORT_NEW_ROUTES_A2DP = 36;
2024 
2025     private static final int MSG_IL_SAVE_PREF_DEVICES_FOR_CAPTURE_PRESET = 37;
2026     private static final int MSG_I_SAVE_CLEAR_PREF_DEVICES_FOR_CAPTURE_PRESET = 38;
2027 
2028     private static final int MSG_L_SET_COMMUNICATION_DEVICE_FOR_CLIENT = 42;
2029     private static final int MSG_IL_UPDATE_COMMUNICATION_ROUTE_CLIENT = 43;
2030 
2031     private static final int MSG_L_BT_ACTIVE_DEVICE_CHANGE_EXT = 45;
2032     //
2033     // process set volume for Le Audio, obj is BleVolumeInfo
2034     private static final int MSG_II_SET_LE_AUDIO_OUT_VOLUME = 46;
2035 
2036     private static final int MSG_IL_SAVE_NDEF_DEVICE_FOR_STRATEGY = 47;
2037     private static final int MSG_IL_SAVE_REMOVE_NDEF_DEVICE_FOR_STRATEGY = 48;
2038     private static final int MSG_IL_BTLEAUDIO_TIMEOUT = 49;
2039 
2040     private static final int MSG_L_NOTIFY_PREFERRED_AUDIOPROFILE_APPLIED = 52;
2041     private static final int MSG_L_CHECK_COMMUNICATION_DEVICE_REMOVAL = 53;
2042 
2043     private static final int MSG_PERSIST_AUDIO_DEVICE_SETTINGS = 54;
2044 
2045     private static final int MSG_L_RECEIVED_BT_EVENT = 55;
2046 
2047     private static final int MSG_CHECK_COMMUNICATION_ROUTE_CLIENT_STATE = 56;
2048 
isMessageHandledUnderWakelock(int msgId)2049     private static boolean isMessageHandledUnderWakelock(int msgId) {
2050         switch(msgId) {
2051             case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE:
2052             case MSG_L_SET_BT_ACTIVE_DEVICE:
2053             case MSG_IL_BTA2DP_TIMEOUT:
2054             case MSG_IL_BTLEAUDIO_TIMEOUT:
2055             case MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE:
2056             case MSG_TOGGLE_HDMI:
2057             case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT:
2058             case MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT:
2059             case MSG_CHECK_MUTE_MUSIC:
2060                 return true;
2061             default:
2062                 return false;
2063         }
2064     }
2065 
2066     // Message helper methods
2067 
2068     // sendMsg() flags
2069     /** If the msg is already queued, replace it with this one. */
2070     private static final int SENDMSG_REPLACE = 0;
2071     /** If the msg is already queued, ignore this one and leave the old. */
2072     private static final int SENDMSG_NOOP = 1;
2073     /** If the msg is already queued, queue this one and leave the old. */
2074     private static final int SENDMSG_QUEUE = 2;
2075 
sendMsg(int msg, int existingMsgPolicy, int delay)2076     private void sendMsg(int msg, int existingMsgPolicy, int delay) {
2077         sendIILMsg(msg, existingMsgPolicy, 0, 0, null, delay);
2078     }
2079 
sendILMsg(int msg, int existingMsgPolicy, int arg, Object obj, int delay)2080     private void sendILMsg(int msg, int existingMsgPolicy, int arg, Object obj, int delay) {
2081         sendIILMsg(msg, existingMsgPolicy, arg, 0, obj, delay);
2082     }
2083 
sendLMsg(int msg, int existingMsgPolicy, Object obj, int delay)2084     private void sendLMsg(int msg, int existingMsgPolicy, Object obj, int delay) {
2085         sendIILMsg(msg, existingMsgPolicy, 0, 0, obj, delay);
2086     }
2087 
sendIMsg(int msg, int existingMsgPolicy, int arg, int delay)2088     private void sendIMsg(int msg, int existingMsgPolicy, int arg, int delay) {
2089         sendIILMsg(msg, existingMsgPolicy, arg, 0, null, delay);
2090     }
2091 
sendMsgNoDelay(int msg, int existingMsgPolicy)2092     private void sendMsgNoDelay(int msg, int existingMsgPolicy) {
2093         sendIILMsg(msg, existingMsgPolicy, 0, 0, null, 0);
2094     }
2095 
sendIMsgNoDelay(int msg, int existingMsgPolicy, int arg)2096     private void sendIMsgNoDelay(int msg, int existingMsgPolicy, int arg) {
2097         sendIILMsg(msg, existingMsgPolicy, arg, 0, null, 0);
2098     }
2099 
sendIIMsgNoDelay(int msg, int existingMsgPolicy, int arg1, int arg2)2100     private void sendIIMsgNoDelay(int msg, int existingMsgPolicy, int arg1, int arg2) {
2101         sendIILMsg(msg, existingMsgPolicy, arg1, arg2, null, 0);
2102     }
2103 
sendILMsgNoDelay(int msg, int existingMsgPolicy, int arg, Object obj)2104     private void sendILMsgNoDelay(int msg, int existingMsgPolicy, int arg, Object obj) {
2105         sendIILMsg(msg, existingMsgPolicy, arg, 0, obj, 0);
2106     }
2107 
sendLMsgNoDelay(int msg, int existingMsgPolicy, Object obj)2108     private void sendLMsgNoDelay(int msg, int existingMsgPolicy, Object obj) {
2109         sendIILMsg(msg, existingMsgPolicy, 0, 0, obj, 0);
2110     }
2111 
sendIILMsgNoDelay(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj)2112     private void sendIILMsgNoDelay(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj) {
2113         sendIILMsg(msg, existingMsgPolicy, arg1, arg2, obj, 0);
2114     }
2115 
sendIILMsg(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj, int delay)2116     private void sendIILMsg(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj,
2117                             int delay) {
2118         if (existingMsgPolicy == SENDMSG_REPLACE) {
2119             mBrokerHandler.removeMessages(msg);
2120         } else if (existingMsgPolicy == SENDMSG_NOOP && mBrokerHandler.hasMessages(msg)) {
2121             return;
2122         }
2123 
2124         if (isMessageHandledUnderWakelock(msg)) {
2125             final long identity = Binder.clearCallingIdentity();
2126             try {
2127                 mBrokerEventWakeLock.acquire(BROKER_WAKELOCK_TIMEOUT_MS);
2128             } catch (Exception e) {
2129                 Log.e(TAG, "Exception acquiring wakelock", e);
2130             } finally {
2131                 Binder.restoreCallingIdentity(identity);
2132             }
2133         }
2134 
2135         if (MESSAGES_MUTE_MUSIC.contains(msg)) {
2136             checkMessagesMuteMusic(msg);
2137         }
2138 
2139         synchronized (sLastDeviceConnectionMsgTimeLock) {
2140             long time = SystemClock.uptimeMillis() + delay;
2141 
2142             switch (msg) {
2143                 case MSG_L_SET_BT_ACTIVE_DEVICE:
2144                 case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE:
2145                 case MSG_IL_BTA2DP_TIMEOUT:
2146                 case MSG_IL_BTLEAUDIO_TIMEOUT:
2147                 case MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE:
2148                     if (sLastDeviceConnectMsgTime >= time) {
2149                         // add a little delay to make sure messages are ordered as expected
2150                         time = sLastDeviceConnectMsgTime + 30;
2151                     }
2152                     sLastDeviceConnectMsgTime = time;
2153                     break;
2154                 default:
2155                     break;
2156             }
2157             mBrokerHandler.sendMessageAtTime(mBrokerHandler.obtainMessage(msg, arg1, arg2, obj),
2158                     time);
2159         }
2160     }
2161 
removeMsgForCheckClientState(int uid)2162     private void removeMsgForCheckClientState(int uid) {
2163         CommunicationRouteClient crc = getCommunicationRouteClientForUid(uid);
2164         if (crc != null) {
2165             mBrokerHandler.removeEqualMessages(MSG_CHECK_COMMUNICATION_ROUTE_CLIENT_STATE, crc);
2166         }
2167     }
2168 
sendMsgForCheckClientState(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj, int delay)2169     private void sendMsgForCheckClientState(int msg, int existingMsgPolicy,
2170                                             int arg1, int arg2, Object obj, int delay) {
2171         if ((existingMsgPolicy == SENDMSG_REPLACE) && (obj != null)) {
2172             mBrokerHandler.removeEqualMessages(msg, obj);
2173         }
2174 
2175         long time = SystemClock.uptimeMillis() + delay;
2176         mBrokerHandler.sendMessageAtTime(mBrokerHandler.obtainMessage(msg, arg1, arg2, obj), time);
2177     }
2178 
2179     /** List of messages for which music is muted while processing is pending */
2180     private static final Set<Integer> MESSAGES_MUTE_MUSIC;
2181     static {
2182         MESSAGES_MUTE_MUSIC = new HashSet<>();
2183         MESSAGES_MUTE_MUSIC.add(MSG_L_SET_BT_ACTIVE_DEVICE);
2184         MESSAGES_MUTE_MUSIC.add(MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE);
2185         MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT);
2186         MESSAGES_MUTE_MUSIC.add(MSG_IIL_SET_FORCE_BT_A2DP_USE);
2187     }
2188 
2189     private AtomicBoolean mMusicMuted = new AtomicBoolean(false);
2190 
hasIntersection(Set<T> a, Set<T> b)2191     private static <T> boolean hasIntersection(Set<T> a, Set<T> b) {
2192         for (T e : a) {
2193             if (b.contains(e)) return true;
2194         }
2195         return false;
2196     }
2197 
messageMutesMusic(int message)2198     boolean messageMutesMusic(int message) {
2199         if (message == 0) {
2200             return false;
2201         }
2202         // Do not mute on bluetooth event if music is playing on a wired headset.
2203         if ((message == MSG_L_SET_BT_ACTIVE_DEVICE
2204                 || message == MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT
2205                 || message == MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE)
2206                 && AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0)
2207                 && hasIntersection(mDeviceInventory.DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET,
2208                         mAudioService.getDeviceSetForStream(AudioSystem.STREAM_MUSIC))) {
2209             return false;
2210         }
2211         return true;
2212     }
2213 
2214     /** Mutes or unmutes music according to pending A2DP messages */
checkMessagesMuteMusic(int message)2215     private void checkMessagesMuteMusic(int message) {
2216         boolean mute = messageMutesMusic(message);
2217         if (!mute) {
2218             for (int msg : MESSAGES_MUTE_MUSIC) {
2219                 if (mBrokerHandler.hasMessages(msg)) {
2220                     if (messageMutesMusic(msg)) {
2221                         mute = true;
2222                         break;
2223                     }
2224                 }
2225             }
2226         }
2227 
2228         if (mute != mMusicMuted.getAndSet(mute)) {
2229             mAudioService.setMusicMute(mute);
2230         }
2231     }
2232 
2233     // List of applications requesting a specific route for communication.
2234     @GuardedBy("mDeviceStateLock")
2235     private final @NonNull LinkedList<CommunicationRouteClient> mCommunicationRouteClients =
2236             new LinkedList<CommunicationRouteClient>();
2237 
2238     private class CommunicationRouteClient implements IBinder.DeathRecipient {
2239         private final IBinder mCb;
2240         private final int mUid;
2241         private final boolean mIsPrivileged;
2242         private AudioDeviceAttributes mDevice;
2243         private boolean mPlaybackActive;
2244         private boolean mRecordingActive;
2245 
CommunicationRouteClient(IBinder cb, int uid, AudioDeviceAttributes device, boolean isPrivileged)2246         CommunicationRouteClient(IBinder cb, int uid, AudioDeviceAttributes device,
2247                                  boolean isPrivileged) {
2248             mCb = cb;
2249             mUid = uid;
2250             mDevice = device;
2251             mIsPrivileged = isPrivileged;
2252             mPlaybackActive = mAudioService.isPlaybackActiveForUid(uid);
2253             mRecordingActive = mAudioService.isRecordingActiveForUid(uid);
2254         }
2255 
registerDeathRecipient()2256         public boolean registerDeathRecipient() {
2257             boolean status = false;
2258             try {
2259                 mCb.linkToDeath(this, 0);
2260                 status = true;
2261             } catch (RemoteException e) {
2262                 Log.w(TAG, "CommunicationRouteClient could not link to " + mCb + " binder death");
2263             }
2264             return status;
2265         }
2266 
unregisterDeathRecipient()2267         public void unregisterDeathRecipient() {
2268             try {
2269                 mCb.unlinkToDeath(this, 0);
2270             } catch (NoSuchElementException e) {
2271                 Log.w(TAG, "CommunicationRouteClient could not not unregistered to binder");
2272             }
2273         }
2274 
2275         @Override
binderDied()2276         public void binderDied() {
2277             postCommunicationRouteClientDied(this);
2278         }
2279 
getBinder()2280         IBinder getBinder() {
2281             return mCb;
2282         }
2283 
getUid()2284         int getUid() {
2285             return mUid;
2286         }
2287 
isPrivileged()2288         boolean isPrivileged() {
2289             return mIsPrivileged;
2290         }
2291 
getDevice()2292         AudioDeviceAttributes getDevice() {
2293             return mDevice;
2294         }
2295 
setPlaybackActive(boolean active)2296         public void setPlaybackActive(boolean active) {
2297             mPlaybackActive = active;
2298         }
2299 
setRecordingActive(boolean active)2300         public void setRecordingActive(boolean active) {
2301             mRecordingActive = active;
2302         }
2303 
isActive()2304         public boolean isActive() {
2305             return mIsPrivileged || mRecordingActive || mPlaybackActive;
2306         }
2307 
2308         @Override
toString()2309         public String toString() {
2310             return "[CommunicationRouteClient: mUid: " + mUid
2311                     + " mDevice: " + mDevice.toString()
2312                     + " mIsPrivileged: " + mIsPrivileged
2313                     + " mPlaybackActive: " + mPlaybackActive
2314                     + " mRecordingActive: " + mRecordingActive + "]";
2315         }
2316     }
2317 
2318     // @GuardedBy("mSetModeLock")
2319     @GuardedBy("mDeviceStateLock")
onCommunicationRouteClientDied(CommunicationRouteClient client)2320     private void onCommunicationRouteClientDied(CommunicationRouteClient client) {
2321         if (client == null) {
2322             return;
2323         }
2324         Log.w(TAG, "Communication client died");
2325         setCommunicationRouteForClient(client.getBinder(), client.getUid(), null,
2326                 BtHelper.SCO_MODE_UNDEFINED, client.isPrivileged(),
2327                 "onCommunicationRouteClientDied");
2328     }
2329 
2330     /**
2331      * Determines which preferred device for phone strategy should be sent to audio policy manager
2332      * as a function of current SCO audio activation state and active communication route requests.
2333      * SCO audio state has the highest priority as it can result from external activation by
2334      * telephony service.
2335      * @return selected forced usage for communication.
2336      */
2337     @GuardedBy("mDeviceStateLock")
preferredCommunicationDevice()2338     @Nullable private AudioDeviceAttributes preferredCommunicationDevice() {
2339         boolean btSCoOn = mBtHelper.isBluetoothScoOn();
2340         synchronized (mBluetoothAudioStateLock) {
2341             btSCoOn = btSCoOn && mBluetoothScoOn;
2342         }
2343 
2344         if (btSCoOn) {
2345             // Use the SCO device known to BtHelper so that it matches exactly
2346             // what has been communicated to audio policy manager. The device
2347             // returned by requestedCommunicationDevice() can be a dummy SCO device if legacy
2348             // APIs are used to start SCO audio.
2349             AudioDeviceAttributes device = mBtHelper.getHeadsetAudioDevice();
2350             if (device != null) {
2351                 return device;
2352             }
2353         }
2354         AudioDeviceAttributes device = requestedCommunicationDevice();
2355         if (device == null || device.getType() == AudioDeviceInfo.TYPE_BLUETOOTH_SCO) {
2356             // Do not indicate BT SCO selection if SCO is requested but SCO is not ON
2357             return null;
2358         }
2359         return device;
2360     }
2361 
2362     /**
2363      * Configures audio policy manager and audio HAL according to active communication route.
2364      * Always called from message Handler.
2365      */
2366     // @GuardedBy("mSetModeLock")
2367     @GuardedBy("mDeviceStateLock")
updateCommunicationRoute(String eventSource)2368     private void updateCommunicationRoute(String eventSource) {
2369         AudioDeviceAttributes preferredCommunicationDevice = preferredCommunicationDevice();
2370         if (AudioService.DEBUG_COMM_RTE) {
2371             Log.v(TAG, "updateCommunicationRoute, preferredCommunicationDevice: "
2372                     + preferredCommunicationDevice + " eventSource: " + eventSource);
2373         }
2374         AudioService.sDeviceLogger.enqueue((new EventLogger.StringEvent(
2375                 "updateCommunicationRoute, preferredCommunicationDevice: "
2376                 + preferredCommunicationDevice + " eventSource: " + eventSource)));
2377 
2378         if (preferredCommunicationDevice == null) {
2379             AudioDeviceAttributes defaultDevice = getDefaultCommunicationDevice();
2380             if (defaultDevice != null) {
2381                 mDeviceInventory.setPreferredDevicesForStrategyInt(
2382                         mCommunicationStrategyId, Arrays.asList(defaultDevice));
2383                 mDeviceInventory.setPreferredDevicesForStrategyInt(
2384                         mAccessibilityStrategyId, Arrays.asList(defaultDevice));
2385             } else {
2386                 mDeviceInventory.removePreferredDevicesForStrategyInt(mCommunicationStrategyId);
2387                 mDeviceInventory.removePreferredDevicesForStrategyInt(mAccessibilityStrategyId);
2388             }
2389             mDeviceInventory.applyConnectedDevicesRoles();
2390             mDeviceInventory.reapplyExternalDevicesRoles();
2391         } else {
2392             mDeviceInventory.setPreferredDevicesForStrategyInt(
2393                     mCommunicationStrategyId, Arrays.asList(preferredCommunicationDevice));
2394             mDeviceInventory.setPreferredDevicesForStrategyInt(
2395                     mAccessibilityStrategyId, Arrays.asList(preferredCommunicationDevice));
2396         }
2397         onUpdatePhoneStrategyDevice(preferredCommunicationDevice);
2398     }
2399 
2400     /**
2401      * Select new communication device from communication route client at the top of the stack
2402      * and restore communication route including restarting SCO audio if needed.
2403      */
2404     // @GuardedBy("mSetModeLock")
2405     @GuardedBy("mDeviceStateLock")
onUpdateCommunicationRouteClient(boolean wasBtScoRequested, String eventSource)2406     private void onUpdateCommunicationRouteClient(boolean wasBtScoRequested, String eventSource) {
2407         CommunicationRouteClient crc = topCommunicationRouteClient();
2408         if (AudioService.DEBUG_COMM_RTE) {
2409             Log.v(TAG, "onUpdateCommunicationRouteClient, crc: " + crc
2410                     + " wasBtScoRequested: " + wasBtScoRequested + " eventSource: " + eventSource);
2411         }
2412         if (crc != null) {
2413             setCommunicationRouteForClient(crc.getBinder(), crc.getUid(), crc.getDevice(),
2414                     BtHelper.SCO_MODE_UNDEFINED, crc.isPrivileged(), eventSource);
2415         } else {
2416             if (!isBluetoothScoRequested() && wasBtScoRequested) {
2417                 mBtHelper.stopBluetoothSco(eventSource);
2418             }
2419             updateCommunicationRoute(eventSource);
2420         }
2421     }
2422 
2423     // @GuardedBy("mSetModeLock")
2424     @GuardedBy("mDeviceStateLock")
onUpdatePhoneStrategyDevice(AudioDeviceAttributes device)2425     private void onUpdatePhoneStrategyDevice(AudioDeviceAttributes device) {
2426         boolean wasSpeakerphoneActive = isSpeakerphoneActive();
2427         mPreferredCommunicationDevice = device;
2428         updateActiveCommunicationDevice();
2429         if (wasSpeakerphoneActive != isSpeakerphoneActive()) {
2430             try {
2431                 mContext.sendBroadcastAsUser(
2432                         new Intent(AudioManager.ACTION_SPEAKERPHONE_STATE_CHANGED)
2433                                 .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY),
2434                                           UserHandle.ALL);
2435             } catch (Exception e) {
2436                 Log.w(TAG, "failed to broadcast ACTION_SPEAKERPHONE_STATE_CHANGED: " + e);
2437             }
2438         }
2439         mAudioService.postUpdateRingerModeServiceInt();
2440         dispatchCommunicationDevice();
2441     }
2442 
2443     @GuardedBy("mDeviceStateLock")
removeCommunicationRouteClient( IBinder cb, boolean unregister)2444     private CommunicationRouteClient removeCommunicationRouteClient(
2445                     IBinder cb, boolean unregister) {
2446         for (CommunicationRouteClient cl : mCommunicationRouteClients) {
2447             if (cl.getBinder() == cb) {
2448                 if (unregister) {
2449                     cl.unregisterDeathRecipient();
2450                 }
2451                 removeMsgForCheckClientState(cl.getUid());
2452                 mCommunicationRouteClients.remove(cl);
2453                 return cl;
2454             }
2455         }
2456         return null;
2457     }
2458 
2459     @GuardedBy("mDeviceStateLock")
addCommunicationRouteClient(IBinder cb, int uid, AudioDeviceAttributes device, boolean isPrivileged)2460     private CommunicationRouteClient addCommunicationRouteClient(IBinder cb, int uid,
2461                 AudioDeviceAttributes device, boolean isPrivileged) {
2462         // always insert new request at first position
2463         removeCommunicationRouteClient(cb, true);
2464         CommunicationRouteClient client =
2465                 new CommunicationRouteClient(cb, uid, device, isPrivileged);
2466         if (client.registerDeathRecipient()) {
2467             mCommunicationRouteClients.add(0, client);
2468             if (!client.isActive()) {
2469                 // initialize the inactive client's state as active and check it after 6 seconds
2470                 setForceCommunicationClientStateAndDelayedCheck(
2471                         client,
2472                         !mAudioService.isPlaybackActiveForUid(client.getUid()),
2473                         !mAudioService.isRecordingActiveForUid(client.getUid()));
2474             }
2475             return client;
2476         }
2477         return null;
2478     }
2479 
2480     @GuardedBy("mDeviceStateLock")
getCommunicationRouteClientForUid(int uid)2481     private CommunicationRouteClient getCommunicationRouteClientForUid(int uid) {
2482         for (CommunicationRouteClient cl : mCommunicationRouteClients) {
2483             if (cl.getUid() == uid) {
2484                 return cl;
2485             }
2486         }
2487         return null;
2488     }
2489 
2490     @GuardedBy("mDeviceStateLock")
2491     // LE Audio: For system server (Telecom) and APKs targeting S and above, we let the audio
2492     // policy routing rules select the default communication device.
2493     // For older APKs, we force LE Audio headset when connected as those APKs cannot select a LE
2494     // Audiodevice explicitly.
communnicationDeviceLeAudioCompatOn()2495     private boolean communnicationDeviceLeAudioCompatOn() {
2496         return mAudioModeOwner.mMode == AudioSystem.MODE_IN_COMMUNICATION
2497                 && !(CompatChanges.isChangeEnabled(
2498                         USE_SET_COMMUNICATION_DEVICE, mAudioModeOwner.mUid)
2499                      || mAudioModeOwner.mUid == android.os.Process.SYSTEM_UID);
2500     }
2501 
2502     @GuardedBy("mDeviceStateLock")
2503     // Hearing Aid: For system server (Telecom) and IN_CALL mode we let the audio
2504     // policy routing rules select the default communication device.
2505     // For 3p apps and IN_COMMUNICATION mode we force Hearing aid when connected to maintain
2506     // backwards compatibility
communnicationDeviceHaCompatOn()2507     private boolean communnicationDeviceHaCompatOn() {
2508         return mAudioModeOwner.mMode == AudioSystem.MODE_IN_COMMUNICATION
2509                 && !(mAudioModeOwner.mUid == android.os.Process.SYSTEM_UID);
2510     }
2511 
2512     @GuardedBy("mDeviceStateLock")
getDefaultCommunicationDevice()2513     AudioDeviceAttributes getDefaultCommunicationDevice() {
2514         AudioDeviceAttributes device = null;
2515         // If both LE and Hearing Aid are active (thie should not happen),
2516         // priority to Hearing Aid.
2517         if (communnicationDeviceHaCompatOn()) {
2518             device = mDeviceInventory.getDeviceOfType(AudioSystem.DEVICE_OUT_HEARING_AID);
2519         }
2520         if (device == null && communnicationDeviceLeAudioCompatOn()) {
2521             device = mDeviceInventory.getDeviceOfType(AudioSystem.DEVICE_OUT_BLE_HEADSET);
2522         }
2523         return device;
2524     }
2525 
updateCommunicationRouteClientsActivity( List<AudioPlaybackConfiguration> playbackConfigs, List<AudioRecordingConfiguration> recordConfigs)2526     void updateCommunicationRouteClientsActivity(
2527             List<AudioPlaybackConfiguration> playbackConfigs,
2528             List<AudioRecordingConfiguration> recordConfigs) {
2529         synchronized (mSetModeLock) {
2530             synchronized (mDeviceStateLock) {
2531                 for (CommunicationRouteClient crc : mCommunicationRouteClients) {
2532                     boolean wasActive = crc.isActive();
2533                     boolean updateClientState = false;
2534                     if (playbackConfigs != null) {
2535                         crc.setPlaybackActive(false);
2536                         for (AudioPlaybackConfiguration config : playbackConfigs) {
2537                             if (config.getClientUid() == crc.getUid()
2538                                     && config.isActive()) {
2539                                 crc.setPlaybackActive(true);
2540                                 updateClientState = true;
2541                                 break;
2542                             }
2543                         }
2544                     }
2545                     if (recordConfigs != null) {
2546                         crc.setRecordingActive(false);
2547                         for (AudioRecordingConfiguration config : recordConfigs) {
2548                             if (config.getClientUid() == crc.getUid()
2549                                     && !config.isClientSilenced()) {
2550                                 crc.setRecordingActive(true);
2551                                 updateClientState = true;
2552                                 break;
2553                             }
2554                         }
2555                     }
2556                     if (updateClientState) {
2557                         removeMsgForCheckClientState(crc.getUid());
2558                         updateCommunicationRouteClientState(crc, wasActive);
2559                     } else {
2560                         if (wasActive) {
2561                             setForceCommunicationClientStateAndDelayedCheck(
2562                                     crc,
2563                                     playbackConfigs != null /* forcePlaybackActive */,
2564                                     recordConfigs != null /* forceRecordingActive */);
2565                         }
2566                     }
2567                 }
2568             }
2569         }
2570     }
2571 
getDeviceSensorUuid(AudioDeviceAttributes device)2572     @Nullable UUID getDeviceSensorUuid(AudioDeviceAttributes device) {
2573         synchronized (mDeviceStateLock) {
2574             return mDeviceInventory.getDeviceSensorUuid(device);
2575         }
2576     }
2577 
dispatchPreferredMixerAttributesChangedCausedByDeviceRemoved(AudioDeviceInfo info)2578     void dispatchPreferredMixerAttributesChangedCausedByDeviceRemoved(AudioDeviceInfo info) {
2579         // Currently, only media usage will be allowed to set preferred mixer attributes
2580         mAudioService.dispatchPreferredMixerAttributesChanged(
2581                 new AudioAttributes.Builder()
2582                         .setUsage(AudioAttributes.USAGE_MEDIA).build(),
2583                 info.getId(),
2584                 null /*mixerAttributes*/);
2585     }
2586 
2587     /**
2588      * post a message to persist the audio device settings.
2589      * Message is delayed by 1s on purpose in case of successive changes in quick succession (at
2590      * init time for instance)
2591      * Note this method is made public to work around a Mockito bug where it needs to be public
2592      * in order to be mocked by a test a the same package
2593      * (see https://code.google.com/archive/p/mockito/issues/127)
2594      */
persistAudioDeviceSettings()2595     public void persistAudioDeviceSettings() {
2596         sendMsg(MSG_PERSIST_AUDIO_DEVICE_SETTINGS, SENDMSG_REPLACE, /*delay*/ 1000);
2597     }
2598 
onPersistAudioDeviceSettings()2599     void onPersistAudioDeviceSettings() {
2600         final String deviceSettings = mDeviceInventory.getDeviceSettings();
2601         Log.v(TAG, "saving AdiDeviceState: " + deviceSettings);
2602         final SettingsAdapter settings = mAudioService.getSettings();
2603         boolean res = settings.putSecureStringForUser(mAudioService.getContentResolver(),
2604                 Settings.Secure.AUDIO_DEVICE_INVENTORY,
2605                 deviceSettings, UserHandle.USER_CURRENT);
2606         if (!res) {
2607             Log.e(TAG, "error saving AdiDeviceState: " + deviceSettings);
2608         }
2609     }
2610 
onReadAudioDeviceSettings()2611     void onReadAudioDeviceSettings() {
2612         final SettingsAdapter settingsAdapter = mAudioService.getSettings();
2613         final ContentResolver contentResolver = mAudioService.getContentResolver();
2614         String settings = settingsAdapter.getSecureStringForUser(contentResolver,
2615                 Settings.Secure.AUDIO_DEVICE_INVENTORY, UserHandle.USER_CURRENT);
2616         if (settings == null) {
2617             Log.i(TAG, "reading AdiDeviceState from legacy key"
2618                     + Settings.Secure.SPATIAL_AUDIO_ENABLED);
2619             // legacy string format for key SPATIAL_AUDIO_ENABLED has the same order of fields like
2620             // the strings for key AUDIO_DEVICE_INVENTORY. This will ensure to construct valid
2621             // device settings when calling {@link #setDeviceSettings()}
2622             settings = settingsAdapter.getSecureStringForUser(contentResolver,
2623                     Settings.Secure.SPATIAL_AUDIO_ENABLED, UserHandle.USER_CURRENT);
2624             if (settings == null) {
2625                 Log.i(TAG, "no AdiDeviceState stored with legacy key");
2626             } else if (!settings.equals("")) {
2627                 // Delete old key value and update the new key
2628                 if (!settingsAdapter.putSecureStringForUser(contentResolver,
2629                         Settings.Secure.SPATIAL_AUDIO_ENABLED,
2630                         /*value=*/"",
2631                         UserHandle.USER_CURRENT)) {
2632                     Log.w(TAG, "cannot erase the legacy AdiDeviceState with key "
2633                             + Settings.Secure.SPATIAL_AUDIO_ENABLED);
2634                 }
2635                 if (!settingsAdapter.putSecureStringForUser(contentResolver,
2636                         Settings.Secure.AUDIO_DEVICE_INVENTORY,
2637                         settings,
2638                         UserHandle.USER_CURRENT)) {
2639                     Log.e(TAG, "error updating the new AdiDeviceState with key "
2640                             + Settings.Secure.AUDIO_DEVICE_INVENTORY);
2641                 }
2642             }
2643         }
2644 
2645         if (settings != null && !settings.equals("")) {
2646             setDeviceSettings(settings);
2647         }
2648     }
2649 
setDeviceSettings(String settings)2650     void setDeviceSettings(String settings) {
2651         mDeviceInventory.setDeviceSettings(settings);
2652     }
2653 
2654     /** Test only method. */
getDeviceSettings()2655     String getDeviceSettings() {
2656         return mDeviceInventory.getDeviceSettings();
2657     }
2658 
getImmutableDeviceInventory()2659     Collection<AdiDeviceState> getImmutableDeviceInventory() {
2660         return mDeviceInventory.getImmutableDeviceInventory();
2661     }
2662 
addOrUpdateDeviceSAStateInInventory(AdiDeviceState deviceState)2663     void addOrUpdateDeviceSAStateInInventory(AdiDeviceState deviceState) {
2664         mDeviceInventory.addOrUpdateDeviceSAStateInInventory(deviceState);
2665     }
2666 
addOrUpdateBtAudioDeviceCategoryInInventory(AdiDeviceState deviceState)2667     void addOrUpdateBtAudioDeviceCategoryInInventory(AdiDeviceState deviceState) {
2668         mDeviceInventory.addOrUpdateAudioDeviceCategoryInInventory(deviceState);
2669     }
2670 
2671     @Nullable
findDeviceStateForAudioDeviceAttributes(AudioDeviceAttributes ada, int canonicalType)2672     AdiDeviceState findDeviceStateForAudioDeviceAttributes(AudioDeviceAttributes ada,
2673             int canonicalType) {
2674         return mDeviceInventory.findDeviceStateForAudioDeviceAttributes(ada, canonicalType);
2675     }
2676 
2677     @Nullable
findBtDeviceStateForAddress(String address, boolean isBle)2678     AdiDeviceState findBtDeviceStateForAddress(String address, boolean isBle) {
2679         return mDeviceInventory.findBtDeviceStateForAddress(address, isBle);
2680     }
2681 
2682     //------------------------------------------------
2683     // for testing purposes only
clearDeviceInventory()2684     void clearDeviceInventory() {
2685         mDeviceInventory.clearDeviceInventory();
2686     }
2687 }
2688