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