1 /*
2  * Copyright (C) 2006 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 
17 package com.android.server.audio;
18 
19 import static android.Manifest.permission.REMOTE_AUDIO_PLAYBACK;
20 import static android.media.AudioManager.RINGER_MODE_NORMAL;
21 import static android.media.AudioManager.RINGER_MODE_SILENT;
22 import static android.media.AudioManager.RINGER_MODE_VIBRATE;
23 import static android.media.AudioManager.STREAM_ALARM;
24 import static android.media.AudioManager.STREAM_MUSIC;
25 import static android.media.AudioManager.STREAM_SYSTEM;
26 import static android.os.Process.FIRST_APPLICATION_UID;
27 import static android.provider.Settings.Secure.VOLUME_HUSH_MUTE;
28 import static android.provider.Settings.Secure.VOLUME_HUSH_OFF;
29 import static android.provider.Settings.Secure.VOLUME_HUSH_VIBRATE;
30 
31 import android.Manifest;
32 import android.annotation.NonNull;
33 import android.annotation.Nullable;
34 import android.app.ActivityManager;
35 import android.app.ActivityManagerInternal;
36 import android.app.AppGlobals;
37 import android.app.AppOpsManager;
38 import android.app.IUidObserver;
39 import android.app.NotificationManager;
40 import android.bluetooth.BluetoothA2dp;
41 import android.bluetooth.BluetoothAdapter;
42 import android.bluetooth.BluetoothClass;
43 import android.bluetooth.BluetoothDevice;
44 import android.bluetooth.BluetoothHeadset;
45 import android.bluetooth.BluetoothHearingAid;
46 import android.bluetooth.BluetoothProfile;
47 import android.content.BroadcastReceiver;
48 import android.content.ComponentName;
49 import android.content.ContentResolver;
50 import android.content.Context;
51 import android.content.Intent;
52 import android.content.IntentFilter;
53 import android.content.pm.ApplicationInfo;
54 import android.content.pm.PackageInfo;
55 import android.content.pm.PackageManager;
56 import android.content.pm.ResolveInfo;
57 import android.content.pm.UserInfo;
58 import android.content.res.Configuration;
59 import android.content.res.Resources;
60 import android.content.res.XmlResourceParser;
61 import android.database.ContentObserver;
62 import android.hardware.hdmi.HdmiControlManager;
63 import android.hardware.hdmi.HdmiPlaybackClient;
64 import android.hardware.hdmi.HdmiTvClient;
65 import android.hardware.usb.UsbManager;
66 import android.media.AudioAttributes;
67 import android.media.AudioDevicePort;
68 import android.media.AudioFocusInfo;
69 import android.media.AudioFocusRequest;
70 import android.media.AudioFormat;
71 import android.media.AudioManager;
72 import android.media.AudioManagerInternal;
73 import android.media.AudioPlaybackConfiguration;
74 import android.media.AudioPort;
75 import android.media.AudioRecordingConfiguration;
76 import android.media.AudioRoutesInfo;
77 import android.media.AudioSystem;
78 import android.media.IAudioFocusDispatcher;
79 import android.media.IAudioRoutesObserver;
80 import android.media.IAudioServerStateDispatcher;
81 import android.media.IAudioService;
82 import android.media.IPlaybackConfigDispatcher;
83 import android.media.IRecordingConfigDispatcher;
84 import android.media.IRingtonePlayer;
85 import android.media.IVolumeController;
86 import android.media.MediaPlayer;
87 import android.media.MediaPlayer.OnCompletionListener;
88 import android.media.MediaPlayer.OnErrorListener;
89 import android.media.PlayerBase;
90 import android.media.SoundPool;
91 import android.media.VolumePolicy;
92 import android.media.audiofx.AudioEffect;
93 import android.media.audiopolicy.AudioMix;
94 import android.media.audiopolicy.AudioPolicy;
95 import android.media.audiopolicy.AudioPolicyConfig;
96 import android.media.audiopolicy.IAudioPolicyCallback;
97 import android.os.Binder;
98 import android.os.Build;
99 import android.os.Bundle;
100 import android.os.Environment;
101 import android.os.Handler;
102 import android.os.IBinder;
103 import android.os.Looper;
104 import android.os.Message;
105 import android.os.PowerManager;
106 import android.os.RemoteCallbackList;
107 import android.os.RemoteException;
108 import android.os.SystemClock;
109 import android.os.SystemProperties;
110 import android.os.UserHandle;
111 import android.os.UserManager;
112 import android.os.UserManagerInternal;
113 import android.os.UserManagerInternal.UserRestrictionsListener;
114 import android.os.VibrationEffect;
115 import android.os.Vibrator;
116 import android.provider.Settings;
117 import android.provider.Settings.System;
118 import android.service.notification.ZenModeConfig;
119 import android.telecom.TelecomManager;
120 import android.text.TextUtils;
121 import android.util.AndroidRuntimeException;
122 import android.util.ArrayMap;
123 import android.util.ArraySet;
124 import android.util.IntArray;
125 import android.util.Log;
126 import android.util.MathUtils;
127 import android.util.Slog;
128 import android.util.SparseIntArray;
129 import android.view.KeyEvent;
130 import android.view.accessibility.AccessibilityManager;
131 import android.widget.Toast;
132 
133 import com.android.internal.annotations.GuardedBy;
134 import com.android.internal.util.DumpUtils;
135 import com.android.internal.util.XmlUtils;
136 import com.android.server.EventLogTags;
137 import com.android.server.LocalServices;
138 import com.android.server.SystemService;
139 import com.android.server.audio.AudioServiceEvents.ForceUseEvent;
140 import com.android.server.audio.AudioServiceEvents.PhoneStateEvent;
141 import com.android.server.audio.AudioServiceEvents.VolumeEvent;
142 import com.android.server.audio.AudioServiceEvents.WiredDevConnectEvent;
143 import com.android.server.pm.UserManagerService;
144 
145 import org.xmlpull.v1.XmlPullParserException;
146 
147 import java.io.File;
148 import java.io.FileDescriptor;
149 import java.io.IOException;
150 import java.io.PrintWriter;
151 import java.lang.reflect.Field;
152 import java.util.ArrayList;
153 import java.util.Collection;
154 import java.util.HashMap;
155 import java.util.Iterator;
156 import java.util.List;
157 import java.util.NoSuchElementException;
158 import java.util.Objects;
159 
160 /**
161  * The implementation of the volume manager service.
162  * <p>
163  * This implementation focuses on delivering a responsive UI. Most methods are
164  * asynchronous to external calls. For example, the task of setting a volume
165  * will update our internal state, but in a separate thread will set the system
166  * volume and later persist to the database. Similarly, setting the ringer mode
167  * will update the state and broadcast a change and in a separate thread later
168  * persist the ringer mode.
169  *
170  * @hide
171  */
172 public class AudioService extends IAudioService.Stub
173         implements AccessibilityManager.TouchExplorationStateChangeListener,
174             AccessibilityManager.AccessibilityServicesStateChangeListener {
175 
176     private static final String TAG = "AudioService";
177 
178     /** Debug audio mode */
179     protected static final boolean DEBUG_MODE = Log.isLoggable(TAG + ".MOD", Log.DEBUG);
180 
181     /** Debug audio policy feature */
182     protected static final boolean DEBUG_AP = Log.isLoggable(TAG + ".AP", Log.DEBUG);
183 
184     /** Debug volumes */
185     protected static final boolean DEBUG_VOL = Log.isLoggable(TAG + ".VOL", Log.DEBUG);
186 
187     /** debug calls to devices APIs */
188     protected static final boolean DEBUG_DEVICES = Log.isLoggable(TAG + ".DEVICES", Log.DEBUG);
189     /** How long to delay before persisting a change in volume/ringer mode. */
190     private static final int PERSIST_DELAY = 500;
191 
192     /** How long to delay after a volume down event before unmuting a stream */
193     private static final int UNMUTE_STREAM_DELAY = 350;
194 
195     /**
196      * Only used in the result from {@link #checkForRingerModeChange(int, int, int)}
197      */
198     private static final int FLAG_ADJUST_VOLUME = 1;
199 
200     private final Context mContext;
201     private final ContentResolver mContentResolver;
202     private final AppOpsManager mAppOps;
203 
204     // the platform type affects volume and silent mode behavior
205     private final int mPlatformType;
206 
207     // indicates whether the system maps all streams to a single stream.
208     private final boolean mIsSingleVolume;
209 
isPlatformVoice()210     private boolean isPlatformVoice() {
211         return mPlatformType == AudioSystem.PLATFORM_VOICE;
212     }
213 
isPlatformTelevision()214     private boolean isPlatformTelevision() {
215         return mPlatformType == AudioSystem.PLATFORM_TELEVISION;
216     }
217 
isPlatformAutomotive()218     private boolean isPlatformAutomotive() {
219         return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
220     }
221 
222     /** The controller for the volume UI. */
223     private final VolumeController mVolumeController = new VolumeController();
224 
225     // sendMsg() flags
226     /** If the msg is already queued, replace it with this one. */
227     private static final int SENDMSG_REPLACE = 0;
228     /** If the msg is already queued, ignore this one and leave the old. */
229     private static final int SENDMSG_NOOP = 1;
230     /** If the msg is already queued, queue this one and leave the old. */
231     private static final int SENDMSG_QUEUE = 2;
232 
233     // AudioHandler messages
234     private static final int MSG_SET_DEVICE_VOLUME = 0;
235     private static final int MSG_PERSIST_VOLUME = 1;
236     private static final int MSG_PERSIST_RINGER_MODE = 3;
237     private static final int MSG_AUDIO_SERVER_DIED = 4;
238     private static final int MSG_PLAY_SOUND_EFFECT = 5;
239     private static final int MSG_LOAD_SOUND_EFFECTS = 7;
240     private static final int MSG_SET_FORCE_USE = 8;
241     private static final int MSG_BT_HEADSET_CNCT_FAILED = 9;
242     private static final int MSG_SET_ALL_VOLUMES = 10;
243     private static final int MSG_REPORT_NEW_ROUTES = 12;
244     private static final int MSG_SET_FORCE_BT_A2DP_USE = 13;
245     private static final int MSG_CHECK_MUSIC_ACTIVE = 14;
246     private static final int MSG_BROADCAST_AUDIO_BECOMING_NOISY = 15;
247     private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME = 16;
248     private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED = 17;
249     private static final int MSG_PERSIST_SAFE_VOLUME_STATE = 18;
250     private static final int MSG_BROADCAST_BT_CONNECTION_STATE = 19;
251     private static final int MSG_UNLOAD_SOUND_EFFECTS = 20;
252     private static final int MSG_SYSTEM_READY = 21;
253     private static final int MSG_PERSIST_MUSIC_ACTIVE_MS = 22;
254     private static final int MSG_UNMUTE_STREAM = 24;
255     private static final int MSG_DYN_POLICY_MIX_STATE_UPDATE = 25;
256     private static final int MSG_INDICATE_SYSTEM_READY = 26;
257     private static final int MSG_ACCESSORY_PLUG_MEDIA_UNMUTE = 27;
258     private static final int MSG_NOTIFY_VOL_EVENT = 28;
259     private static final int MSG_DISPATCH_AUDIO_SERVER_STATE = 29;
260     private static final int MSG_ENABLE_SURROUND_FORMATS = 30;
261     // start of messages handled under wakelock
262     //   these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(),
263     //   and not with sendMsg(..., ..., SENDMSG_QUEUE, ...)
264     private static final int MSG_SET_WIRED_DEVICE_CONNECTION_STATE = 100;
265     private static final int MSG_SET_A2DP_SRC_CONNECTION_STATE = 101;
266     private static final int MSG_SET_A2DP_SINK_CONNECTION_STATE = 102;
267     private static final int MSG_A2DP_DEVICE_CONFIG_CHANGE = 103;
268     private static final int MSG_DISABLE_AUDIO_FOR_UID = 104;
269     private static final int MSG_SET_HEARING_AID_CONNECTION_STATE = 105;
270     private static final int MSG_BTA2DP_DOCK_TIMEOUT = 106;
271     // end of messages handled under wakelock
272 
273     private static final int BTA2DP_DOCK_TIMEOUT_MILLIS = 8000;
274     // Timeout for connection to bluetooth headset service
275     private static final int BT_HEADSET_CNCT_TIMEOUT_MS = 3000;
276 
277     // retry delay in case of failure to indicate system ready to AudioFlinger
278     private static final int INDICATE_SYSTEM_READY_RETRY_DELAY_MS = 1000;
279 
280     private static final int BT_HEARING_AID_GAIN_MIN = -128;
281 
282     /** @see AudioSystemThread */
283     private AudioSystemThread mAudioSystemThread;
284     /** @see AudioHandler */
285     private AudioHandler mAudioHandler;
286     /** @see VolumeStreamState */
287     private VolumeStreamState[] mStreamStates;
288     private SettingsObserver mSettingsObserver;
289 
290     private int mMode = AudioSystem.MODE_NORMAL;
291     // protects mRingerMode
292     private final Object mSettingsLock = new Object();
293 
294     private SoundPool mSoundPool;
295     private final Object mSoundEffectsLock = new Object();
296     private static final int NUM_SOUNDPOOL_CHANNELS = 4;
297 
298     /* Sound effect file names  */
299     private static final String SOUND_EFFECTS_PATH = "/media/audio/ui/";
300     private static final List<String> SOUND_EFFECT_FILES = new ArrayList<String>();
301 
302     /* Sound effect file name mapping sound effect id (AudioManager.FX_xxx) to
303      * file index in SOUND_EFFECT_FILES[] (first column) and indicating if effect
304      * uses soundpool (second column) */
305     private final int[][] SOUND_EFFECT_FILES_MAP = new int[AudioManager.NUM_SOUND_EFFECTS][2];
306 
307    /** Maximum volume index values for audio streams */
308     protected static int[] MAX_STREAM_VOLUME = new int[] {
309         5,  // STREAM_VOICE_CALL
310         7,  // STREAM_SYSTEM
311         7,  // STREAM_RING
312         15, // STREAM_MUSIC
313         7,  // STREAM_ALARM
314         7,  // STREAM_NOTIFICATION
315         15, // STREAM_BLUETOOTH_SCO
316         7,  // STREAM_SYSTEM_ENFORCED
317         15, // STREAM_DTMF
318         15, // STREAM_TTS
319         15  // STREAM_ACCESSIBILITY
320     };
321 
322     /** Minimum volume index values for audio streams */
323     protected static int[] MIN_STREAM_VOLUME = new int[] {
324         1,  // STREAM_VOICE_CALL
325         0,  // STREAM_SYSTEM
326         0,  // STREAM_RING
327         0,  // STREAM_MUSIC
328         1,  // STREAM_ALARM
329         0,  // STREAM_NOTIFICATION
330         0,  // STREAM_BLUETOOTH_SCO
331         0,  // STREAM_SYSTEM_ENFORCED
332         0,  // STREAM_DTMF
333         0,  // STREAM_TTS
334         1   // STREAM_ACCESSIBILITY
335     };
336 
337     /* mStreamVolumeAlias[] indicates for each stream if it uses the volume settings
338      * of another stream: This avoids multiplying the volume settings for hidden
339      * stream types that follow other stream behavior for volume settings
340      * NOTE: do not create loops in aliases!
341      * Some streams alias to different streams according to device category (phone or tablet) or
342      * use case (in call vs off call...). See updateStreamVolumeAlias() for more details.
343      *  mStreamVolumeAlias contains STREAM_VOLUME_ALIAS_VOICE aliases for a voice capable device
344      *  (phone), STREAM_VOLUME_ALIAS_TELEVISION for a television or set-top box and
345      *  STREAM_VOLUME_ALIAS_DEFAULT for other devices (e.g. tablets).*/
346     private final int[] STREAM_VOLUME_ALIAS_VOICE = new int[] {
347         AudioSystem.STREAM_VOICE_CALL,      // STREAM_VOICE_CALL
348         AudioSystem.STREAM_RING,            // STREAM_SYSTEM
349         AudioSystem.STREAM_RING,            // STREAM_RING
350         AudioSystem.STREAM_MUSIC,           // STREAM_MUSIC
351         AudioSystem.STREAM_ALARM,           // STREAM_ALARM
352         AudioSystem.STREAM_RING,            // STREAM_NOTIFICATION
353         AudioSystem.STREAM_BLUETOOTH_SCO,   // STREAM_BLUETOOTH_SCO
354         AudioSystem.STREAM_RING,            // STREAM_SYSTEM_ENFORCED
355         AudioSystem.STREAM_RING,            // STREAM_DTMF
356         AudioSystem.STREAM_MUSIC,           // STREAM_TTS
357         AudioSystem.STREAM_MUSIC            // STREAM_ACCESSIBILITY
358     };
359     private final int[] STREAM_VOLUME_ALIAS_TELEVISION = new int[] {
360         AudioSystem.STREAM_MUSIC,       // STREAM_VOICE_CALL
361         AudioSystem.STREAM_MUSIC,       // STREAM_SYSTEM
362         AudioSystem.STREAM_MUSIC,       // STREAM_RING
363         AudioSystem.STREAM_MUSIC,       // STREAM_MUSIC
364         AudioSystem.STREAM_MUSIC,       // STREAM_ALARM
365         AudioSystem.STREAM_MUSIC,       // STREAM_NOTIFICATION
366         AudioSystem.STREAM_MUSIC,       // STREAM_BLUETOOTH_SCO
367         AudioSystem.STREAM_MUSIC,       // STREAM_SYSTEM_ENFORCED
368         AudioSystem.STREAM_MUSIC,       // STREAM_DTMF
369         AudioSystem.STREAM_MUSIC,       // STREAM_TTS
370         AudioSystem.STREAM_MUSIC        // STREAM_ACCESSIBILITY
371     };
372     private final int[] STREAM_VOLUME_ALIAS_DEFAULT = new int[] {
373         AudioSystem.STREAM_VOICE_CALL,      // STREAM_VOICE_CALL
374         AudioSystem.STREAM_RING,            // STREAM_SYSTEM
375         AudioSystem.STREAM_RING,            // STREAM_RING
376         AudioSystem.STREAM_MUSIC,           // STREAM_MUSIC
377         AudioSystem.STREAM_ALARM,           // STREAM_ALARM
378         AudioSystem.STREAM_RING,            // STREAM_NOTIFICATION
379         AudioSystem.STREAM_BLUETOOTH_SCO,   // STREAM_BLUETOOTH_SCO
380         AudioSystem.STREAM_RING,            // STREAM_SYSTEM_ENFORCED
381         AudioSystem.STREAM_RING,            // STREAM_DTMF
382         AudioSystem.STREAM_MUSIC,           // STREAM_TTS
383         AudioSystem.STREAM_MUSIC            // STREAM_ACCESSIBILITY
384     };
385     protected static int[] mStreamVolumeAlias;
386 
387     /**
388      * Map AudioSystem.STREAM_* constants to app ops.  This should be used
389      * after mapping through mStreamVolumeAlias.
390      */
391     private static final int[] STREAM_VOLUME_OPS = new int[] {
392         AppOpsManager.OP_AUDIO_VOICE_VOLUME,            // STREAM_VOICE_CALL
393         AppOpsManager.OP_AUDIO_MEDIA_VOLUME,            // STREAM_SYSTEM
394         AppOpsManager.OP_AUDIO_RING_VOLUME,             // STREAM_RING
395         AppOpsManager.OP_AUDIO_MEDIA_VOLUME,            // STREAM_MUSIC
396         AppOpsManager.OP_AUDIO_ALARM_VOLUME,            // STREAM_ALARM
397         AppOpsManager.OP_AUDIO_NOTIFICATION_VOLUME,     // STREAM_NOTIFICATION
398         AppOpsManager.OP_AUDIO_BLUETOOTH_VOLUME,        // STREAM_BLUETOOTH_SCO
399         AppOpsManager.OP_AUDIO_MEDIA_VOLUME,            // STREAM_SYSTEM_ENFORCED
400         AppOpsManager.OP_AUDIO_MEDIA_VOLUME,            // STREAM_DTMF
401         AppOpsManager.OP_AUDIO_MEDIA_VOLUME,            // STREAM_TTS
402         AppOpsManager.OP_AUDIO_ACCESSIBILITY_VOLUME,    // STREAM_ACCESSIBILITY
403     };
404 
405     private final boolean mUseFixedVolume;
406 
407     /**
408     * Default stream type used for volume control in the absence of playback
409     * e.g. user on homescreen, no app playing anything, presses hardware volume buttons, this
410     *    stream type is controlled.
411     */
412    protected static final int DEFAULT_VOL_STREAM_NO_PLAYBACK = AudioSystem.STREAM_MUSIC;
413 
414     private final AudioSystem.ErrorCallback mAudioSystemCallback = new AudioSystem.ErrorCallback() {
415         public void onError(int error) {
416             switch (error) {
417             case AudioSystem.AUDIO_STATUS_SERVER_DIED:
418                 sendMsg(mAudioHandler, MSG_AUDIO_SERVER_DIED,
419                         SENDMSG_NOOP, 0, 0, null, 0);
420                 sendMsg(mAudioHandler, MSG_DISPATCH_AUDIO_SERVER_STATE,
421                         SENDMSG_QUEUE, 0, 0, null, 0);
422                 break;
423             default:
424                 break;
425             }
426         }
427     };
428 
429     /**
430      * Current ringer mode from one of {@link AudioManager#RINGER_MODE_NORMAL},
431      * {@link AudioManager#RINGER_MODE_SILENT}, or
432      * {@link AudioManager#RINGER_MODE_VIBRATE}.
433      */
434     @GuardedBy("mSettingsLock")
435     private int mRingerMode;  // internal ringer mode, affects muting of underlying streams
436     @GuardedBy("mSettingsLock")
437     private int mRingerModeExternal = -1;  // reported ringer mode to outside clients (AudioManager)
438 
439     /** @see System#MODE_RINGER_STREAMS_AFFECTED */
440     private int mRingerModeAffectedStreams = 0;
441 
442     private int mZenModeAffectedStreams = 0;
443 
444     // Streams currently muted by ringer mode and dnd
445     private int mRingerAndZenModeMutedStreams;
446 
447     /** Streams that can be muted. Do not resolve to aliases when checking.
448      * @see System#MUTE_STREAMS_AFFECTED */
449     private int mMuteAffectedStreams;
450 
451     /**
452      * NOTE: setVibrateSetting(), getVibrateSetting(), shouldVibrate() are deprecated.
453      * mVibrateSetting is just maintained during deprecation period but vibration policy is
454      * now only controlled by mHasVibrator and mRingerMode
455      */
456     private int mVibrateSetting;
457 
458     // Is there a vibrator
459     private final boolean mHasVibrator;
460     // Used to play vibrations
461     private Vibrator mVibrator;
462     private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
463             .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
464             .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
465             .build();
466 
467     // Broadcast receiver for device connections intent broadcasts
468     private final BroadcastReceiver mReceiver = new AudioServiceBroadcastReceiver();
469 
470     /** Interface for UserManagerService. */
471     private final UserManagerInternal mUserManagerInternal;
472     private final ActivityManagerInternal mActivityManagerInternal;
473 
474     private final UserRestrictionsListener mUserRestrictionsListener =
475             new AudioServiceUserRestrictionsListener();
476 
477     // Devices currently connected
478     // Use makeDeviceListKey() to make a unique key for this list.
479     private class DeviceListSpec {
480         int mDeviceType;
481         String mDeviceName;
482         String mDeviceAddress;
483 
DeviceListSpec(int deviceType, String deviceName, String deviceAddress)484         public DeviceListSpec(int deviceType, String deviceName, String deviceAddress) {
485             mDeviceType = deviceType;
486             mDeviceName = deviceName;
487             mDeviceAddress = deviceAddress;
488         }
489 
toString()490         public String toString() {
491             return "[type:0x" + Integer.toHexString(mDeviceType) + " name:" + mDeviceName
492                     + " address:" + mDeviceAddress + "]";
493         }
494     }
495 
496     // Generate a unique key for the mConnectedDevices List by composing the device "type"
497     // and the "address" associated with a specific instance of that device type
makeDeviceListKey(int device, String deviceAddress)498     private String makeDeviceListKey(int device, String deviceAddress) {
499         return "0x" + Integer.toHexString(device) + ":" + deviceAddress;
500     }
501 
502     private final ArrayMap<String, DeviceListSpec> mConnectedDevices = new ArrayMap<>();
503 
504     // Forced device usage for communications
505     private int mForcedUseForComm;
506     private int mForcedUseForCommExt; // External state returned by getters: always consistent
507                                       // with requests by setters
508 
509     // List of binder death handlers for setMode() client processes.
510     // The last process to have called setMode() is at the top of the list.
511     private final ArrayList <SetModeDeathHandler> mSetModeDeathHandlers = new ArrayList <SetModeDeathHandler>();
512 
513     // List of clients having issued a SCO start request
514     private final ArrayList <ScoClient> mScoClients = new ArrayList <ScoClient>();
515 
516     // BluetoothHeadset API to control SCO connection
517     private BluetoothHeadset mBluetoothHeadset;
518 
519     // Bluetooth headset device
520     private BluetoothDevice mBluetoothHeadsetDevice;
521 
522     // Indicate if SCO audio connection is currently active and if the initiator is
523     // audio service (internal) or bluetooth headset (external)
524     private int mScoAudioState;
525     // SCO audio state is not active
526     private static final int SCO_STATE_INACTIVE = 0;
527     // SCO audio activation request waiting for headset service to connect
528     private static final int SCO_STATE_ACTIVATE_REQ = 1;
529     // SCO audio state is active or starting due to a request from AudioManager API
530     private static final int SCO_STATE_ACTIVE_INTERNAL = 3;
531     // SCO audio deactivation request waiting for headset service to connect
532     private static final int SCO_STATE_DEACTIVATE_REQ = 4;
533     // SCO audio deactivation in progress, waiting for Bluetooth audio intent
534     private static final int SCO_STATE_DEACTIVATING = 5;
535 
536     // SCO audio state is active due to an action in BT handsfree (either voice recognition or
537     // in call audio)
538     private static final int SCO_STATE_ACTIVE_EXTERNAL = 2;
539 
540     // Indicates the mode used for SCO audio connection. The mode is virtual call if the request
541     // originated from an app targeting an API version before JB MR2 and raw audio after that.
542     private int mScoAudioMode;
543     // SCO audio mode is undefined
544     private static final int SCO_MODE_UNDEFINED = -1;
545     // SCO audio mode is virtual voice call (BluetoothHeadset.startScoUsingVirtualVoiceCall())
546     private static final int SCO_MODE_VIRTUAL_CALL = 0;
547     // SCO audio mode is raw audio (BluetoothHeadset.connectAudio())
548     private static final int SCO_MODE_RAW = 1;
549     // SCO audio mode is Voice Recognition (BluetoothHeadset.startVoiceRecognition())
550     private static final int SCO_MODE_VR = 2;
551 
552     private static final int SCO_MODE_MAX = 2;
553 
554     // Current connection state indicated by bluetooth headset
555     private int mScoConnectionState;
556 
557     // true if boot sequence has been completed
558     private boolean mSystemReady;
559     // true if Intent.ACTION_USER_SWITCHED has ever been received
560     private boolean mUserSwitchedReceived;
561     // listener for SoundPool sample load completion indication
562     private SoundPoolCallback mSoundPoolCallBack;
563     // thread for SoundPool listener
564     private SoundPoolListenerThread mSoundPoolListenerThread;
565     // message looper for SoundPool listener
566     private Looper mSoundPoolLooper = null;
567     // volume applied to sound played with playSoundEffect()
568     private static int sSoundEffectVolumeDb;
569     // previous volume adjustment direction received by checkForRingerModeChange()
570     private int mPrevVolDirection = AudioManager.ADJUST_SAME;
571     // mVolumeControlStream is set by VolumePanel to temporarily force the stream type which volume
572     // is controlled by Vol keys.
573     private int mVolumeControlStream = -1;
574     // interpretation of whether the volume stream has been selected by the user by clicking on a
575     // volume slider to change which volume is controlled by the volume keys. Is false
576     // when mVolumeControlStream is -1.
577     private boolean mUserSelectedVolumeControlStream = false;
578     private final Object mForceControlStreamLock = new Object();
579     // VolumePanel is currently the only client of forceVolumeControlStream() and runs in system
580     // server process so in theory it is not necessary to monitor the client death.
581     // However it is good to be ready for future evolutions.
582     private ForceControlStreamClient mForceControlStreamClient = null;
583     // Used to play ringtones outside system_server
584     private volatile IRingtonePlayer mRingtonePlayer;
585 
586     // Request to override default use of A2DP for media.
587     private boolean mBluetoothA2dpEnabled;
588     private final Object mBluetoothA2dpEnabledLock = new Object();
589 
590     // Monitoring of audio routes.  Protected by mCurAudioRoutes.
591     final AudioRoutesInfo mCurAudioRoutes = new AudioRoutesInfo();
592     final RemoteCallbackList<IAudioRoutesObserver> mRoutesObservers
593             = new RemoteCallbackList<IAudioRoutesObserver>();
594 
595     // Devices for which the volume is fixed and VolumePanel slider should be disabled
596     int mFixedVolumeDevices = AudioSystem.DEVICE_OUT_HDMI |
597             AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET |
598             AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET |
599             AudioSystem.DEVICE_OUT_HDMI_ARC |
600             AudioSystem.DEVICE_OUT_SPDIF |
601             AudioSystem.DEVICE_OUT_AUX_LINE;
602     int mFullVolumeDevices = 0;
603 
604     private final boolean mMonitorRotation;
605 
606     private boolean mDockAudioMediaEnabled = true;
607 
608     private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
609 
610     // Used when safe volume warning message display is requested by setStreamVolume(). In this
611     // case, the new requested volume, stream type and device are stored in mPendingVolumeCommand
612     // and used later when/if disableSafeMediaVolume() is called.
613     private StreamVolumeCommand mPendingVolumeCommand;
614 
615     private PowerManager.WakeLock mAudioEventWakeLock;
616 
617     private final MediaFocusControl mMediaFocusControl;
618 
619     // Reference to BluetoothA2dp to query for volume.
620     private BluetoothHearingAid mHearingAid;
621     // lock always taken synchronized on mConnectedDevices
622     private final Object mHearingAidLock = new Object();
623     // Reference to BluetoothA2dp to query for AbsoluteVolume.
624     private BluetoothA2dp mA2dp;
625     // lock always taken synchronized on mConnectedDevices
626     private final Object mA2dpAvrcpLock = new Object();
627     // If absolute volume is supported in AVRCP device
628     private boolean mAvrcpAbsVolSupported = false;
629 
630     private static Long mLastDeviceConnectMsgTime = new Long(0);
631 
632     private NotificationManager mNm;
633     private AudioManagerInternal.RingerModeDelegate mRingerModeDelegate;
634     private VolumePolicy mVolumePolicy = VolumePolicy.DEFAULT;
635     private long mLoweredFromNormalToVibrateTime;
636 
637     // Array of Uids of valid accessibility services to check if caller is one of them
638     private int[] mAccessibilityServiceUids;
639     private final Object mAccessibilityServiceUidsLock = new Object();
640 
641     private int mEncodedSurroundMode;
642     private String mEnabledSurroundFormats;
643     private boolean mSurroundModeChanged;
644 
645     // Intent "extra" data keys.
646     public static final String CONNECT_INTENT_KEY_PORT_NAME = "portName";
647     public static final String CONNECT_INTENT_KEY_STATE = "state";
648     public static final String CONNECT_INTENT_KEY_ADDRESS = "address";
649     public static final String CONNECT_INTENT_KEY_HAS_PLAYBACK = "hasPlayback";
650     public static final String CONNECT_INTENT_KEY_HAS_CAPTURE = "hasCapture";
651     public static final String CONNECT_INTENT_KEY_HAS_MIDI = "hasMIDI";
652     public static final String CONNECT_INTENT_KEY_DEVICE_CLASS = "class";
653 
654     // Defines the format for the connection "address" for ALSA devices
makeAlsaAddressString(int card, int device)655     public static String makeAlsaAddressString(int card, int device) {
656         return "card=" + card + ";device=" + device + ";";
657     }
658 
659     public static final class Lifecycle extends SystemService {
660         private AudioService mService;
661 
Lifecycle(Context context)662         public Lifecycle(Context context) {
663             super(context);
664             mService = new AudioService(context);
665         }
666 
667         @Override
onStart()668         public void onStart() {
669             publishBinderService(Context.AUDIO_SERVICE, mService);
670         }
671 
672         @Override
onBootPhase(int phase)673         public void onBootPhase(int phase) {
674             if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
675                 mService.systemReady();
676             }
677         }
678     }
679 
680     final private IUidObserver mUidObserver = new IUidObserver.Stub() {
681         @Override public void onUidStateChanged(int uid, int procState, long procStateSeq) {
682         }
683 
684         @Override public void onUidGone(int uid, boolean disabled) {
685             // Once the uid is no longer running, no need to keep trying to disable its audio.
686             disableAudioForUid(false, uid);
687         }
688 
689         @Override public void onUidActive(int uid) throws RemoteException {
690         }
691 
692         @Override public void onUidIdle(int uid, boolean disabled) {
693         }
694 
695         @Override public void onUidCachedChanged(int uid, boolean cached) {
696             disableAudioForUid(cached, uid);
697         }
698 
699         private void disableAudioForUid(boolean disable, int uid) {
700             queueMsgUnderWakeLock(mAudioHandler, MSG_DISABLE_AUDIO_FOR_UID,
701                     disable ? 1 : 0 /* arg1 */,  uid /* arg2 */,
702                     null /* obj */,  0 /* delay */);
703         }
704     };
705 
706     ///////////////////////////////////////////////////////////////////////////
707     // Construction
708     ///////////////////////////////////////////////////////////////////////////
709 
710     /** @hide */
AudioService(Context context)711     public AudioService(Context context) {
712         mContext = context;
713         mContentResolver = context.getContentResolver();
714         mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
715 
716         mPlatformType = AudioSystem.getPlatformType(context);
717 
718         mIsSingleVolume = AudioSystem.isSingleVolume(context);
719 
720         mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
721         mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
722 
723         PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
724         mAudioEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "handleAudioEvent");
725 
726         mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
727         mHasVibrator = mVibrator == null ? false : mVibrator.hasVibrator();
728 
729         // Initialize volume
730         int maxCallVolume = SystemProperties.getInt("ro.config.vc_call_vol_steps", -1);
731         if (maxCallVolume != -1) {
732             MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] = maxCallVolume;
733             AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] =
734                     (maxCallVolume * 3) / 4;
735         }
736 
737         int maxMusicVolume = SystemProperties.getInt("ro.config.media_vol_steps", -1);
738         if (maxMusicVolume != -1) {
739             MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] = maxMusicVolume;
740         }
741 
742         int defaultMusicVolume = SystemProperties.getInt("ro.config.media_vol_default", -1);
743         if (defaultMusicVolume != -1 &&
744                 defaultMusicVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC]) {
745             AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] = defaultMusicVolume;
746         } else {
747             if (isPlatformTelevision()) {
748                 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] =
749                         MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] / 4;
750             } else {
751                 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] =
752                         MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] / 3;
753             }
754         }
755 
756         int maxAlarmVolume = SystemProperties.getInt("ro.config.alarm_vol_steps", -1);
757         if (maxAlarmVolume != -1) {
758             MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM] = maxAlarmVolume;
759         }
760 
761         int defaultAlarmVolume = SystemProperties.getInt("ro.config.alarm_vol_default", -1);
762         if (defaultAlarmVolume != -1 &&
763                 defaultAlarmVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM]) {
764             AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_ALARM] = defaultAlarmVolume;
765         } else {
766             // Default is 6 out of 7 (default maximum), so scale accordingly.
767             AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_ALARM] =
768                         6 * MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM] / 7;
769         }
770 
771         int maxSystemVolume = SystemProperties.getInt("ro.config.system_vol_steps", -1);
772         if (maxSystemVolume != -1) {
773             MAX_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM] = maxSystemVolume;
774         }
775 
776         int defaultSystemVolume = SystemProperties.getInt("ro.config.system_vol_default", -1);
777         if (defaultSystemVolume != -1 &&
778                 defaultSystemVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM]) {
779             AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM] = defaultSystemVolume;
780         } else {
781             // Default is to use maximum.
782             AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM] =
783                         MAX_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM];
784         }
785 
786         sSoundEffectVolumeDb = context.getResources().getInteger(
787                 com.android.internal.R.integer.config_soundEffectVolumeDb);
788 
789         mForcedUseForComm = AudioSystem.FORCE_NONE;
790 
791         createAudioSystemThread();
792 
793         AudioSystem.setErrorCallback(mAudioSystemCallback);
794 
795         boolean cameraSoundForced = readCameraSoundForced();
796         mCameraSoundForced = new Boolean(cameraSoundForced);
797         sendMsg(mAudioHandler,
798                 MSG_SET_FORCE_USE,
799                 SENDMSG_QUEUE,
800                 AudioSystem.FOR_SYSTEM,
801                 cameraSoundForced ?
802                         AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE,
803                 new String("AudioService ctor"),
804                 0);
805 
806         mSafeMediaVolumeState = new Integer(Settings.Global.getInt(mContentResolver,
807                                                         Settings.Global.AUDIO_SAFE_VOLUME_STATE,
808                                                         SAFE_MEDIA_VOLUME_NOT_CONFIGURED));
809         // The default safe volume index read here will be replaced by the actual value when
810         // the mcc is read by onConfigureSafeVolume()
811         mSafeMediaVolumeIndex = mContext.getResources().getInteger(
812                 com.android.internal.R.integer.config_safe_media_volume_index) * 10;
813 
814         mUseFixedVolume = mContext.getResources().getBoolean(
815                 com.android.internal.R.bool.config_useFixedVolume);
816 
817         // must be called before readPersistedSettings() which needs a valid mStreamVolumeAlias[]
818         // array initialized by updateStreamVolumeAlias()
819         updateStreamVolumeAlias(false /*updateVolumes*/, TAG);
820         readPersistedSettings();
821         readUserRestrictions();
822         mSettingsObserver = new SettingsObserver();
823         createStreamStates();
824 
825         // mSafeUsbMediaVolumeIndex must be initialized after createStreamStates() because it
826         // relies on audio policy having correct ranges for volume indexes.
827         mSafeUsbMediaVolumeIndex = getSafeUsbMediaVolumeIndex();
828 
829         mPlaybackMonitor =
830                 new PlaybackActivityMonitor(context, MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM]);
831 
832         mMediaFocusControl = new MediaFocusControl(mContext, mPlaybackMonitor);
833 
834         mRecordMonitor = new RecordingActivityMonitor(mContext);
835 
836         readAndSetLowRamDevice();
837 
838         // Call setRingerModeInt() to apply correct mute
839         // state on streams affected by ringer mode.
840         mRingerAndZenModeMutedStreams = 0;
841         setRingerModeInt(getRingerModeInternal(), false);
842 
843         // Register for device connection intent broadcasts.
844         IntentFilter intentFilter =
845                 new IntentFilter(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
846         intentFilter.addAction(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED);
847         intentFilter.addAction(Intent.ACTION_DOCK_EVENT);
848         intentFilter.addAction(Intent.ACTION_SCREEN_ON);
849         intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
850         intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
851         intentFilter.addAction(Intent.ACTION_USER_BACKGROUND);
852         intentFilter.addAction(Intent.ACTION_USER_FOREGROUND);
853         intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
854         intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
855 
856         intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
857         mMonitorRotation = SystemProperties.getBoolean("ro.audio.monitorRotation", false);
858         if (mMonitorRotation) {
859             RotationHelper.init(mContext, mAudioHandler);
860         }
861 
862         intentFilter.addAction(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION);
863         intentFilter.addAction(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION);
864 
865         context.registerReceiverAsUser(mReceiver, UserHandle.ALL, intentFilter, null, null);
866 
867         LocalServices.addService(AudioManagerInternal.class, new AudioServiceInternal());
868 
869         mUserManagerInternal.addUserRestrictionsListener(mUserRestrictionsListener);
870 
871         mRecordMonitor.initMonitor();
872     }
873 
systemReady()874     public void systemReady() {
875         sendMsg(mAudioHandler, MSG_SYSTEM_READY, SENDMSG_QUEUE,
876                 0, 0, null, 0);
877         if (false) {
878             // This is turned off for now, because it is racy and thus causes apps to break.
879             // Currently banning a uid means that if an app tries to start playing an audio
880             // stream, that will be preventing, and unbanning it will not allow that stream
881             // to resume.  However these changes in uid state are racy with what the app is doing,
882             // so that after taking a process out of the cached state we can't guarantee that
883             // we will unban the uid before the app actually tries to start playing audio.
884             // (To do that, the activity manager would need to wait until it knows for sure
885             // that the ban has been removed, before telling the app to do whatever it is
886             // supposed to do that caused it to go out of the cached state.)
887             try {
888                 ActivityManager.getService().registerUidObserver(mUidObserver,
889                         ActivityManager.UID_OBSERVER_CACHED | ActivityManager.UID_OBSERVER_GONE,
890                         ActivityManager.PROCESS_STATE_UNKNOWN, null);
891             } catch (RemoteException e) {
892                 // ignored; both services live in system_server
893             }
894         }
895     }
896 
onSystemReady()897     public void onSystemReady() {
898         mSystemReady = true;
899         sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE,
900                 0, 0, null, 0);
901 
902         mScoConnectionState = AudioManager.SCO_AUDIO_STATE_ERROR;
903         resetBluetoothSco();
904         getBluetoothHeadset();
905         //FIXME: this is to maintain compatibility with deprecated intent
906         // AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. Remove when appropriate.
907         Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED);
908         newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE,
909                 AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
910         sendStickyBroadcastToAll(newIntent);
911 
912         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
913         if (adapter != null) {
914             adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
915                                     BluetoothProfile.A2DP);
916             adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
917                                     BluetoothProfile.HEARING_AID);
918         }
919 
920         if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_HDMI_CEC)) {
921             mHdmiManager = mContext.getSystemService(HdmiControlManager.class);
922             synchronized (mHdmiManager) {
923                 mHdmiTvClient = mHdmiManager.getTvClient();
924                 if (mHdmiTvClient != null) {
925                     mFixedVolumeDevices &= ~AudioSystem.DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER;
926                 }
927                 mHdmiPlaybackClient = mHdmiManager.getPlaybackClient();
928                 mHdmiCecSink = false;
929             }
930         }
931 
932         mNm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
933 
934         sendMsg(mAudioHandler,
935                 MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED,
936                 SENDMSG_REPLACE,
937                 0,
938                 0,
939                 TAG,
940                 SystemProperties.getBoolean("audio.safemedia.bypass", false) ?
941                         0 : SAFE_VOLUME_CONFIGURE_TIMEOUT_MS);
942 
943         initA11yMonitoring();
944         onIndicateSystemReady();
945     }
946 
onIndicateSystemReady()947     void onIndicateSystemReady() {
948         if (AudioSystem.systemReady() == AudioSystem.SUCCESS) {
949             return;
950         }
951         sendMsg(mAudioHandler,
952                 MSG_INDICATE_SYSTEM_READY,
953                 SENDMSG_REPLACE,
954                 0,
955                 0,
956                 null,
957                 INDICATE_SYSTEM_READY_RETRY_DELAY_MS);
958     }
959 
onAudioServerDied()960     public void onAudioServerDied() {
961         if (!mSystemReady ||
962                 (AudioSystem.checkAudioFlinger() != AudioSystem.AUDIO_STATUS_OK)) {
963             Log.e(TAG, "Audioserver died.");
964             sendMsg(mAudioHandler, MSG_AUDIO_SERVER_DIED, SENDMSG_NOOP, 0, 0,
965                     null, 500);
966             return;
967         }
968         Log.e(TAG, "Audioserver started.");
969 
970         // indicate to audio HAL that we start the reconfiguration phase after a media
971         // server crash
972         // Note that we only execute this when the media server
973         // process restarts after a crash, not the first time it is started.
974         AudioSystem.setParameters("restarting=true");
975 
976         readAndSetLowRamDevice();
977 
978         // Restore device connection states
979         synchronized (mConnectedDevices) {
980             for (int i = 0; i < mConnectedDevices.size(); i++) {
981                 DeviceListSpec spec = mConnectedDevices.valueAt(i);
982                 AudioSystem.setDeviceConnectionState(
983                                                 spec.mDeviceType,
984                                                 AudioSystem.DEVICE_STATE_AVAILABLE,
985                                                 spec.mDeviceAddress,
986                                                 spec.mDeviceName);
987             }
988         }
989         // Restore call state
990         if (AudioSystem.setPhoneState(mMode) ==  AudioSystem.AUDIO_STATUS_OK) {
991             mModeLogger.log(new AudioEventLogger.StringEvent(
992                 "onAudioServerDied causes setPhoneState(" + AudioSystem.modeToString(mMode) + ")"));
993         }
994 
995         // Restore forced usage for communications and record
996         mForceUseLogger.log(new ForceUseEvent(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm,
997                 "onAudioServerDied"));
998         AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm);
999         mForceUseLogger.log(new ForceUseEvent(AudioSystem.FOR_RECORD, mForcedUseForComm,
1000                 "onAudioServerDied"));
1001         AudioSystem.setForceUse(AudioSystem.FOR_RECORD, mForcedUseForComm);
1002         final int forSys;
1003         synchronized (mSettingsLock) {
1004             forSys = mCameraSoundForced ?
1005                     AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE;
1006         }
1007         mForceUseLogger.log(new ForceUseEvent(AudioSystem.FOR_SYSTEM, forSys,
1008                 "onAudioServerDied"));
1009         AudioSystem.setForceUse(AudioSystem.FOR_SYSTEM, forSys);
1010 
1011         // Restore stream volumes
1012         int numStreamTypes = AudioSystem.getNumStreamTypes();
1013         for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
1014             VolumeStreamState streamState = mStreamStates[streamType];
1015             AudioSystem.initStreamVolume(
1016                 streamType, streamState.mIndexMin / 10, streamState.mIndexMax / 10);
1017 
1018             streamState.applyAllVolumes();
1019         }
1020 
1021         // Restore mono mode
1022         updateMasterMono(mContentResolver);
1023 
1024         // Restore ringer mode
1025         setRingerModeInt(getRingerModeInternal(), false);
1026 
1027         // Reset device rotation (if monitored for this device)
1028         if (mMonitorRotation) {
1029             RotationHelper.updateOrientation();
1030         }
1031 
1032         synchronized (mBluetoothA2dpEnabledLock) {
1033             final int forMed = mBluetoothA2dpEnabled ?
1034                     AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP;
1035             mForceUseLogger.log(new ForceUseEvent(AudioSystem.FOR_MEDIA, forMed,
1036                     "onAudioServerDied"));
1037             AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, forMed);
1038         }
1039 
1040         synchronized (mSettingsLock) {
1041             final int forDock = mDockAudioMediaEnabled ?
1042                     AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE;
1043             mForceUseLogger.log(new ForceUseEvent(AudioSystem.FOR_DOCK, forDock,
1044                     "onAudioServerDied"));
1045             AudioSystem.setForceUse(AudioSystem.FOR_DOCK, forDock);
1046             sendEncodedSurroundMode(mContentResolver, "onAudioServerDied");
1047             sendEnabledSurroundFormats(mContentResolver, true);
1048         }
1049         if (mHdmiManager != null) {
1050             synchronized (mHdmiManager) {
1051                 if (mHdmiTvClient != null) {
1052                     setHdmiSystemAudioSupported(mHdmiSystemAudioSupported);
1053                 }
1054             }
1055         }
1056 
1057         synchronized (mAudioPolicies) {
1058             for (AudioPolicyProxy policy : mAudioPolicies.values()) {
1059                 policy.connectMixes();
1060             }
1061         }
1062 
1063         onIndicateSystemReady();
1064         // indicate the end of reconfiguration phase to audio HAL
1065         AudioSystem.setParameters("restarting=false");
1066 
1067         sendMsg(mAudioHandler, MSG_DISPATCH_AUDIO_SERVER_STATE,
1068                 SENDMSG_QUEUE, 1, 0, null, 0);
1069     }
1070 
onDispatchAudioServerStateChange(boolean state)1071     private void onDispatchAudioServerStateChange(boolean state) {
1072         synchronized (mAudioServerStateListeners) {
1073             for (AsdProxy asdp : mAudioServerStateListeners.values()) {
1074                 try {
1075                     asdp.callback().dispatchAudioServerStateChange(state);
1076                 } catch (RemoteException e) {
1077                     Log.w(TAG, "Could not call dispatchAudioServerStateChange()", e);
1078                 }
1079             }
1080         }
1081     }
1082 
createAudioSystemThread()1083     private void createAudioSystemThread() {
1084         mAudioSystemThread = new AudioSystemThread();
1085         mAudioSystemThread.start();
1086         waitForAudioHandlerCreation();
1087     }
1088 
1089     /** Waits for the volume handler to be created by the other thread. */
waitForAudioHandlerCreation()1090     private void waitForAudioHandlerCreation() {
1091         synchronized(this) {
1092             while (mAudioHandler == null) {
1093                 try {
1094                     // Wait for mAudioHandler to be set by the other thread
1095                     wait();
1096                 } catch (InterruptedException e) {
1097                     Log.e(TAG, "Interrupted while waiting on volume handler.");
1098                 }
1099             }
1100         }
1101     }
1102 
checkAllAliasStreamVolumes()1103     private void checkAllAliasStreamVolumes() {
1104         synchronized (mSettingsLock) {
1105             synchronized (VolumeStreamState.class) {
1106                 int numStreamTypes = AudioSystem.getNumStreamTypes();
1107                 for (int streamType = 0; streamType < numStreamTypes; streamType++) {
1108                     mStreamStates[streamType]
1109                             .setAllIndexes(mStreamStates[mStreamVolumeAlias[streamType]], TAG);
1110                     // apply stream volume
1111                     if (!mStreamStates[streamType].mIsMuted) {
1112                         mStreamStates[streamType].applyAllVolumes();
1113                     }
1114                 }
1115             }
1116         }
1117     }
1118 
checkAllFixedVolumeDevices()1119     private void checkAllFixedVolumeDevices()
1120     {
1121         int numStreamTypes = AudioSystem.getNumStreamTypes();
1122         for (int streamType = 0; streamType < numStreamTypes; streamType++) {
1123             mStreamStates[streamType].checkFixedVolumeDevices();
1124         }
1125     }
1126 
checkAllFixedVolumeDevices(int streamType)1127     private void checkAllFixedVolumeDevices(int streamType) {
1128         mStreamStates[streamType].checkFixedVolumeDevices();
1129     }
1130 
checkMuteAffectedStreams()1131     private void checkMuteAffectedStreams() {
1132         // any stream with a min level > 0 is not muteable by definition
1133         // STREAM_VOICE_CALL can be muted by applications that has the the MODIFY_PHONE_STATE permission.
1134         for (int i = 0; i < mStreamStates.length; i++) {
1135             final VolumeStreamState vss = mStreamStates[i];
1136             if (vss.mIndexMin > 0 &&
1137                 vss.mStreamType != AudioSystem.STREAM_VOICE_CALL) {
1138                 mMuteAffectedStreams &= ~(1 << vss.mStreamType);
1139             }
1140         }
1141     }
1142 
createStreamStates()1143     private void createStreamStates() {
1144         int numStreamTypes = AudioSystem.getNumStreamTypes();
1145         VolumeStreamState[] streams = mStreamStates = new VolumeStreamState[numStreamTypes];
1146 
1147         for (int i = 0; i < numStreamTypes; i++) {
1148             streams[i] =
1149                     new VolumeStreamState(System.VOLUME_SETTINGS_INT[mStreamVolumeAlias[i]], i);
1150         }
1151 
1152         checkAllFixedVolumeDevices();
1153         checkAllAliasStreamVolumes();
1154         checkMuteAffectedStreams();
1155         updateDefaultVolumes();
1156     }
1157 
1158     // Update default indexes from aliased streams. Must be called after mStreamStates is created
updateDefaultVolumes()1159     private void updateDefaultVolumes() {
1160         for (int stream = 0; stream < mStreamStates.length; stream++) {
1161             if (stream != mStreamVolumeAlias[stream]) {
1162                 AudioSystem.DEFAULT_STREAM_VOLUME[stream] = rescaleIndex(
1163                         AudioSystem.DEFAULT_STREAM_VOLUME[mStreamVolumeAlias[stream]],
1164                         mStreamVolumeAlias[stream],
1165                         stream);
1166             }
1167         }
1168     }
1169 
dumpStreamStates(PrintWriter pw)1170     private void dumpStreamStates(PrintWriter pw) {
1171         pw.println("\nStream volumes (device: index)");
1172         int numStreamTypes = AudioSystem.getNumStreamTypes();
1173         for (int i = 0; i < numStreamTypes; i++) {
1174             pw.println("- " + AudioSystem.STREAM_NAMES[i] + ":");
1175             mStreamStates[i].dump(pw);
1176             pw.println("");
1177         }
1178         pw.print("\n- mute affected streams = 0x");
1179         pw.println(Integer.toHexString(mMuteAffectedStreams));
1180     }
1181 
updateStreamVolumeAlias(boolean updateVolumes, String caller)1182     private void updateStreamVolumeAlias(boolean updateVolumes, String caller) {
1183         int dtmfStreamAlias;
1184         final int a11yStreamAlias = sIndependentA11yVolume ?
1185                 AudioSystem.STREAM_ACCESSIBILITY : AudioSystem.STREAM_MUSIC;
1186 
1187         if (mIsSingleVolume) {
1188             mStreamVolumeAlias = STREAM_VOLUME_ALIAS_TELEVISION;
1189             dtmfStreamAlias = AudioSystem.STREAM_MUSIC;
1190         } else {
1191             switch (mPlatformType) {
1192                 case AudioSystem.PLATFORM_VOICE:
1193                     mStreamVolumeAlias = STREAM_VOLUME_ALIAS_VOICE;
1194                     dtmfStreamAlias = AudioSystem.STREAM_RING;
1195                     break;
1196                 default:
1197                     mStreamVolumeAlias = STREAM_VOLUME_ALIAS_DEFAULT;
1198                     dtmfStreamAlias = AudioSystem.STREAM_MUSIC;
1199             }
1200         }
1201 
1202         if (mIsSingleVolume) {
1203             mRingerModeAffectedStreams = 0;
1204         } else {
1205             if (isInCommunication()) {
1206                 dtmfStreamAlias = AudioSystem.STREAM_VOICE_CALL;
1207                 mRingerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_DTMF);
1208             } else {
1209                 mRingerModeAffectedStreams |= (1 << AudioSystem.STREAM_DTMF);
1210             }
1211         }
1212 
1213         mStreamVolumeAlias[AudioSystem.STREAM_DTMF] = dtmfStreamAlias;
1214         mStreamVolumeAlias[AudioSystem.STREAM_ACCESSIBILITY] = a11yStreamAlias;
1215 
1216         if (updateVolumes && mStreamStates != null) {
1217             updateDefaultVolumes();
1218 
1219             synchronized (mSettingsLock) {
1220                 synchronized (VolumeStreamState.class) {
1221                     mStreamStates[AudioSystem.STREAM_DTMF]
1222                             .setAllIndexes(mStreamStates[dtmfStreamAlias], caller);
1223                     mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].mVolumeIndexSettingName =
1224                             System.VOLUME_SETTINGS_INT[a11yStreamAlias];
1225                     mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].setAllIndexes(
1226                             mStreamStates[a11yStreamAlias], caller);
1227                     mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].refreshRange(
1228                             mStreamVolumeAlias[AudioSystem.STREAM_ACCESSIBILITY]);
1229                 }
1230             }
1231             if (sIndependentA11yVolume) {
1232                 // restore the a11y values from the settings
1233                 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].readSettings();
1234             }
1235 
1236             // apply stream mute states according to new value of mRingerModeAffectedStreams
1237             setRingerModeInt(getRingerModeInternal(), false);
1238             sendMsg(mAudioHandler,
1239                     MSG_SET_ALL_VOLUMES,
1240                     SENDMSG_QUEUE,
1241                     0,
1242                     0,
1243                     mStreamStates[AudioSystem.STREAM_DTMF], 0);
1244             sendMsg(mAudioHandler,
1245                     MSG_SET_ALL_VOLUMES,
1246                     SENDMSG_QUEUE,
1247                     0,
1248                     0,
1249                     mStreamStates[AudioSystem.STREAM_ACCESSIBILITY], 0);
1250         }
1251     }
1252 
readDockAudioSettings(ContentResolver cr)1253     private void readDockAudioSettings(ContentResolver cr)
1254     {
1255         mDockAudioMediaEnabled = Settings.Global.getInt(
1256                                         cr, Settings.Global.DOCK_AUDIO_MEDIA_ENABLED, 0) == 1;
1257 
1258         sendMsg(mAudioHandler,
1259                 MSG_SET_FORCE_USE,
1260                 SENDMSG_QUEUE,
1261                 AudioSystem.FOR_DOCK,
1262                 mDockAudioMediaEnabled ?
1263                         AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE,
1264                 new String("readDockAudioSettings"),
1265                 0);
1266     }
1267 
1268 
updateMasterMono(ContentResolver cr)1269     private void updateMasterMono(ContentResolver cr)
1270     {
1271         final boolean masterMono = System.getIntForUser(
1272                 cr, System.MASTER_MONO, 0 /* default */, UserHandle.USER_CURRENT) == 1;
1273         if (DEBUG_VOL) {
1274             Log.d(TAG, String.format("Master mono %b", masterMono));
1275         }
1276         AudioSystem.setMasterMono(masterMono);
1277     }
1278 
sendEncodedSurroundMode(ContentResolver cr, String eventSource)1279     private void sendEncodedSurroundMode(ContentResolver cr, String eventSource)
1280     {
1281         int encodedSurroundMode = Settings.Global.getInt(
1282                 cr, Settings.Global.ENCODED_SURROUND_OUTPUT,
1283                 Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
1284         sendEncodedSurroundMode(encodedSurroundMode, eventSource);
1285     }
1286 
sendEncodedSurroundMode(int encodedSurroundMode, String eventSource)1287     private void sendEncodedSurroundMode(int encodedSurroundMode, String eventSource)
1288     {
1289         // initialize to guaranteed bad value
1290         int forceSetting = AudioSystem.NUM_FORCE_CONFIG;
1291         switch (encodedSurroundMode) {
1292             case Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO:
1293                 forceSetting = AudioSystem.FORCE_NONE;
1294                 break;
1295             case Settings.Global.ENCODED_SURROUND_OUTPUT_NEVER:
1296                 forceSetting = AudioSystem.FORCE_ENCODED_SURROUND_NEVER;
1297                 break;
1298             case Settings.Global.ENCODED_SURROUND_OUTPUT_ALWAYS:
1299                 forceSetting = AudioSystem.FORCE_ENCODED_SURROUND_ALWAYS;
1300                 break;
1301             case Settings.Global.ENCODED_SURROUND_OUTPUT_MANUAL:
1302                 forceSetting = AudioSystem.FORCE_ENCODED_SURROUND_MANUAL;
1303                 break;
1304             default:
1305                 Log.e(TAG, "updateSurroundSoundSettings: illegal value "
1306                         + encodedSurroundMode);
1307                 break;
1308         }
1309         if (forceSetting != AudioSystem.NUM_FORCE_CONFIG) {
1310             sendMsg(mAudioHandler,
1311                     MSG_SET_FORCE_USE,
1312                     SENDMSG_QUEUE,
1313                     AudioSystem.FOR_ENCODED_SURROUND,
1314                     forceSetting,
1315                     eventSource,
1316                     0);
1317         }
1318     }
1319 
sendEnabledSurroundFormats(ContentResolver cr, boolean forceUpdate)1320     private void sendEnabledSurroundFormats(ContentResolver cr, boolean forceUpdate) {
1321         if (mEncodedSurroundMode != Settings.Global.ENCODED_SURROUND_OUTPUT_MANUAL) {
1322             // Manually enable surround formats only when the setting is in manual mode.
1323             return;
1324         }
1325         String enabledSurroundFormats = Settings.Global.getString(
1326                 cr, Settings.Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS);
1327         if (enabledSurroundFormats == null) {
1328             // Never allow enabledSurroundFormats as a null, which could happen when
1329             // ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS is not appear in settings DB.
1330             enabledSurroundFormats = "";
1331         }
1332         if (!forceUpdate && TextUtils.equals(enabledSurroundFormats, mEnabledSurroundFormats)) {
1333             // Update enabled surround formats to AudioPolicyManager only when forceUpdate
1334             // is true or enabled surround formats changed.
1335             return;
1336         }
1337 
1338         mEnabledSurroundFormats = enabledSurroundFormats;
1339         String[] surroundFormats = TextUtils.split(enabledSurroundFormats, ",");
1340         ArrayList<Integer> formats = new ArrayList<>();
1341         for (String format : surroundFormats) {
1342             try {
1343                 int audioFormat = Integer.valueOf(format);
1344                 boolean isSurroundFormat = false;
1345                 for (int sf : AudioFormat.SURROUND_SOUND_ENCODING) {
1346                     if (sf == audioFormat) {
1347                         isSurroundFormat = true;
1348                         break;
1349                     }
1350                 }
1351                 if (isSurroundFormat && !formats.contains(audioFormat)) {
1352                     formats.add(audioFormat);
1353                 }
1354             } catch (Exception e) {
1355                 Log.e(TAG, "Invalid enabled surround format:" + format);
1356             }
1357         }
1358         // Set filtered surround formats to settings DB in case
1359         // there are invalid surround formats in original settings.
1360         Settings.Global.putString(mContext.getContentResolver(),
1361                 Settings.Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS,
1362                 TextUtils.join(",", formats));
1363         sendMsg(mAudioHandler, MSG_ENABLE_SURROUND_FORMATS, SENDMSG_QUEUE, 0, 0, formats, 0);
1364     }
1365 
onEnableSurroundFormats(ArrayList<Integer> enabledSurroundFormats)1366     private void onEnableSurroundFormats(ArrayList<Integer> enabledSurroundFormats) {
1367         // Set surround format enabled accordingly.
1368         for (int surroundFormat : AudioFormat.SURROUND_SOUND_ENCODING) {
1369             boolean enabled = enabledSurroundFormats.contains(surroundFormat);
1370             int ret = AudioSystem.setSurroundFormatEnabled(surroundFormat, enabled);
1371             Log.i(TAG, "enable surround format:" + surroundFormat + " " + enabled + " " + ret);
1372         }
1373     }
1374 
readPersistedSettings()1375     private void readPersistedSettings() {
1376         final ContentResolver cr = mContentResolver;
1377 
1378         int ringerModeFromSettings =
1379                 Settings.Global.getInt(
1380                         cr, Settings.Global.MODE_RINGER, AudioManager.RINGER_MODE_NORMAL);
1381         int ringerMode = ringerModeFromSettings;
1382         // sanity check in case the settings are restored from a device with incompatible
1383         // ringer modes
1384         if (!isValidRingerMode(ringerMode)) {
1385             ringerMode = AudioManager.RINGER_MODE_NORMAL;
1386         }
1387         if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) {
1388             ringerMode = AudioManager.RINGER_MODE_SILENT;
1389         }
1390         if (ringerMode != ringerModeFromSettings) {
1391             Settings.Global.putInt(cr, Settings.Global.MODE_RINGER, ringerMode);
1392         }
1393         if (mUseFixedVolume || mIsSingleVolume) {
1394             ringerMode = AudioManager.RINGER_MODE_NORMAL;
1395         }
1396         synchronized(mSettingsLock) {
1397             mRingerMode = ringerMode;
1398             if (mRingerModeExternal == -1) {
1399                 mRingerModeExternal = mRingerMode;
1400             }
1401 
1402             // System.VIBRATE_ON is not used any more but defaults for mVibrateSetting
1403             // are still needed while setVibrateSetting() and getVibrateSetting() are being
1404             // deprecated.
1405             mVibrateSetting = AudioSystem.getValueForVibrateSetting(0,
1406                                             AudioManager.VIBRATE_TYPE_NOTIFICATION,
1407                                             mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT
1408                                                             : AudioManager.VIBRATE_SETTING_OFF);
1409             mVibrateSetting = AudioSystem.getValueForVibrateSetting(mVibrateSetting,
1410                                             AudioManager.VIBRATE_TYPE_RINGER,
1411                                             mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT
1412                                                             : AudioManager.VIBRATE_SETTING_OFF);
1413 
1414             updateRingerAndZenModeAffectedStreams();
1415             readDockAudioSettings(cr);
1416             sendEncodedSurroundMode(cr, "readPersistedSettings");
1417             sendEnabledSurroundFormats(cr, true);
1418         }
1419 
1420         mMuteAffectedStreams = System.getIntForUser(cr,
1421                 System.MUTE_STREAMS_AFFECTED, AudioSystem.DEFAULT_MUTE_STREAMS_AFFECTED,
1422                 UserHandle.USER_CURRENT);
1423 
1424         updateMasterMono(cr);
1425 
1426         // Each stream will read its own persisted settings
1427 
1428         // Broadcast the sticky intents
1429         broadcastRingerMode(AudioManager.RINGER_MODE_CHANGED_ACTION, mRingerModeExternal);
1430         broadcastRingerMode(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION, mRingerMode);
1431 
1432         // Broadcast vibrate settings
1433         broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER);
1434         broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION);
1435 
1436         // Load settings for the volume controller
1437         mVolumeController.loadSettings(cr);
1438     }
1439 
readUserRestrictions()1440     private void readUserRestrictions() {
1441         final int currentUser = getCurrentUserId();
1442 
1443         // Check the current user restriction.
1444         boolean masterMute =
1445                 mUserManagerInternal.getUserRestriction(currentUser,
1446                         UserManager.DISALLOW_UNMUTE_DEVICE)
1447                         || mUserManagerInternal.getUserRestriction(currentUser,
1448                         UserManager.DISALLOW_ADJUST_VOLUME);
1449         if (mUseFixedVolume) {
1450             masterMute = false;
1451             AudioSystem.setMasterVolume(1.0f);
1452         }
1453         if (DEBUG_VOL) {
1454             Log.d(TAG, String.format("Master mute %s, user=%d", masterMute, currentUser));
1455         }
1456         setSystemAudioMute(masterMute);
1457         AudioSystem.setMasterMute(masterMute);
1458         broadcastMasterMuteStatus(masterMute);
1459 
1460         boolean microphoneMute = mUserManagerInternal.getUserRestriction(
1461                 currentUser, UserManager.DISALLOW_UNMUTE_MICROPHONE);
1462         if (DEBUG_VOL) {
1463             Log.d(TAG, String.format("Mic mute %s, user=%d", microphoneMute, currentUser));
1464         }
1465         AudioSystem.muteMicrophone(microphoneMute);
1466     }
1467 
rescaleIndex(int index, int srcStream, int dstStream)1468     private int rescaleIndex(int index, int srcStream, int dstStream) {
1469         final int rescaled =
1470                 (index * mStreamStates[dstStream].getMaxIndex()
1471                         + mStreamStates[srcStream].getMaxIndex() / 2)
1472                 / mStreamStates[srcStream].getMaxIndex();
1473         if (rescaled < mStreamStates[dstStream].getMinIndex()) {
1474             return mStreamStates[dstStream].getMinIndex();
1475         } else {
1476             return rescaled;
1477         }
1478     }
1479 
1480     ///////////////////////////////////////////////////////////////////////////
1481     // IPC methods
1482     ///////////////////////////////////////////////////////////////////////////
1483     /** @see AudioManager#adjustVolume(int, int) */
adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags, String callingPackage, String caller)1484     public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
1485             String callingPackage, String caller) {
1486         final IAudioPolicyCallback extVolCtlr;
1487         synchronized (mExtVolumeControllerLock) {
1488             extVolCtlr = mExtVolumeController;
1489         }
1490         if (extVolCtlr != null) {
1491             sendMsg(mAudioHandler, MSG_NOTIFY_VOL_EVENT, SENDMSG_QUEUE,
1492                     direction, 0 /*ignored*/,
1493                     extVolCtlr, 0 /*delay*/);
1494         } else {
1495             adjustSuggestedStreamVolume(direction, suggestedStreamType, flags, callingPackage,
1496                     caller, Binder.getCallingUid());
1497         }
1498     }
1499 
adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags, String callingPackage, String caller, int uid)1500     private void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
1501             String callingPackage, String caller, int uid) {
1502         if (DEBUG_VOL) Log.d(TAG, "adjustSuggestedStreamVolume() stream=" + suggestedStreamType
1503                 + ", flags=" + flags + ", caller=" + caller
1504                 + ", volControlStream=" + mVolumeControlStream
1505                 + ", userSelect=" + mUserSelectedVolumeControlStream);
1506         mVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_ADJUST_SUGG_VOL, suggestedStreamType,
1507                 direction/*val1*/, flags/*val2*/, new StringBuilder(callingPackage)
1508                         .append("/").append(caller).append(" uid:").append(uid).toString()));
1509         final int streamType;
1510         synchronized (mForceControlStreamLock) {
1511             // Request lock in case mVolumeControlStream is changed by other thread.
1512             if (mUserSelectedVolumeControlStream) { // implies mVolumeControlStream != -1
1513                 streamType = mVolumeControlStream;
1514             } else {
1515                 final int maybeActiveStreamType = getActiveStreamType(suggestedStreamType);
1516                 final boolean activeForReal;
1517                 if (maybeActiveStreamType == AudioSystem.STREAM_RING
1518                         || maybeActiveStreamType == AudioSystem.STREAM_NOTIFICATION) {
1519                     activeForReal = wasStreamActiveRecently(maybeActiveStreamType, 0);
1520                 } else {
1521                     activeForReal = AudioSystem.isStreamActive(maybeActiveStreamType, 0);
1522                 }
1523                 if (activeForReal || mVolumeControlStream == -1) {
1524                     streamType = maybeActiveStreamType;
1525                 } else {
1526                     streamType = mVolumeControlStream;
1527                 }
1528             }
1529         }
1530 
1531         final boolean isMute = isMuteAdjust(direction);
1532 
1533         ensureValidStreamType(streamType);
1534         final int resolvedStream = mStreamVolumeAlias[streamType];
1535 
1536         // Play sounds on STREAM_RING only.
1537         if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0 &&
1538                 resolvedStream != AudioSystem.STREAM_RING) {
1539             flags &= ~AudioManager.FLAG_PLAY_SOUND;
1540         }
1541 
1542         // For notifications/ring, show the ui before making any adjustments
1543         // Don't suppress mute/unmute requests
1544         if (mVolumeController.suppressAdjustment(resolvedStream, flags, isMute)) {
1545             direction = 0;
1546             flags &= ~AudioManager.FLAG_PLAY_SOUND;
1547             flags &= ~AudioManager.FLAG_VIBRATE;
1548             if (DEBUG_VOL) Log.d(TAG, "Volume controller suppressed adjustment");
1549         }
1550 
1551         adjustStreamVolume(streamType, direction, flags, callingPackage, caller, uid);
1552     }
1553 
1554     /** @see AudioManager#adjustStreamVolume(int, int, int) */
adjustStreamVolume(int streamType, int direction, int flags, String callingPackage)1555     public void adjustStreamVolume(int streamType, int direction, int flags,
1556             String callingPackage) {
1557         if ((streamType == AudioManager.STREAM_ACCESSIBILITY) && !canChangeAccessibilityVolume()) {
1558             Log.w(TAG, "Trying to call adjustStreamVolume() for a11y without"
1559                     + "CHANGE_ACCESSIBILITY_VOLUME / callingPackage=" + callingPackage);
1560             return;
1561         }
1562         mVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_ADJUST_STREAM_VOL, streamType,
1563                 direction/*val1*/, flags/*val2*/, callingPackage));
1564         adjustStreamVolume(streamType, direction, flags, callingPackage, callingPackage,
1565                 Binder.getCallingUid());
1566     }
1567 
adjustStreamVolume(int streamType, int direction, int flags, String callingPackage, String caller, int uid)1568     protected void adjustStreamVolume(int streamType, int direction, int flags,
1569             String callingPackage, String caller, int uid) {
1570         if (mUseFixedVolume) {
1571             return;
1572         }
1573         if (DEBUG_VOL) Log.d(TAG, "adjustStreamVolume() stream=" + streamType + ", dir=" + direction
1574                 + ", flags=" + flags + ", caller=" + caller);
1575 
1576         ensureValidDirection(direction);
1577         ensureValidStreamType(streamType);
1578 
1579         boolean isMuteAdjust = isMuteAdjust(direction);
1580 
1581         if (isMuteAdjust && !isStreamAffectedByMute(streamType)) {
1582             return;
1583         }
1584 
1585         // If adjust is mute and the stream is STREAM_VOICE_CALL, make sure
1586         // that the calling app have the MODIFY_PHONE_STATE permission.
1587         if (isMuteAdjust &&
1588             streamType == AudioSystem.STREAM_VOICE_CALL &&
1589             mContext.checkCallingOrSelfPermission(
1590                 android.Manifest.permission.MODIFY_PHONE_STATE)
1591                     != PackageManager.PERMISSION_GRANTED) {
1592             Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: adjustStreamVolume from pid="
1593                     + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
1594             return;
1595         }
1596 
1597         // use stream type alias here so that streams with same alias have the same behavior,
1598         // including with regard to silent mode control (e.g the use of STREAM_RING below and in
1599         // checkForRingerModeChange() in place of STREAM_RING or STREAM_NOTIFICATION)
1600         int streamTypeAlias = mStreamVolumeAlias[streamType];
1601 
1602         VolumeStreamState streamState = mStreamStates[streamTypeAlias];
1603 
1604         final int device = getDeviceForStream(streamTypeAlias);
1605 
1606         int aliasIndex = streamState.getIndex(device);
1607         boolean adjustVolume = true;
1608         int step;
1609 
1610         // skip a2dp absolute volume control request when the device
1611         // is not an a2dp device
1612         if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 &&
1613             (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
1614             return;
1615         }
1616 
1617         // If we are being called by the system (e.g. hardware keys) check for current user
1618         // so we handle user restrictions correctly.
1619         if (uid == android.os.Process.SYSTEM_UID) {
1620             uid = UserHandle.getUid(getCurrentUserId(), UserHandle.getAppId(uid));
1621         }
1622         if (mAppOps.noteOp(STREAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage)
1623                 != AppOpsManager.MODE_ALLOWED) {
1624             return;
1625         }
1626 
1627         // reset any pending volume command
1628         synchronized (mSafeMediaVolumeState) {
1629             mPendingVolumeCommand = null;
1630         }
1631 
1632         flags &= ~AudioManager.FLAG_FIXED_VOLUME;
1633         if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
1634                ((device & mFixedVolumeDevices) != 0)) {
1635             flags |= AudioManager.FLAG_FIXED_VOLUME;
1636 
1637             // Always toggle between max safe volume and 0 for fixed volume devices where safe
1638             // volume is enforced, and max and 0 for the others.
1639             // This is simulated by stepping by the full allowed volume range
1640             if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE &&
1641                     (device & mSafeMediaVolumeDevices) != 0) {
1642                 step = safeMediaVolumeIndex(device);
1643             } else {
1644                 step = streamState.getMaxIndex();
1645             }
1646             if (aliasIndex != 0) {
1647                 aliasIndex = step;
1648             }
1649         } else {
1650             // convert one UI step (+/-1) into a number of internal units on the stream alias
1651             step = rescaleIndex(10, streamType, streamTypeAlias);
1652         }
1653 
1654         // If either the client forces allowing ringer modes for this adjustment,
1655         // or the stream type is one that is affected by ringer modes
1656         if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
1657                 (streamTypeAlias == getUiSoundsStreamType())) {
1658             int ringerMode = getRingerModeInternal();
1659             // do not vibrate if already in vibrate mode
1660             if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
1661                 flags &= ~AudioManager.FLAG_VIBRATE;
1662             }
1663             // Check if the ringer mode handles this adjustment. If it does we don't
1664             // need to adjust the volume further.
1665             final int result = checkForRingerModeChange(aliasIndex, direction, step,
1666                     streamState.mIsMuted, callingPackage, flags);
1667             adjustVolume = (result & FLAG_ADJUST_VOLUME) != 0;
1668             // If suppressing a volume adjustment in silent mode, display the UI hint
1669             if ((result & AudioManager.FLAG_SHOW_SILENT_HINT) != 0) {
1670                 flags |= AudioManager.FLAG_SHOW_SILENT_HINT;
1671             }
1672             // If suppressing a volume down adjustment in vibrate mode, display the UI hint
1673             if ((result & AudioManager.FLAG_SHOW_VIBRATE_HINT) != 0) {
1674                 flags |= AudioManager.FLAG_SHOW_VIBRATE_HINT;
1675             }
1676         }
1677 
1678         // If the ringer mode or zen is muting the stream, do not change stream unless
1679         // it'll cause us to exit dnd
1680         if (!volumeAdjustmentAllowedByDnd(streamTypeAlias, flags)) {
1681             adjustVolume = false;
1682         }
1683         int oldIndex = mStreamStates[streamType].getIndex(device);
1684 
1685         if (adjustVolume && (direction != AudioManager.ADJUST_SAME)) {
1686             mAudioHandler.removeMessages(MSG_UNMUTE_STREAM);
1687 
1688             if (isMuteAdjust) {
1689                 boolean state;
1690                 if (direction == AudioManager.ADJUST_TOGGLE_MUTE) {
1691                     state = !streamState.mIsMuted;
1692                 } else {
1693                     state = direction == AudioManager.ADJUST_MUTE;
1694                 }
1695                 if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
1696                     setSystemAudioMute(state);
1697                 }
1698                 for (int stream = 0; stream < mStreamStates.length; stream++) {
1699                     if (streamTypeAlias == mStreamVolumeAlias[stream]) {
1700                         if (!(readCameraSoundForced()
1701                                     && (mStreamStates[stream].getStreamType()
1702                                         == AudioSystem.STREAM_SYSTEM_ENFORCED))) {
1703                             mStreamStates[stream].mute(state);
1704                         }
1705                     }
1706                 }
1707             } else if ((direction == AudioManager.ADJUST_RAISE) &&
1708                     !checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) {
1709                 Log.e(TAG, "adjustStreamVolume() safe volume index = " + oldIndex);
1710                 mVolumeController.postDisplaySafeVolumeWarning(flags);
1711             } else if (streamState.adjustIndex(direction * step, device, caller)
1712                     || streamState.mIsMuted) {
1713                 // Post message to set system volume (it in turn will post a
1714                 // message to persist).
1715                 if (streamState.mIsMuted) {
1716                     // Unmute the stream if it was previously muted
1717                     if (direction == AudioManager.ADJUST_RAISE) {
1718                         // unmute immediately for volume up
1719                         streamState.mute(false);
1720                     } else if (direction == AudioManager.ADJUST_LOWER) {
1721                         if (mIsSingleVolume) {
1722                             sendMsg(mAudioHandler, MSG_UNMUTE_STREAM, SENDMSG_QUEUE,
1723                                     streamTypeAlias, flags, null, UNMUTE_STREAM_DELAY);
1724                         }
1725                     }
1726                 }
1727                 sendMsg(mAudioHandler,
1728                         MSG_SET_DEVICE_VOLUME,
1729                         SENDMSG_QUEUE,
1730                         device,
1731                         0,
1732                         streamState,
1733                         0);
1734             }
1735 
1736             int newIndex = mStreamStates[streamType].getIndex(device);
1737 
1738             // Check if volume update should be send to AVRCP
1739             if (streamTypeAlias == AudioSystem.STREAM_MUSIC &&
1740                 (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
1741                 (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
1742                 synchronized (mA2dpAvrcpLock) {
1743                     if (mA2dp != null && mAvrcpAbsVolSupported) {
1744                         mA2dp.setAvrcpAbsoluteVolume(newIndex / 10);
1745                     }
1746                 }
1747             }
1748 
1749             // Check if volume update should be send to Hearing Aid
1750             if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
1751                 setHearingAidVolume(newIndex, streamType);
1752             }
1753 
1754             // Check if volume update should be sent to Hdmi system audio.
1755             if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
1756                 setSystemAudioVolume(oldIndex, newIndex, getStreamMaxVolume(streamType), flags);
1757             }
1758             if (mHdmiManager != null) {
1759                 synchronized (mHdmiManager) {
1760                     // mHdmiCecSink true => mHdmiPlaybackClient != null
1761                     if (mHdmiCecSink &&
1762                             streamTypeAlias == AudioSystem.STREAM_MUSIC &&
1763                             oldIndex != newIndex) {
1764                         synchronized (mHdmiPlaybackClient) {
1765                             int keyCode = (direction == -1) ? KeyEvent.KEYCODE_VOLUME_DOWN :
1766                                     KeyEvent.KEYCODE_VOLUME_UP;
1767                             final long ident = Binder.clearCallingIdentity();
1768                             try {
1769                                 mHdmiPlaybackClient.sendKeyEvent(keyCode, true);
1770                                 mHdmiPlaybackClient.sendKeyEvent(keyCode, false);
1771                             } finally {
1772                                 Binder.restoreCallingIdentity(ident);
1773                             }
1774                         }
1775                     }
1776                 }
1777             }
1778         }
1779         int index = mStreamStates[streamType].getIndex(device);
1780         sendVolumeUpdate(streamType, oldIndex, index, flags);
1781     }
1782 
1783     // Called after a delay when volume down is pressed while muted
onUnmuteStream(int stream, int flags)1784     private void onUnmuteStream(int stream, int flags) {
1785         VolumeStreamState streamState = mStreamStates[stream];
1786         streamState.mute(false);
1787 
1788         final int device = getDeviceForStream(stream);
1789         final int index = mStreamStates[stream].getIndex(device);
1790         sendVolumeUpdate(stream, index, index, flags);
1791     }
1792 
setSystemAudioVolume(int oldVolume, int newVolume, int maxVolume, int flags)1793     private void setSystemAudioVolume(int oldVolume, int newVolume, int maxVolume, int flags) {
1794         if (mHdmiManager == null
1795                 || mHdmiTvClient == null
1796                 || oldVolume == newVolume
1797                 || (flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) != 0) return;
1798 
1799         // Sets the audio volume of AVR when we are in system audio mode. The new volume info
1800         // is tranformed to HDMI-CEC commands and passed through CEC bus.
1801         synchronized (mHdmiManager) {
1802             if (!mHdmiSystemAudioSupported) return;
1803             synchronized (mHdmiTvClient) {
1804                 final long token = Binder.clearCallingIdentity();
1805                 try {
1806                     mHdmiTvClient.setSystemAudioVolume(oldVolume, newVolume, maxVolume);
1807                 } finally {
1808                     Binder.restoreCallingIdentity(token);
1809                 }
1810             }
1811         }
1812     }
1813 
1814     // StreamVolumeCommand contains the information needed to defer the process of
1815     // setStreamVolume() in case the user has to acknowledge the safe volume warning message.
1816     class StreamVolumeCommand {
1817         public final int mStreamType;
1818         public final int mIndex;
1819         public final int mFlags;
1820         public final int mDevice;
1821 
StreamVolumeCommand(int streamType, int index, int flags, int device)1822         StreamVolumeCommand(int streamType, int index, int flags, int device) {
1823             mStreamType = streamType;
1824             mIndex = index;
1825             mFlags = flags;
1826             mDevice = device;
1827         }
1828 
1829         @Override
toString()1830         public String toString() {
1831             return new StringBuilder().append("{streamType=").append(mStreamType).append(",index=")
1832                     .append(mIndex).append(",flags=").append(mFlags).append(",device=")
1833                     .append(mDevice).append('}').toString();
1834         }
1835     };
1836 
getNewRingerMode(int stream, int index, int flags)1837     private int getNewRingerMode(int stream, int index, int flags) {
1838         // setRingerMode does nothing if the device is single volume,so the value would be unchanged
1839         if (mIsSingleVolume) {
1840             return getRingerModeExternal();
1841         }
1842 
1843         // setting volume on ui sounds stream type also controls silent mode
1844         if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
1845                 (stream == getUiSoundsStreamType())) {
1846             int newRingerMode;
1847             if (index == 0) {
1848                 newRingerMode = mHasVibrator ? AudioManager.RINGER_MODE_VIBRATE
1849                         : mVolumePolicy.volumeDownToEnterSilent ? AudioManager.RINGER_MODE_SILENT
1850                                 : AudioManager.RINGER_MODE_NORMAL;
1851             } else {
1852                 newRingerMode = AudioManager.RINGER_MODE_NORMAL;
1853             }
1854             return newRingerMode;
1855         }
1856         return getRingerModeExternal();
1857     }
1858 
isAndroidNPlus(String caller)1859     private boolean isAndroidNPlus(String caller) {
1860         try {
1861             final ApplicationInfo applicationInfo =
1862                     mContext.getPackageManager().getApplicationInfoAsUser(
1863                             caller, 0, UserHandle.getUserId(Binder.getCallingUid()));
1864             if (applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
1865                 return true;
1866             }
1867             return false;
1868         } catch (PackageManager.NameNotFoundException e) {
1869             return true;
1870         }
1871     }
1872 
wouldToggleZenMode(int newMode)1873     private boolean wouldToggleZenMode(int newMode) {
1874         if (getRingerModeExternal() == AudioManager.RINGER_MODE_SILENT
1875                 && newMode != AudioManager.RINGER_MODE_SILENT) {
1876             return true;
1877         } else if (getRingerModeExternal() != AudioManager.RINGER_MODE_SILENT
1878                 && newMode == AudioManager.RINGER_MODE_SILENT) {
1879             return true;
1880         }
1881         return false;
1882     }
1883 
onSetStreamVolume(int streamType, int index, int flags, int device, String caller)1884     private void onSetStreamVolume(int streamType, int index, int flags, int device,
1885             String caller) {
1886         final int stream = mStreamVolumeAlias[streamType];
1887         setStreamVolumeInt(stream, index, device, false, caller);
1888         // setting volume on ui sounds stream type also controls silent mode
1889         if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
1890                 (stream == getUiSoundsStreamType())) {
1891             setRingerMode(getNewRingerMode(stream, index, flags),
1892                     TAG + ".onSetStreamVolume", false /*external*/);
1893         }
1894         // setting non-zero volume for a muted stream unmutes the stream and vice versa
1895         mStreamStates[stream].mute(index == 0);
1896     }
1897 
1898     /** @see AudioManager#setStreamVolume(int, int, int) */
setStreamVolume(int streamType, int index, int flags, String callingPackage)1899     public void setStreamVolume(int streamType, int index, int flags, String callingPackage) {
1900         if ((streamType == AudioManager.STREAM_ACCESSIBILITY) && !canChangeAccessibilityVolume()) {
1901             Log.w(TAG, "Trying to call setStreamVolume() for a11y without"
1902                     + " CHANGE_ACCESSIBILITY_VOLUME  callingPackage=" + callingPackage);
1903             return;
1904         }
1905         if ((streamType == AudioManager.STREAM_VOICE_CALL) &&
1906                 (index == 0) &&
1907                 (mContext.checkCallingOrSelfPermission(
1908                 android.Manifest.permission.MODIFY_PHONE_STATE)
1909                     != PackageManager.PERMISSION_GRANTED)) {
1910             Log.w(TAG, "Trying to call setStreamVolume() for STREAM_VOICE_CALL and index 0 without"
1911                     + " MODIFY_PHONE_STATE  callingPackage=" + callingPackage);
1912             return;
1913         }
1914         mVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_SET_STREAM_VOL, streamType,
1915                 index/*val1*/, flags/*val2*/, callingPackage));
1916         setStreamVolume(streamType, index, flags, callingPackage, callingPackage,
1917                 Binder.getCallingUid());
1918     }
1919 
canChangeAccessibilityVolume()1920     private boolean canChangeAccessibilityVolume() {
1921         synchronized (mAccessibilityServiceUidsLock) {
1922             if (PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
1923                     android.Manifest.permission.CHANGE_ACCESSIBILITY_VOLUME)) {
1924                 return true;
1925             }
1926             if (mAccessibilityServiceUids != null) {
1927                 int callingUid = Binder.getCallingUid();
1928                 for (int i = 0; i < mAccessibilityServiceUids.length; i++) {
1929                     if (mAccessibilityServiceUids[i] == callingUid) {
1930                         return true;
1931                     }
1932                 }
1933             }
1934             return false;
1935         }
1936     }
1937 
setStreamVolume(int streamType, int index, int flags, String callingPackage, String caller, int uid)1938     private void setStreamVolume(int streamType, int index, int flags, String callingPackage,
1939             String caller, int uid) {
1940         if (DEBUG_VOL) {
1941             Log.d(TAG, "setStreamVolume(stream=" + streamType+", index=" + index
1942                     + ", calling=" + callingPackage + ")");
1943         }
1944         if (mUseFixedVolume) {
1945             return;
1946         }
1947 
1948         ensureValidStreamType(streamType);
1949         int streamTypeAlias = mStreamVolumeAlias[streamType];
1950         VolumeStreamState streamState = mStreamStates[streamTypeAlias];
1951 
1952         final int device = getDeviceForStream(streamType);
1953         int oldIndex;
1954 
1955         // skip a2dp absolute volume control request when the device
1956         // is not an a2dp device
1957         if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 &&
1958             (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
1959             return;
1960         }
1961         // If we are being called by the system (e.g. hardware keys) check for current user
1962         // so we handle user restrictions correctly.
1963         if (uid == android.os.Process.SYSTEM_UID) {
1964             uid = UserHandle.getUid(getCurrentUserId(), UserHandle.getAppId(uid));
1965         }
1966         if (mAppOps.noteOp(STREAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage)
1967                 != AppOpsManager.MODE_ALLOWED) {
1968             return;
1969         }
1970 
1971         if (isAndroidNPlus(callingPackage)
1972                 && wouldToggleZenMode(getNewRingerMode(streamTypeAlias, index, flags))
1973                 && !mNm.isNotificationPolicyAccessGrantedForPackage(callingPackage)) {
1974             throw new SecurityException("Not allowed to change Do Not Disturb state");
1975         }
1976 
1977         if (!volumeAdjustmentAllowedByDnd(streamTypeAlias, flags)) {
1978             return;
1979         }
1980 
1981         synchronized (mSafeMediaVolumeState) {
1982             // reset any pending volume command
1983             mPendingVolumeCommand = null;
1984 
1985             oldIndex = streamState.getIndex(device);
1986 
1987             index = rescaleIndex(index * 10, streamType, streamTypeAlias);
1988 
1989             if (streamTypeAlias == AudioSystem.STREAM_MUSIC &&
1990                 (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
1991                 (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
1992                 synchronized (mA2dpAvrcpLock) {
1993                     if (mA2dp != null && mAvrcpAbsVolSupported) {
1994                         mA2dp.setAvrcpAbsoluteVolume(index / 10);
1995                     }
1996                 }
1997             }
1998 
1999             if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
2000                 setHearingAidVolume(index, streamType);
2001             }
2002 
2003             if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
2004                 setSystemAudioVolume(oldIndex, index, getStreamMaxVolume(streamType), flags);
2005             }
2006 
2007             flags &= ~AudioManager.FLAG_FIXED_VOLUME;
2008             if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
2009                     ((device & mFixedVolumeDevices) != 0)) {
2010                 flags |= AudioManager.FLAG_FIXED_VOLUME;
2011 
2012                 // volume is either 0 or max allowed for fixed volume devices
2013                 if (index != 0) {
2014                     if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE &&
2015                             (device & mSafeMediaVolumeDevices) != 0) {
2016                         index = safeMediaVolumeIndex(device);
2017                     } else {
2018                         index = streamState.getMaxIndex();
2019                     }
2020                 }
2021             }
2022 
2023             if (!checkSafeMediaVolume(streamTypeAlias, index, device)) {
2024                 mVolumeController.postDisplaySafeVolumeWarning(flags);
2025                 mPendingVolumeCommand = new StreamVolumeCommand(
2026                                                     streamType, index, flags, device);
2027             } else {
2028                 onSetStreamVolume(streamType, index, flags, device, caller);
2029                 index = mStreamStates[streamType].getIndex(device);
2030             }
2031         }
2032         sendVolumeUpdate(streamType, oldIndex, index, flags);
2033     }
2034 
2035     // No ringer or zen muted stream volumes can be changed unless it'll exit dnd
volumeAdjustmentAllowedByDnd(int streamTypeAlias, int flags)2036     private boolean volumeAdjustmentAllowedByDnd(int streamTypeAlias, int flags) {
2037         switch (mNm.getZenMode()) {
2038             case Settings.Global.ZEN_MODE_OFF:
2039                 return true;
2040             case Settings.Global.ZEN_MODE_NO_INTERRUPTIONS:
2041             case Settings.Global.ZEN_MODE_ALARMS:
2042             case Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
2043                 return !isStreamMutedByRingerOrZenMode(streamTypeAlias)
2044                         || streamTypeAlias == getUiSoundsStreamType()
2045                         || (flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0;
2046         }
2047 
2048         return true;
2049     }
2050 
2051     /** @see AudioManager#forceVolumeControlStream(int) */
forceVolumeControlStream(int streamType, IBinder cb)2052     public void forceVolumeControlStream(int streamType, IBinder cb) {
2053         if (DEBUG_VOL) { Log.d(TAG, String.format("forceVolumeControlStream(%d)", streamType)); }
2054         synchronized(mForceControlStreamLock) {
2055             if (mVolumeControlStream != -1 && streamType != -1) {
2056                 mUserSelectedVolumeControlStream = true;
2057             }
2058             mVolumeControlStream = streamType;
2059             if (mVolumeControlStream == -1) {
2060                 if (mForceControlStreamClient != null) {
2061                     mForceControlStreamClient.release();
2062                     mForceControlStreamClient = null;
2063                 }
2064                 mUserSelectedVolumeControlStream = false;
2065             } else {
2066                 if (null == mForceControlStreamClient) {
2067                     mForceControlStreamClient = new ForceControlStreamClient(cb);
2068                 } else {
2069                     if (mForceControlStreamClient.getBinder() == cb) {
2070                         Log.d(TAG, "forceVolumeControlStream cb:" + cb + " is already linked.");
2071                     } else {
2072                         mForceControlStreamClient.release();
2073                         mForceControlStreamClient = new ForceControlStreamClient(cb);
2074                     }
2075                 }
2076             }
2077         }
2078     }
2079 
2080     private class ForceControlStreamClient implements IBinder.DeathRecipient {
2081         private IBinder mCb; // To be notified of client's death
2082 
ForceControlStreamClient(IBinder cb)2083         ForceControlStreamClient(IBinder cb) {
2084             if (cb != null) {
2085                 try {
2086                     cb.linkToDeath(this, 0);
2087                 } catch (RemoteException e) {
2088                     // Client has died!
2089                     Log.w(TAG, "ForceControlStreamClient() could not link to "+cb+" binder death");
2090                     cb = null;
2091                 }
2092             }
2093             mCb = cb;
2094         }
2095 
binderDied()2096         public void binderDied() {
2097             synchronized(mForceControlStreamLock) {
2098                 Log.w(TAG, "SCO client died");
2099                 if (mForceControlStreamClient != this) {
2100                     Log.w(TAG, "unregistered control stream client died");
2101                 } else {
2102                     mForceControlStreamClient = null;
2103                     mVolumeControlStream = -1;
2104                     mUserSelectedVolumeControlStream = false;
2105                 }
2106             }
2107         }
2108 
release()2109         public void release() {
2110             if (mCb != null) {
2111                 mCb.unlinkToDeath(this, 0);
2112                 mCb = null;
2113             }
2114         }
2115 
getBinder()2116         public IBinder getBinder() {
2117             return mCb;
2118         }
2119     }
2120 
sendBroadcastToAll(Intent intent)2121     private void sendBroadcastToAll(Intent intent) {
2122         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
2123         intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
2124         final long ident = Binder.clearCallingIdentity();
2125         try {
2126             mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
2127         } finally {
2128             Binder.restoreCallingIdentity(ident);
2129         }
2130     }
2131 
sendStickyBroadcastToAll(Intent intent)2132     private void sendStickyBroadcastToAll(Intent intent) {
2133         intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
2134         final long ident = Binder.clearCallingIdentity();
2135         try {
2136             mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
2137         } finally {
2138             Binder.restoreCallingIdentity(ident);
2139         }
2140     }
2141 
getCurrentUserId()2142     private int getCurrentUserId() {
2143         final long ident = Binder.clearCallingIdentity();
2144         try {
2145             UserInfo currentUser = ActivityManager.getService().getCurrentUser();
2146             return currentUser.id;
2147         } catch (RemoteException e) {
2148             // Activity manager not running, nothing we can do assume user 0.
2149         } finally {
2150             Binder.restoreCallingIdentity(ident);
2151         }
2152         return UserHandle.USER_SYSTEM;
2153     }
2154 
2155     // UI update and Broadcast Intent
sendVolumeUpdate(int streamType, int oldIndex, int index, int flags)2156     protected void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags) {
2157         streamType = mStreamVolumeAlias[streamType];
2158 
2159         if (streamType == AudioSystem.STREAM_MUSIC) {
2160             flags = updateFlagsForSystemAudio(flags);
2161         }
2162         mVolumeController.postVolumeChanged(streamType, flags);
2163     }
2164 
2165     // If Hdmi-CEC system audio mode is on, we show volume bar only when TV
2166     // receives volume notification from Audio Receiver.
updateFlagsForSystemAudio(int flags)2167     private int updateFlagsForSystemAudio(int flags) {
2168         if (mHdmiTvClient != null) {
2169             synchronized (mHdmiTvClient) {
2170                 if (mHdmiSystemAudioSupported &&
2171                         ((flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) == 0)) {
2172                     flags &= ~AudioManager.FLAG_SHOW_UI;
2173                 }
2174             }
2175         }
2176         return flags;
2177     }
2178 
2179     // UI update and Broadcast Intent
sendMasterMuteUpdate(boolean muted, int flags)2180     private void sendMasterMuteUpdate(boolean muted, int flags) {
2181         mVolumeController.postMasterMuteChanged(updateFlagsForSystemAudio(flags));
2182         broadcastMasterMuteStatus(muted);
2183     }
2184 
broadcastMasterMuteStatus(boolean muted)2185     private void broadcastMasterMuteStatus(boolean muted) {
2186         Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION);
2187         intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, muted);
2188         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
2189                 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
2190         sendStickyBroadcastToAll(intent);
2191     }
2192 
2193     /**
2194      * Sets the stream state's index, and posts a message to set system volume.
2195      * This will not call out to the UI. Assumes a valid stream type.
2196      *
2197      * @param streamType Type of the stream
2198      * @param index Desired volume index of the stream
2199      * @param device the device whose volume must be changed
2200      * @param force If true, set the volume even if the desired volume is same
2201      * as the current volume.
2202      */
setStreamVolumeInt(int streamType, int index, int device, boolean force, String caller)2203     private void setStreamVolumeInt(int streamType,
2204                                     int index,
2205                                     int device,
2206                                     boolean force,
2207                                     String caller) {
2208         VolumeStreamState streamState = mStreamStates[streamType];
2209 
2210         if (streamState.setIndex(index, device, caller) || force) {
2211             // Post message to set system volume (it in turn will post a message
2212             // to persist).
2213             sendMsg(mAudioHandler,
2214                     MSG_SET_DEVICE_VOLUME,
2215                     SENDMSG_QUEUE,
2216                     device,
2217                     0,
2218                     streamState,
2219                     0);
2220         }
2221     }
2222 
setSystemAudioMute(boolean state)2223     private void setSystemAudioMute(boolean state) {
2224         if (mHdmiManager == null || mHdmiTvClient == null) return;
2225         synchronized (mHdmiManager) {
2226             if (!mHdmiSystemAudioSupported) return;
2227             synchronized (mHdmiTvClient) {
2228                 final long token = Binder.clearCallingIdentity();
2229                 try {
2230                     mHdmiTvClient.setSystemAudioMute(state);
2231                 } finally {
2232                     Binder.restoreCallingIdentity(token);
2233                 }
2234             }
2235         }
2236     }
2237 
2238     /** get stream mute state. */
isStreamMute(int streamType)2239     public boolean isStreamMute(int streamType) {
2240         if (streamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
2241             streamType = getActiveStreamType(streamType);
2242         }
2243         synchronized (VolumeStreamState.class) {
2244             ensureValidStreamType(streamType);
2245             return mStreamStates[streamType].mIsMuted;
2246         }
2247     }
2248 
2249     private class RmtSbmxFullVolDeathHandler implements IBinder.DeathRecipient {
2250         private IBinder mICallback; // To be notified of client's death
2251 
RmtSbmxFullVolDeathHandler(IBinder cb)2252         RmtSbmxFullVolDeathHandler(IBinder cb) {
2253             mICallback = cb;
2254             try {
2255                 cb.linkToDeath(this, 0/*flags*/);
2256             } catch (RemoteException e) {
2257                 Log.e(TAG, "can't link to death", e);
2258             }
2259         }
2260 
isHandlerFor(IBinder cb)2261         boolean isHandlerFor(IBinder cb) {
2262             return mICallback.equals(cb);
2263         }
2264 
forget()2265         void forget() {
2266             try {
2267                 mICallback.unlinkToDeath(this, 0/*flags*/);
2268             } catch (NoSuchElementException e) {
2269                 Log.e(TAG, "error unlinking to death", e);
2270             }
2271         }
2272 
binderDied()2273         public void binderDied() {
2274             Log.w(TAG, "Recorder with remote submix at full volume died " + mICallback);
2275             forceRemoteSubmixFullVolume(false, mICallback);
2276         }
2277     }
2278 
2279     /**
2280      * call must be synchronized on mRmtSbmxFullVolDeathHandlers
2281      * @return true if there is a registered death handler, false otherwise */
discardRmtSbmxFullVolDeathHandlerFor(IBinder cb)2282     private boolean discardRmtSbmxFullVolDeathHandlerFor(IBinder cb) {
2283         Iterator<RmtSbmxFullVolDeathHandler> it = mRmtSbmxFullVolDeathHandlers.iterator();
2284         while (it.hasNext()) {
2285             final RmtSbmxFullVolDeathHandler handler = it.next();
2286             if (handler.isHandlerFor(cb)) {
2287                 handler.forget();
2288                 mRmtSbmxFullVolDeathHandlers.remove(handler);
2289                 return true;
2290             }
2291         }
2292         return false;
2293     }
2294 
2295     /** call synchronized on mRmtSbmxFullVolDeathHandlers */
hasRmtSbmxFullVolDeathHandlerFor(IBinder cb)2296     private boolean hasRmtSbmxFullVolDeathHandlerFor(IBinder cb) {
2297         Iterator<RmtSbmxFullVolDeathHandler> it = mRmtSbmxFullVolDeathHandlers.iterator();
2298         while (it.hasNext()) {
2299             if (it.next().isHandlerFor(cb)) {
2300                 return true;
2301             }
2302         }
2303         return false;
2304     }
2305 
2306     private int mRmtSbmxFullVolRefCount = 0;
2307     private ArrayList<RmtSbmxFullVolDeathHandler> mRmtSbmxFullVolDeathHandlers =
2308             new ArrayList<RmtSbmxFullVolDeathHandler>();
2309 
forceRemoteSubmixFullVolume(boolean startForcing, IBinder cb)2310     public void forceRemoteSubmixFullVolume(boolean startForcing, IBinder cb) {
2311         if (cb == null) {
2312             return;
2313         }
2314         if ((PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission(
2315                         android.Manifest.permission.CAPTURE_AUDIO_OUTPUT))) {
2316             Log.w(TAG, "Trying to call forceRemoteSubmixFullVolume() without CAPTURE_AUDIO_OUTPUT");
2317             return;
2318         }
2319         synchronized(mRmtSbmxFullVolDeathHandlers) {
2320             boolean applyRequired = false;
2321             if (startForcing) {
2322                 if (!hasRmtSbmxFullVolDeathHandlerFor(cb)) {
2323                     mRmtSbmxFullVolDeathHandlers.add(new RmtSbmxFullVolDeathHandler(cb));
2324                     if (mRmtSbmxFullVolRefCount == 0) {
2325                         mFullVolumeDevices |= AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
2326                         mFixedVolumeDevices |= AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
2327                         applyRequired = true;
2328                     }
2329                     mRmtSbmxFullVolRefCount++;
2330                 }
2331             } else {
2332                 if (discardRmtSbmxFullVolDeathHandlerFor(cb) && (mRmtSbmxFullVolRefCount > 0)) {
2333                     mRmtSbmxFullVolRefCount--;
2334                     if (mRmtSbmxFullVolRefCount == 0) {
2335                         mFullVolumeDevices &= ~AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
2336                         mFixedVolumeDevices &= ~AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
2337                         applyRequired = true;
2338                     }
2339                 }
2340             }
2341             if (applyRequired) {
2342                 // Assumes only STREAM_MUSIC going through DEVICE_OUT_REMOTE_SUBMIX
2343                 checkAllFixedVolumeDevices(AudioSystem.STREAM_MUSIC);
2344                 mStreamStates[AudioSystem.STREAM_MUSIC].applyAllVolumes();
2345             }
2346         }
2347     }
2348 
setMasterMuteInternal(boolean mute, int flags, String callingPackage, int uid, int userId)2349     private void setMasterMuteInternal(boolean mute, int flags, String callingPackage, int uid,
2350             int userId) {
2351         // If we are being called by the system check for user we are going to change
2352         // so we handle user restrictions correctly.
2353         if (uid == android.os.Process.SYSTEM_UID) {
2354             uid = UserHandle.getUid(userId, UserHandle.getAppId(uid));
2355         }
2356         // If OP_AUDIO_MASTER_VOLUME is set, disallow unmuting.
2357         if (!mute && mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, uid, callingPackage)
2358                 != AppOpsManager.MODE_ALLOWED) {
2359             return;
2360         }
2361         if (userId != UserHandle.getCallingUserId() &&
2362                 mContext.checkCallingOrSelfPermission(
2363                         android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
2364                 != PackageManager.PERMISSION_GRANTED) {
2365             return;
2366         }
2367         setMasterMuteInternalNoCallerCheck(mute, flags, userId);
2368     }
2369 
setMasterMuteInternalNoCallerCheck(boolean mute, int flags, int userId)2370     private void setMasterMuteInternalNoCallerCheck(boolean mute, int flags, int userId) {
2371         if (DEBUG_VOL) {
2372             Log.d(TAG, String.format("Master mute %s, %d, user=%d", mute, flags, userId));
2373         }
2374         if (!isPlatformAutomotive() && mUseFixedVolume) {
2375             // If using fixed volume, we don't mute.
2376             // TODO: remove the isPlatformAutomotive check here.
2377             // The isPlatformAutomotive check is added for safety but may not be necessary.
2378             return;
2379         }
2380         if (getCurrentUserId() == userId) {
2381             if (mute != AudioSystem.getMasterMute()) {
2382                 setSystemAudioMute(mute);
2383                 AudioSystem.setMasterMute(mute);
2384                 sendMasterMuteUpdate(mute, flags);
2385 
2386                 Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION);
2387                 intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, mute);
2388                 sendBroadcastToAll(intent);
2389             }
2390         }
2391     }
2392 
2393     /** get master mute state. */
isMasterMute()2394     public boolean isMasterMute() {
2395         return AudioSystem.getMasterMute();
2396     }
2397 
setMasterMute(boolean mute, int flags, String callingPackage, int userId)2398     public void setMasterMute(boolean mute, int flags, String callingPackage, int userId) {
2399         setMasterMuteInternal(mute, flags, callingPackage, Binder.getCallingUid(),
2400                 userId);
2401     }
2402 
2403     /** @see AudioManager#getStreamVolume(int) */
getStreamVolume(int streamType)2404     public int getStreamVolume(int streamType) {
2405         ensureValidStreamType(streamType);
2406         int device = getDeviceForStream(streamType);
2407         synchronized (VolumeStreamState.class) {
2408             int index = mStreamStates[streamType].getIndex(device);
2409 
2410             // by convention getStreamVolume() returns 0 when a stream is muted.
2411             if (mStreamStates[streamType].mIsMuted) {
2412                 index = 0;
2413             }
2414             if (index != 0 && (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
2415                     (device & mFixedVolumeDevices) != 0) {
2416                 index = mStreamStates[streamType].getMaxIndex();
2417             }
2418             return (index + 5) / 10;
2419         }
2420     }
2421 
2422     /** @see AudioManager#getStreamMaxVolume(int) */
getStreamMaxVolume(int streamType)2423     public int getStreamMaxVolume(int streamType) {
2424         ensureValidStreamType(streamType);
2425         return (mStreamStates[streamType].getMaxIndex() + 5) / 10;
2426     }
2427 
2428     /** @see AudioManager#getStreamMinVolumeInt(int) */
getStreamMinVolume(int streamType)2429     public int getStreamMinVolume(int streamType) {
2430         ensureValidStreamType(streamType);
2431         return (mStreamStates[streamType].getMinIndex() + 5) / 10;
2432     }
2433 
2434     /** Get last audible volume before stream was muted. */
getLastAudibleStreamVolume(int streamType)2435     public int getLastAudibleStreamVolume(int streamType) {
2436         ensureValidStreamType(streamType);
2437         int device = getDeviceForStream(streamType);
2438         return (mStreamStates[streamType].getIndex(device) + 5) / 10;
2439     }
2440 
2441     /** @see AudioManager#getUiSoundsStreamType()  */
getUiSoundsStreamType()2442     public int getUiSoundsStreamType() {
2443         return mStreamVolumeAlias[AudioSystem.STREAM_SYSTEM];
2444     }
2445 
2446     /** @see AudioManager#setMicrophoneMute(boolean) */
2447     @Override
setMicrophoneMute(boolean on, String callingPackage, int userId)2448     public void setMicrophoneMute(boolean on, String callingPackage, int userId) {
2449         // If we are being called by the system check for user we are going to change
2450         // so we handle user restrictions correctly.
2451         int uid = Binder.getCallingUid();
2452         if (uid == android.os.Process.SYSTEM_UID) {
2453             uid = UserHandle.getUid(userId, UserHandle.getAppId(uid));
2454         }
2455         // If OP_MUTE_MICROPHONE is set, disallow unmuting.
2456         if (!on && mAppOps.noteOp(AppOpsManager.OP_MUTE_MICROPHONE, uid, callingPackage)
2457                 != AppOpsManager.MODE_ALLOWED) {
2458             return;
2459         }
2460         if (!checkAudioSettingsPermission("setMicrophoneMute()")) {
2461             return;
2462         }
2463         if (userId != UserHandle.getCallingUserId() &&
2464                 mContext.checkCallingOrSelfPermission(
2465                 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
2466                 != PackageManager.PERMISSION_GRANTED) {
2467             return;
2468         }
2469         setMicrophoneMuteNoCallerCheck(on, userId);
2470     }
2471 
setMicrophoneMuteNoCallerCheck(boolean on, int userId)2472     private void setMicrophoneMuteNoCallerCheck(boolean on, int userId) {
2473         if (DEBUG_VOL) {
2474             Log.d(TAG, String.format("Mic mute %s, user=%d", on, userId));
2475         }
2476         // only mute for the current user
2477         if (getCurrentUserId() == userId) {
2478             final boolean currentMute = AudioSystem.isMicrophoneMuted();
2479             final long identity = Binder.clearCallingIdentity();
2480             AudioSystem.muteMicrophone(on);
2481             Binder.restoreCallingIdentity(identity);
2482             if (on != currentMute) {
2483                 mContext.sendBroadcast(new Intent(AudioManager.ACTION_MICROPHONE_MUTE_CHANGED)
2484                         .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY));
2485             }
2486         }
2487     }
2488 
2489     @Override
getRingerModeExternal()2490     public int getRingerModeExternal() {
2491         synchronized(mSettingsLock) {
2492             return mRingerModeExternal;
2493         }
2494     }
2495 
2496     @Override
getRingerModeInternal()2497     public int getRingerModeInternal() {
2498         synchronized(mSettingsLock) {
2499             return mRingerMode;
2500         }
2501     }
2502 
ensureValidRingerMode(int ringerMode)2503     private void ensureValidRingerMode(int ringerMode) {
2504         if (!isValidRingerMode(ringerMode)) {
2505             throw new IllegalArgumentException("Bad ringer mode " + ringerMode);
2506         }
2507     }
2508 
2509     /** @see AudioManager#isValidRingerMode(int) */
isValidRingerMode(int ringerMode)2510     public boolean isValidRingerMode(int ringerMode) {
2511         return ringerMode >= 0 && ringerMode <= AudioManager.RINGER_MODE_MAX;
2512     }
2513 
setRingerModeExternal(int ringerMode, String caller)2514     public void setRingerModeExternal(int ringerMode, String caller) {
2515         if (isAndroidNPlus(caller) && wouldToggleZenMode(ringerMode)
2516                 && !mNm.isNotificationPolicyAccessGrantedForPackage(caller)) {
2517             throw new SecurityException("Not allowed to change Do Not Disturb state");
2518         }
2519 
2520         setRingerMode(ringerMode, caller, true /*external*/);
2521     }
2522 
setRingerModeInternal(int ringerMode, String caller)2523     public void setRingerModeInternal(int ringerMode, String caller) {
2524         enforceVolumeController("setRingerModeInternal");
2525         setRingerMode(ringerMode, caller, false /*external*/);
2526     }
2527 
silenceRingerModeInternal(String reason)2528     public void silenceRingerModeInternal(String reason) {
2529         VibrationEffect effect = null;
2530         int ringerMode = AudioManager.RINGER_MODE_SILENT;
2531         int toastText = 0;
2532 
2533         int silenceRingerSetting = Settings.Secure.VOLUME_HUSH_OFF;
2534         if (mContext.getResources()
2535                 .getBoolean(com.android.internal.R.bool.config_volumeHushGestureEnabled)) {
2536             silenceRingerSetting = Settings.Secure.getIntForUser(mContentResolver,
2537                     Settings.Secure.VOLUME_HUSH_GESTURE, VOLUME_HUSH_OFF,
2538                     UserHandle.USER_CURRENT);
2539         }
2540 
2541         switch(silenceRingerSetting) {
2542             case VOLUME_HUSH_MUTE:
2543                 effect = VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK);
2544                 ringerMode = AudioManager.RINGER_MODE_SILENT;
2545                 toastText = com.android.internal.R.string.volume_dialog_ringer_guidance_silent;
2546                 break;
2547             case VOLUME_HUSH_VIBRATE:
2548                 effect = VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK);
2549                 ringerMode = AudioManager.RINGER_MODE_VIBRATE;
2550                 toastText = com.android.internal.R.string.volume_dialog_ringer_guidance_vibrate;
2551                 break;
2552         }
2553         maybeVibrate(effect);
2554         setRingerModeInternal(ringerMode, reason);
2555         Toast.makeText(mContext, toastText, Toast.LENGTH_SHORT).show();
2556     }
2557 
maybeVibrate(VibrationEffect effect)2558     private boolean maybeVibrate(VibrationEffect effect) {
2559         if (!mHasVibrator) {
2560             return false;
2561         }
2562         final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(),
2563                 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
2564         if (hapticsDisabled) {
2565             return false;
2566         }
2567 
2568         if (effect == null) {
2569             return false;
2570         }
2571         mVibrator.vibrate(
2572                 Binder.getCallingUid(), mContext.getOpPackageName(), effect, VIBRATION_ATTRIBUTES);
2573         return true;
2574     }
2575 
setRingerMode(int ringerMode, String caller, boolean external)2576     private void setRingerMode(int ringerMode, String caller, boolean external) {
2577         if (mUseFixedVolume || mIsSingleVolume) {
2578             return;
2579         }
2580         if (caller == null || caller.length() == 0) {
2581             throw new IllegalArgumentException("Bad caller: " + caller);
2582         }
2583         ensureValidRingerMode(ringerMode);
2584         if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) {
2585             ringerMode = AudioManager.RINGER_MODE_SILENT;
2586         }
2587         final long identity = Binder.clearCallingIdentity();
2588         try {
2589             synchronized (mSettingsLock) {
2590                 final int ringerModeInternal = getRingerModeInternal();
2591                 final int ringerModeExternal = getRingerModeExternal();
2592                 if (external) {
2593                     setRingerModeExt(ringerMode);
2594                     if (mRingerModeDelegate != null) {
2595                         ringerMode = mRingerModeDelegate.onSetRingerModeExternal(ringerModeExternal,
2596                                 ringerMode, caller, ringerModeInternal, mVolumePolicy);
2597                     }
2598                     if (ringerMode != ringerModeInternal) {
2599                         setRingerModeInt(ringerMode, true /*persist*/);
2600                     }
2601                 } else /*internal*/ {
2602                     if (ringerMode != ringerModeInternal) {
2603                         setRingerModeInt(ringerMode, true /*persist*/);
2604                     }
2605                     if (mRingerModeDelegate != null) {
2606                         ringerMode = mRingerModeDelegate.onSetRingerModeInternal(ringerModeInternal,
2607                                 ringerMode, caller, ringerModeExternal, mVolumePolicy);
2608                     }
2609                     setRingerModeExt(ringerMode);
2610                 }
2611             }
2612         } finally {
2613             Binder.restoreCallingIdentity(identity);
2614         }
2615     }
2616 
setRingerModeExt(int ringerMode)2617     private void setRingerModeExt(int ringerMode) {
2618         synchronized(mSettingsLock) {
2619             if (ringerMode == mRingerModeExternal) return;
2620             mRingerModeExternal = ringerMode;
2621         }
2622         // Send sticky broadcast
2623         broadcastRingerMode(AudioManager.RINGER_MODE_CHANGED_ACTION, ringerMode);
2624     }
2625 
2626     @GuardedBy("mSettingsLock")
muteRingerModeStreams()2627     private void muteRingerModeStreams() {
2628         // Mute stream if not previously muted by ringer mode and (ringer mode
2629         // is not RINGER_MODE_NORMAL OR stream is zen muted) and stream is affected by ringer mode.
2630         // Unmute stream if previously muted by ringer/zen mode and ringer mode
2631         // is RINGER_MODE_NORMAL or stream is not affected by ringer mode.
2632         int numStreamTypes = AudioSystem.getNumStreamTypes();
2633 
2634         if (mNm == null) {
2635             mNm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
2636         }
2637 
2638         final int ringerMode = mRingerMode; // Read ringer mode as reading primitives is atomic
2639         final boolean ringerModeMute = ringerMode == AudioManager.RINGER_MODE_VIBRATE
2640                 || ringerMode == AudioManager.RINGER_MODE_SILENT;
2641         final boolean shouldRingSco = ringerMode == AudioManager.RINGER_MODE_VIBRATE
2642                 && isBluetoothScoOn();
2643         // Ask audio policy engine to force use Bluetooth SCO channel if needed
2644         final String eventSource = "muteRingerModeStreams() from u/pid:" + Binder.getCallingUid()
2645                 + "/" + Binder.getCallingPid();
2646         sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, AudioSystem.FOR_VIBRATE_RINGING,
2647                 shouldRingSco ? AudioSystem.FORCE_BT_SCO : AudioSystem.FORCE_NONE, eventSource, 0);
2648 
2649         for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
2650             final boolean isMuted = isStreamMutedByRingerOrZenMode(streamType);
2651             final boolean muteAllowedBySco =
2652                     !(shouldRingSco && streamType == AudioSystem.STREAM_RING);
2653             final boolean shouldZenMute = shouldZenMuteStream(streamType);
2654             final boolean shouldMute = shouldZenMute || (ringerModeMute
2655                     && isStreamAffectedByRingerMode(streamType) && muteAllowedBySco);
2656             if (isMuted == shouldMute) continue;
2657             if (!shouldMute) {
2658                 // unmute
2659                 // ring and notifications volume should never be 0 when not silenced
2660                 if (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_RING) {
2661                     synchronized (VolumeStreamState.class) {
2662                         final VolumeStreamState vss = mStreamStates[streamType];
2663                         for (int i = 0; i < vss.mIndexMap.size(); i++) {
2664                             int device = vss.mIndexMap.keyAt(i);
2665                             int value = vss.mIndexMap.valueAt(i);
2666                             if (value == 0) {
2667                                 vss.setIndex(10, device, TAG);
2668                             }
2669                         }
2670                         // Persist volume for stream ring when it is changed here
2671                       final int device = getDeviceForStream(streamType);
2672                       sendMsg(mAudioHandler,
2673                               MSG_PERSIST_VOLUME,
2674                               SENDMSG_QUEUE,
2675                               device,
2676                               0,
2677                               mStreamStates[streamType],
2678                               PERSIST_DELAY);
2679                     }
2680                 }
2681                 mStreamStates[streamType].mute(false);
2682                 mRingerAndZenModeMutedStreams &= ~(1 << streamType);
2683             } else {
2684                 // mute
2685                 mStreamStates[streamType].mute(true);
2686                 mRingerAndZenModeMutedStreams |= (1 << streamType);
2687             }
2688         }
2689     }
2690 
isAlarm(int streamType)2691     private boolean isAlarm(int streamType) {
2692         return streamType == AudioSystem.STREAM_ALARM;
2693     }
2694 
isNotificationOrRinger(int streamType)2695     private boolean isNotificationOrRinger(int streamType) {
2696         return streamType == AudioSystem.STREAM_NOTIFICATION
2697                 || streamType == AudioSystem.STREAM_RING;
2698     }
2699 
isMedia(int streamType)2700     private boolean isMedia(int streamType) {
2701         return streamType == AudioSystem.STREAM_MUSIC;
2702     }
2703 
2704 
isSystem(int streamType)2705     private boolean isSystem(int streamType) {
2706         return streamType == AudioSystem.STREAM_SYSTEM;
2707     }
2708 
setRingerModeInt(int ringerMode, boolean persist)2709     private void setRingerModeInt(int ringerMode, boolean persist) {
2710         final boolean change;
2711         synchronized(mSettingsLock) {
2712             change = mRingerMode != ringerMode;
2713             mRingerMode = ringerMode;
2714             muteRingerModeStreams();
2715         }
2716 
2717         // Post a persist ringer mode msg
2718         if (persist) {
2719             sendMsg(mAudioHandler, MSG_PERSIST_RINGER_MODE,
2720                     SENDMSG_REPLACE, 0, 0, null, PERSIST_DELAY);
2721         }
2722         if (change) {
2723             // Send sticky broadcast
2724             broadcastRingerMode(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION, ringerMode);
2725         }
2726     }
2727 
2728     /** @see AudioManager#shouldVibrate(int) */
shouldVibrate(int vibrateType)2729     public boolean shouldVibrate(int vibrateType) {
2730         if (!mHasVibrator) return false;
2731 
2732         switch (getVibrateSetting(vibrateType)) {
2733 
2734             case AudioManager.VIBRATE_SETTING_ON:
2735                 return getRingerModeExternal() != AudioManager.RINGER_MODE_SILENT;
2736 
2737             case AudioManager.VIBRATE_SETTING_ONLY_SILENT:
2738                 return getRingerModeExternal() == AudioManager.RINGER_MODE_VIBRATE;
2739 
2740             case AudioManager.VIBRATE_SETTING_OFF:
2741                 // return false, even for incoming calls
2742                 return false;
2743 
2744             default:
2745                 return false;
2746         }
2747     }
2748 
2749     /** @see AudioManager#getVibrateSetting(int) */
getVibrateSetting(int vibrateType)2750     public int getVibrateSetting(int vibrateType) {
2751         if (!mHasVibrator) return AudioManager.VIBRATE_SETTING_OFF;
2752         return (mVibrateSetting >> (vibrateType * 2)) & 3;
2753     }
2754 
2755     /** @see AudioManager#setVibrateSetting(int, int) */
setVibrateSetting(int vibrateType, int vibrateSetting)2756     public void setVibrateSetting(int vibrateType, int vibrateSetting) {
2757 
2758         if (!mHasVibrator) return;
2759 
2760         mVibrateSetting = AudioSystem.getValueForVibrateSetting(mVibrateSetting, vibrateType,
2761                 vibrateSetting);
2762 
2763         // Broadcast change
2764         broadcastVibrateSetting(vibrateType);
2765 
2766     }
2767 
2768     private class SetModeDeathHandler implements IBinder.DeathRecipient {
2769         private IBinder mCb; // To be notified of client's death
2770         private int mPid;
2771         private int mMode = AudioSystem.MODE_NORMAL; // Current mode set by this client
2772 
SetModeDeathHandler(IBinder cb, int pid)2773         SetModeDeathHandler(IBinder cb, int pid) {
2774             mCb = cb;
2775             mPid = pid;
2776         }
2777 
binderDied()2778         public void binderDied() {
2779             int oldModeOwnerPid = 0;
2780             int newModeOwnerPid = 0;
2781             synchronized(mSetModeDeathHandlers) {
2782                 Log.w(TAG, "setMode() client died");
2783                 if (!mSetModeDeathHandlers.isEmpty()) {
2784                     oldModeOwnerPid = mSetModeDeathHandlers.get(0).getPid();
2785                 }
2786                 int index = mSetModeDeathHandlers.indexOf(this);
2787                 if (index < 0) {
2788                     Log.w(TAG, "unregistered setMode() client died");
2789                 } else {
2790                     newModeOwnerPid = setModeInt(AudioSystem.MODE_NORMAL, mCb, mPid, TAG);
2791                 }
2792             }
2793             // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
2794             // SCO connections not started by the application changing the mode when pid changes
2795             if ((newModeOwnerPid != oldModeOwnerPid) && (newModeOwnerPid != 0)) {
2796                 final long ident = Binder.clearCallingIdentity();
2797                 disconnectBluetoothSco(newModeOwnerPid);
2798                 Binder.restoreCallingIdentity(ident);
2799             }
2800         }
2801 
getPid()2802         public int getPid() {
2803             return mPid;
2804         }
2805 
setMode(int mode)2806         public void setMode(int mode) {
2807             mMode = mode;
2808         }
2809 
getMode()2810         public int getMode() {
2811             return mMode;
2812         }
2813 
getBinder()2814         public IBinder getBinder() {
2815             return mCb;
2816         }
2817     }
2818 
2819     /** @see AudioManager#setMode(int) */
setMode(int mode, IBinder cb, String callingPackage)2820     public void setMode(int mode, IBinder cb, String callingPackage) {
2821         if (DEBUG_MODE) { Log.v(TAG, "setMode(mode=" + mode + ", callingPackage=" + callingPackage + ")"); }
2822         if (!checkAudioSettingsPermission("setMode()")) {
2823             return;
2824         }
2825 
2826         if ( (mode == AudioSystem.MODE_IN_CALL) &&
2827                 (mContext.checkCallingOrSelfPermission(
2828                         android.Manifest.permission.MODIFY_PHONE_STATE)
2829                             != PackageManager.PERMISSION_GRANTED)) {
2830             Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: setMode(MODE_IN_CALL) from pid="
2831                     + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
2832             return;
2833         }
2834 
2835         if (mode < AudioSystem.MODE_CURRENT || mode >= AudioSystem.NUM_MODES) {
2836             return;
2837         }
2838 
2839         int oldModeOwnerPid = 0;
2840         int newModeOwnerPid = 0;
2841         synchronized(mSetModeDeathHandlers) {
2842             if (!mSetModeDeathHandlers.isEmpty()) {
2843                 oldModeOwnerPid = mSetModeDeathHandlers.get(0).getPid();
2844             }
2845             if (mode == AudioSystem.MODE_CURRENT) {
2846                 mode = mMode;
2847             }
2848             newModeOwnerPid = setModeInt(mode, cb, Binder.getCallingPid(), callingPackage);
2849         }
2850         // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
2851         // SCO connections not started by the application changing the mode when pid changes
2852         if ((newModeOwnerPid != oldModeOwnerPid) && (newModeOwnerPid != 0)) {
2853             disconnectBluetoothSco(newModeOwnerPid);
2854         }
2855     }
2856 
2857     // must be called synchronized on mSetModeDeathHandlers
2858     // setModeInt() returns a valid PID if the audio mode was successfully set to
2859     // any mode other than NORMAL.
setModeInt(int mode, IBinder cb, int pid, String caller)2860     private int setModeInt(int mode, IBinder cb, int pid, String caller) {
2861         if (DEBUG_MODE) { Log.v(TAG, "setModeInt(mode=" + mode + ", pid=" + pid + ", caller="
2862                 + caller + ")"); }
2863         int newModeOwnerPid = 0;
2864         if (cb == null) {
2865             Log.e(TAG, "setModeInt() called with null binder");
2866             return newModeOwnerPid;
2867         }
2868 
2869         SetModeDeathHandler hdlr = null;
2870         Iterator iter = mSetModeDeathHandlers.iterator();
2871         while (iter.hasNext()) {
2872             SetModeDeathHandler h = (SetModeDeathHandler)iter.next();
2873             if (h.getPid() == pid) {
2874                 hdlr = h;
2875                 // Remove from client list so that it is re-inserted at top of list
2876                 iter.remove();
2877                 hdlr.getBinder().unlinkToDeath(hdlr, 0);
2878                 break;
2879             }
2880         }
2881         int status = AudioSystem.AUDIO_STATUS_OK;
2882         int actualMode;
2883         do {
2884             actualMode = mode;
2885             if (mode == AudioSystem.MODE_NORMAL) {
2886                 // get new mode from client at top the list if any
2887                 if (!mSetModeDeathHandlers.isEmpty()) {
2888                     hdlr = mSetModeDeathHandlers.get(0);
2889                     cb = hdlr.getBinder();
2890                     actualMode = hdlr.getMode();
2891                     if (DEBUG_MODE) {
2892                         Log.w(TAG, " using mode=" + mode + " instead due to death hdlr at pid="
2893                                 + hdlr.mPid);
2894                     }
2895                 }
2896             } else {
2897                 if (hdlr == null) {
2898                     hdlr = new SetModeDeathHandler(cb, pid);
2899                 }
2900                 // Register for client death notification
2901                 try {
2902                     cb.linkToDeath(hdlr, 0);
2903                 } catch (RemoteException e) {
2904                     // Client has died!
2905                     Log.w(TAG, "setMode() could not link to "+cb+" binder death");
2906                 }
2907 
2908                 // Last client to call setMode() is always at top of client list
2909                 // as required by SetModeDeathHandler.binderDied()
2910                 mSetModeDeathHandlers.add(0, hdlr);
2911                 hdlr.setMode(mode);
2912             }
2913 
2914             if (actualMode != mMode) {
2915                 final long identity = Binder.clearCallingIdentity();
2916                 status = AudioSystem.setPhoneState(actualMode);
2917                 Binder.restoreCallingIdentity(identity);
2918                 if (status == AudioSystem.AUDIO_STATUS_OK) {
2919                     if (DEBUG_MODE) { Log.v(TAG, " mode successfully set to " + actualMode); }
2920                     mMode = actualMode;
2921                 } else {
2922                     if (hdlr != null) {
2923                         mSetModeDeathHandlers.remove(hdlr);
2924                         cb.unlinkToDeath(hdlr, 0);
2925                     }
2926                     // force reading new top of mSetModeDeathHandlers stack
2927                     if (DEBUG_MODE) { Log.w(TAG, " mode set to MODE_NORMAL after phoneState pb"); }
2928                     mode = AudioSystem.MODE_NORMAL;
2929                 }
2930             } else {
2931                 status = AudioSystem.AUDIO_STATUS_OK;
2932             }
2933         } while (status != AudioSystem.AUDIO_STATUS_OK && !mSetModeDeathHandlers.isEmpty());
2934 
2935         if (status == AudioSystem.AUDIO_STATUS_OK) {
2936             if (actualMode != AudioSystem.MODE_NORMAL) {
2937                 if (mSetModeDeathHandlers.isEmpty()) {
2938                     Log.e(TAG, "setMode() different from MODE_NORMAL with empty mode client stack");
2939                 } else {
2940                     newModeOwnerPid = mSetModeDeathHandlers.get(0).getPid();
2941                 }
2942             }
2943             // Note: newModeOwnerPid is always 0 when actualMode is MODE_NORMAL
2944             mModeLogger.log(
2945                     new PhoneStateEvent(caller, pid, mode, newModeOwnerPid, actualMode));
2946             int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE);
2947             int device = getDeviceForStream(streamType);
2948             int index = mStreamStates[mStreamVolumeAlias[streamType]].getIndex(device);
2949             setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, true, caller);
2950 
2951             updateStreamVolumeAlias(true /*updateVolumes*/, caller);
2952         }
2953         return newModeOwnerPid;
2954     }
2955 
2956     /** @see AudioManager#getMode() */
getMode()2957     public int getMode() {
2958         return mMode;
2959     }
2960 
2961     //==========================================================================================
2962     // Sound Effects
2963     //==========================================================================================
2964 
2965     private static final String TAG_AUDIO_ASSETS = "audio_assets";
2966     private static final String ATTR_VERSION = "version";
2967     private static final String TAG_GROUP = "group";
2968     private static final String ATTR_GROUP_NAME = "name";
2969     private static final String TAG_ASSET = "asset";
2970     private static final String ATTR_ASSET_ID = "id";
2971     private static final String ATTR_ASSET_FILE = "file";
2972 
2973     private static final String ASSET_FILE_VERSION = "1.0";
2974     private static final String GROUP_TOUCH_SOUNDS = "touch_sounds";
2975 
2976     private static final int SOUND_EFFECTS_LOAD_TIMEOUT_MS = 5000;
2977 
2978     class LoadSoundEffectReply {
2979         public int mStatus = 1;
2980     };
2981 
loadTouchSoundAssetDefaults()2982     private void loadTouchSoundAssetDefaults() {
2983         SOUND_EFFECT_FILES.add("Effect_Tick.ogg");
2984         for (int i = 0; i < AudioManager.NUM_SOUND_EFFECTS; i++) {
2985             SOUND_EFFECT_FILES_MAP[i][0] = 0;
2986             SOUND_EFFECT_FILES_MAP[i][1] = -1;
2987         }
2988     }
2989 
loadTouchSoundAssets()2990     private void loadTouchSoundAssets() {
2991         XmlResourceParser parser = null;
2992 
2993         // only load assets once.
2994         if (!SOUND_EFFECT_FILES.isEmpty()) {
2995             return;
2996         }
2997 
2998         loadTouchSoundAssetDefaults();
2999 
3000         try {
3001             parser = mContext.getResources().getXml(com.android.internal.R.xml.audio_assets);
3002 
3003             XmlUtils.beginDocument(parser, TAG_AUDIO_ASSETS);
3004             String version = parser.getAttributeValue(null, ATTR_VERSION);
3005             boolean inTouchSoundsGroup = false;
3006 
3007             if (ASSET_FILE_VERSION.equals(version)) {
3008                 while (true) {
3009                     XmlUtils.nextElement(parser);
3010                     String element = parser.getName();
3011                     if (element == null) {
3012                         break;
3013                     }
3014                     if (element.equals(TAG_GROUP)) {
3015                         String name = parser.getAttributeValue(null, ATTR_GROUP_NAME);
3016                         if (GROUP_TOUCH_SOUNDS.equals(name)) {
3017                             inTouchSoundsGroup = true;
3018                             break;
3019                         }
3020                     }
3021                 }
3022                 while (inTouchSoundsGroup) {
3023                     XmlUtils.nextElement(parser);
3024                     String element = parser.getName();
3025                     if (element == null) {
3026                         break;
3027                     }
3028                     if (element.equals(TAG_ASSET)) {
3029                         String id = parser.getAttributeValue(null, ATTR_ASSET_ID);
3030                         String file = parser.getAttributeValue(null, ATTR_ASSET_FILE);
3031                         int fx;
3032 
3033                         try {
3034                             Field field = AudioManager.class.getField(id);
3035                             fx = field.getInt(null);
3036                         } catch (Exception e) {
3037                             Log.w(TAG, "Invalid touch sound ID: "+id);
3038                             continue;
3039                         }
3040 
3041                         int i = SOUND_EFFECT_FILES.indexOf(file);
3042                         if (i == -1) {
3043                             i = SOUND_EFFECT_FILES.size();
3044                             SOUND_EFFECT_FILES.add(file);
3045                         }
3046                         SOUND_EFFECT_FILES_MAP[fx][0] = i;
3047                     } else {
3048                         break;
3049                     }
3050                 }
3051             }
3052         } catch (Resources.NotFoundException e) {
3053             Log.w(TAG, "audio assets file not found", e);
3054         } catch (XmlPullParserException e) {
3055             Log.w(TAG, "XML parser exception reading touch sound assets", e);
3056         } catch (IOException e) {
3057             Log.w(TAG, "I/O exception reading touch sound assets", e);
3058         } finally {
3059             if (parser != null) {
3060                 parser.close();
3061             }
3062         }
3063     }
3064 
3065     /** @see AudioManager#playSoundEffect(int) */
playSoundEffect(int effectType)3066     public void playSoundEffect(int effectType) {
3067         playSoundEffectVolume(effectType, -1.0f);
3068     }
3069 
3070     /** @see AudioManager#playSoundEffect(int, float) */
playSoundEffectVolume(int effectType, float volume)3071     public void playSoundEffectVolume(int effectType, float volume) {
3072         // do not try to play the sound effect if the system stream is muted
3073         if (isStreamMutedByRingerOrZenMode(STREAM_SYSTEM)) {
3074             return;
3075         }
3076 
3077         if (effectType >= AudioManager.NUM_SOUND_EFFECTS || effectType < 0) {
3078             Log.w(TAG, "AudioService effectType value " + effectType + " out of range");
3079             return;
3080         }
3081 
3082         sendMsg(mAudioHandler, MSG_PLAY_SOUND_EFFECT, SENDMSG_QUEUE,
3083                 effectType, (int) (volume * 1000), null, 0);
3084     }
3085 
3086     /**
3087      * Loads samples into the soundpool.
3088      * This method must be called at first when sound effects are enabled
3089      */
loadSoundEffects()3090     public boolean loadSoundEffects() {
3091         int attempts = 3;
3092         LoadSoundEffectReply reply = new LoadSoundEffectReply();
3093 
3094         synchronized (reply) {
3095             sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, reply, 0);
3096             while ((reply.mStatus == 1) && (attempts-- > 0)) {
3097                 try {
3098                     reply.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
3099                 } catch (InterruptedException e) {
3100                     Log.w(TAG, "loadSoundEffects Interrupted while waiting sound pool loaded.");
3101                 }
3102             }
3103         }
3104         return (reply.mStatus == 0);
3105     }
3106 
3107     /**
3108      *  Unloads samples from the sound pool.
3109      *  This method can be called to free some memory when
3110      *  sound effects are disabled.
3111      */
unloadSoundEffects()3112     public void unloadSoundEffects() {
3113         sendMsg(mAudioHandler, MSG_UNLOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, null, 0);
3114     }
3115 
3116     class SoundPoolListenerThread extends Thread {
SoundPoolListenerThread()3117         public SoundPoolListenerThread() {
3118             super("SoundPoolListenerThread");
3119         }
3120 
3121         @Override
run()3122         public void run() {
3123 
3124             Looper.prepare();
3125             mSoundPoolLooper = Looper.myLooper();
3126 
3127             synchronized (mSoundEffectsLock) {
3128                 if (mSoundPool != null) {
3129                     mSoundPoolCallBack = new SoundPoolCallback();
3130                     mSoundPool.setOnLoadCompleteListener(mSoundPoolCallBack);
3131                 }
3132                 mSoundEffectsLock.notify();
3133             }
3134             Looper.loop();
3135         }
3136     }
3137 
3138     private final class SoundPoolCallback implements
3139             android.media.SoundPool.OnLoadCompleteListener {
3140 
3141         int mStatus = 1; // 1 means neither error nor last sample loaded yet
3142         List<Integer> mSamples = new ArrayList<Integer>();
3143 
status()3144         public int status() {
3145             return mStatus;
3146         }
3147 
setSamples(int[] samples)3148         public void setSamples(int[] samples) {
3149             for (int i = 0; i < samples.length; i++) {
3150                 // do not wait ack for samples rejected upfront by SoundPool
3151                 if (samples[i] > 0) {
3152                     mSamples.add(samples[i]);
3153                 }
3154             }
3155         }
3156 
onLoadComplete(SoundPool soundPool, int sampleId, int status)3157         public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
3158             synchronized (mSoundEffectsLock) {
3159                 int i = mSamples.indexOf(sampleId);
3160                 if (i >= 0) {
3161                     mSamples.remove(i);
3162                 }
3163                 if ((status != 0) || mSamples. isEmpty()) {
3164                     mStatus = status;
3165                     mSoundEffectsLock.notify();
3166                 }
3167             }
3168         }
3169     }
3170 
3171     /** @see AudioManager#reloadAudioSettings() */
reloadAudioSettings()3172     public void reloadAudioSettings() {
3173         readAudioSettings(false /*userSwitch*/);
3174     }
3175 
readAudioSettings(boolean userSwitch)3176     private void readAudioSettings(boolean userSwitch) {
3177         // restore ringer mode, ringer mode affected streams, mute affected streams and vibrate settings
3178         readPersistedSettings();
3179         readUserRestrictions();
3180 
3181         // restore volume settings
3182         int numStreamTypes = AudioSystem.getNumStreamTypes();
3183         for (int streamType = 0; streamType < numStreamTypes; streamType++) {
3184             VolumeStreamState streamState = mStreamStates[streamType];
3185 
3186             if (userSwitch && mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) {
3187                 continue;
3188             }
3189 
3190             streamState.readSettings();
3191             synchronized (VolumeStreamState.class) {
3192                 // unmute stream that was muted but is not affect by mute anymore
3193                 if (streamState.mIsMuted && ((!isStreamAffectedByMute(streamType) &&
3194                         !isStreamMutedByRingerOrZenMode(streamType)) || mUseFixedVolume)) {
3195                     streamState.mIsMuted = false;
3196                 }
3197             }
3198         }
3199 
3200         // apply new ringer mode before checking volume for alias streams so that streams
3201         // muted by ringer mode have the correct volume
3202         setRingerModeInt(getRingerModeInternal(), false);
3203 
3204         checkAllFixedVolumeDevices();
3205         checkAllAliasStreamVolumes();
3206         checkMuteAffectedStreams();
3207 
3208         synchronized (mSafeMediaVolumeState) {
3209             mMusicActiveMs = MathUtils.constrain(Settings.Secure.getIntForUser(mContentResolver,
3210                     Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS, 0, UserHandle.USER_CURRENT),
3211                     0, UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX);
3212             if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) {
3213                 enforceSafeMediaVolume(TAG);
3214             }
3215         }
3216     }
3217 
3218     /** @see AudioManager#setSpeakerphoneOn(boolean) */
setSpeakerphoneOn(boolean on)3219     public void setSpeakerphoneOn(boolean on){
3220         if (!checkAudioSettingsPermission("setSpeakerphoneOn()")) {
3221             return;
3222         }
3223         // for logging only
3224         final String eventSource = new StringBuilder("setSpeakerphoneOn(").append(on)
3225                 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3226                 .append(Binder.getCallingPid()).toString();
3227 
3228         if (on) {
3229             if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
3230                     sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
3231                             AudioSystem.FOR_RECORD, AudioSystem.FORCE_NONE,
3232                             eventSource, 0);
3233             }
3234             mForcedUseForComm = AudioSystem.FORCE_SPEAKER;
3235         } else if (mForcedUseForComm == AudioSystem.FORCE_SPEAKER){
3236             mForcedUseForComm = AudioSystem.FORCE_NONE;
3237         }
3238 
3239         mForcedUseForCommExt = mForcedUseForComm;
3240         sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
3241                 AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, eventSource, 0);
3242     }
3243 
3244     /** @see AudioManager#isSpeakerphoneOn() */
isSpeakerphoneOn()3245     public boolean isSpeakerphoneOn() {
3246         return (mForcedUseForCommExt == AudioSystem.FORCE_SPEAKER);
3247     }
3248 
3249     /** @see AudioManager#setBluetoothScoOn(boolean) */
setBluetoothScoOn(boolean on)3250     public void setBluetoothScoOn(boolean on) {
3251         if (!checkAudioSettingsPermission("setBluetoothScoOn()")) {
3252             return;
3253         }
3254 
3255         // Only enable calls from system components
3256         if (Binder.getCallingUid() >= FIRST_APPLICATION_UID) {
3257             mForcedUseForCommExt = on ? AudioSystem.FORCE_BT_SCO : AudioSystem.FORCE_NONE;
3258             return;
3259         }
3260 
3261         // for logging only
3262         final String eventSource = new StringBuilder("setBluetoothScoOn(").append(on)
3263                 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3264                 .append(Binder.getCallingPid()).toString();
3265         setBluetoothScoOnInt(on, eventSource);
3266     }
3267 
setBluetoothScoOnInt(boolean on, String eventSource)3268     public void setBluetoothScoOnInt(boolean on, String eventSource) {
3269         Log.i(TAG, "setBluetoothScoOnInt: " + on + " " + eventSource);
3270         if (on) {
3271             // do not accept SCO ON if SCO audio is not connected
3272             synchronized (mScoClients) {
3273                 if ((mBluetoothHeadset != null)
3274                         && (mBluetoothHeadset.getAudioState(mBluetoothHeadsetDevice)
3275                             != BluetoothHeadset.STATE_AUDIO_CONNECTED)) {
3276                     mForcedUseForCommExt = AudioSystem.FORCE_BT_SCO;
3277                     Log.w(TAG, "setBluetoothScoOnInt(true) failed because "
3278                             + mBluetoothHeadsetDevice + " is not in audio connected mode");
3279                     return;
3280                 }
3281             }
3282             mForcedUseForComm = AudioSystem.FORCE_BT_SCO;
3283         } else if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
3284             mForcedUseForComm = AudioSystem.FORCE_NONE;
3285         }
3286         mForcedUseForCommExt = mForcedUseForComm;
3287         AudioSystem.setParameters("BT_SCO="+ (on ? "on" : "off"));
3288         sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
3289                 AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, eventSource, 0);
3290         sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
3291                 AudioSystem.FOR_RECORD, mForcedUseForComm, eventSource, 0);
3292         // Un-mute ringtone stream volume
3293         setRingerModeInt(getRingerModeInternal(), false);
3294     }
3295 
3296     /** @see AudioManager#isBluetoothScoOn() */
isBluetoothScoOn()3297     public boolean isBluetoothScoOn() {
3298         return (mForcedUseForCommExt == AudioSystem.FORCE_BT_SCO);
3299     }
3300 
3301     /** @see AudioManager#setBluetoothA2dpOn(boolean) */
setBluetoothA2dpOn(boolean on)3302     public void setBluetoothA2dpOn(boolean on) {
3303         // for logging only
3304         final String eventSource = new StringBuilder("setBluetoothA2dpOn(").append(on)
3305                 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3306                 .append(Binder.getCallingPid()).toString();
3307 
3308         synchronized (mBluetoothA2dpEnabledLock) {
3309             if (mBluetoothA2dpEnabled == on) {
3310                 return;
3311             }
3312             mBluetoothA2dpEnabled = on;
3313             sendMsg(mAudioHandler, MSG_SET_FORCE_BT_A2DP_USE, SENDMSG_QUEUE,
3314                     AudioSystem.FOR_MEDIA,
3315                     mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP,
3316                     eventSource, 0);
3317         }
3318     }
3319 
3320     /** @see AudioManager#isBluetoothA2dpOn() */
isBluetoothA2dpOn()3321     public boolean isBluetoothA2dpOn() {
3322         synchronized (mBluetoothA2dpEnabledLock) {
3323             return mBluetoothA2dpEnabled;
3324         }
3325     }
3326 
3327     /** @see AudioManager#startBluetoothSco() */
startBluetoothSco(IBinder cb, int targetSdkVersion)3328     public void startBluetoothSco(IBinder cb, int targetSdkVersion) {
3329         int scoAudioMode =
3330                 (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR2) ?
3331                         SCO_MODE_VIRTUAL_CALL : SCO_MODE_UNDEFINED;
3332         startBluetoothScoInt(cb, scoAudioMode);
3333     }
3334 
3335     /** @see AudioManager#startBluetoothScoVirtualCall() */
startBluetoothScoVirtualCall(IBinder cb)3336     public void startBluetoothScoVirtualCall(IBinder cb) {
3337         startBluetoothScoInt(cb, SCO_MODE_VIRTUAL_CALL);
3338     }
3339 
startBluetoothScoInt(IBinder cb, int scoAudioMode)3340     void startBluetoothScoInt(IBinder cb, int scoAudioMode){
3341         if (!checkAudioSettingsPermission("startBluetoothSco()") ||
3342                 !mSystemReady) {
3343             return;
3344         }
3345         ScoClient client = getScoClient(cb, true);
3346         // The calling identity must be cleared before calling ScoClient.incCount().
3347         // inCount() calls requestScoState() which in turn can call BluetoothHeadset APIs
3348         // and this must be done on behalf of system server to make sure permissions are granted.
3349         // The caller identity must be cleared after getScoClient() because it is needed if a new
3350         // client is created.
3351         final long ident = Binder.clearCallingIdentity();
3352         client.incCount(scoAudioMode);
3353         Binder.restoreCallingIdentity(ident);
3354     }
3355 
3356     /** @see AudioManager#stopBluetoothSco() */
stopBluetoothSco(IBinder cb)3357     public void stopBluetoothSco(IBinder cb){
3358         if (!checkAudioSettingsPermission("stopBluetoothSco()") ||
3359                 !mSystemReady) {
3360             return;
3361         }
3362         ScoClient client = getScoClient(cb, false);
3363         // The calling identity must be cleared before calling ScoClient.decCount().
3364         // decCount() calls requestScoState() which in turn can call BluetoothHeadset APIs
3365         // and this must be done on behalf of system server to make sure permissions are granted.
3366         final long ident = Binder.clearCallingIdentity();
3367         if (client != null) {
3368             client.decCount();
3369         }
3370         Binder.restoreCallingIdentity(ident);
3371     }
3372 
3373 
3374     private class ScoClient implements IBinder.DeathRecipient {
3375         private IBinder mCb; // To be notified of client's death
3376         private int mCreatorPid;
3377         private int mStartcount; // number of SCO connections started by this client
3378 
ScoClient(IBinder cb)3379         ScoClient(IBinder cb) {
3380             mCb = cb;
3381             mCreatorPid = Binder.getCallingPid();
3382             mStartcount = 0;
3383         }
3384 
binderDied()3385         public void binderDied() {
3386             synchronized(mScoClients) {
3387                 Log.w(TAG, "SCO client died");
3388                 int index = mScoClients.indexOf(this);
3389                 if (index < 0) {
3390                     Log.w(TAG, "unregistered SCO client died");
3391                 } else {
3392                     clearCount(true);
3393                     mScoClients.remove(this);
3394                 }
3395             }
3396         }
3397 
incCount(int scoAudioMode)3398         public void incCount(int scoAudioMode) {
3399             synchronized(mScoClients) {
3400                 requestScoState(BluetoothHeadset.STATE_AUDIO_CONNECTED, scoAudioMode);
3401                 if (mStartcount == 0) {
3402                     try {
3403                         mCb.linkToDeath(this, 0);
3404                     } catch (RemoteException e) {
3405                         // client has already died!
3406                         Log.w(TAG, "ScoClient  incCount() could not link to "+mCb+" binder death");
3407                     }
3408                 }
3409                 mStartcount++;
3410             }
3411         }
3412 
decCount()3413         public void decCount() {
3414             synchronized(mScoClients) {
3415                 if (mStartcount == 0) {
3416                     Log.w(TAG, "ScoClient.decCount() already 0");
3417                 } else {
3418                     mStartcount--;
3419                     if (mStartcount == 0) {
3420                         try {
3421                             mCb.unlinkToDeath(this, 0);
3422                         } catch (NoSuchElementException e) {
3423                             Log.w(TAG, "decCount() going to 0 but not registered to binder");
3424                         }
3425                     }
3426                     requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, 0);
3427                 }
3428             }
3429         }
3430 
clearCount(boolean stopSco)3431         public void clearCount(boolean stopSco) {
3432             synchronized(mScoClients) {
3433                 if (mStartcount != 0) {
3434                     try {
3435                         mCb.unlinkToDeath(this, 0);
3436                     } catch (NoSuchElementException e) {
3437                         Log.w(TAG, "clearCount() mStartcount: "+mStartcount+" != 0 but not registered to binder");
3438                     }
3439                 }
3440                 mStartcount = 0;
3441                 if (stopSco) {
3442                     requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, 0);
3443                 }
3444             }
3445         }
3446 
getCount()3447         public int getCount() {
3448             return mStartcount;
3449         }
3450 
getBinder()3451         public IBinder getBinder() {
3452             return mCb;
3453         }
3454 
getPid()3455         public int getPid() {
3456             return mCreatorPid;
3457         }
3458 
totalCount()3459         public int totalCount() {
3460             synchronized(mScoClients) {
3461                 int count = 0;
3462                 for (ScoClient mScoClient : mScoClients) {
3463                     count += mScoClient.getCount();
3464                 }
3465                 return count;
3466             }
3467         }
3468 
requestScoState(int state, int scoAudioMode)3469         private void requestScoState(int state, int scoAudioMode) {
3470             checkScoAudioState();
3471             int clientCount = totalCount();
3472             if (clientCount != 0) {
3473                 Log.i(TAG, "requestScoState: state=" + state + ", scoAudioMode=" + scoAudioMode
3474                         + ", clientCount=" + clientCount);
3475                 return;
3476             }
3477             if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) {
3478                 // Make sure that the state transitions to CONNECTING even if we cannot initiate
3479                 // the connection.
3480                 broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTING);
3481                 // Accept SCO audio activation only in NORMAL audio mode or if the mode is
3482                 // currently controlled by the same client process.
3483                 synchronized(mSetModeDeathHandlers) {
3484                     int modeOwnerPid =  mSetModeDeathHandlers.isEmpty()
3485                             ? 0 : mSetModeDeathHandlers.get(0).getPid();
3486                     if (modeOwnerPid != 0 && (modeOwnerPid != mCreatorPid)) {
3487                         Log.w(TAG, "requestScoState: audio mode is not NORMAL and modeOwnerPid "
3488                                 + modeOwnerPid + " != creatorPid " + mCreatorPid);
3489                         broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
3490                         return;
3491                     }
3492                     switch (mScoAudioState) {
3493                         case SCO_STATE_INACTIVE:
3494                             mScoAudioMode = scoAudioMode;
3495                             if (scoAudioMode == SCO_MODE_UNDEFINED) {
3496                                 mScoAudioMode = SCO_MODE_VIRTUAL_CALL;
3497                                 if (mBluetoothHeadsetDevice != null) {
3498                                     mScoAudioMode = Settings.Global.getInt(mContentResolver,
3499                                             "bluetooth_sco_channel_"
3500                                                     + mBluetoothHeadsetDevice.getAddress(),
3501                                             SCO_MODE_VIRTUAL_CALL);
3502                                     if (mScoAudioMode > SCO_MODE_MAX || mScoAudioMode < 0) {
3503                                         mScoAudioMode = SCO_MODE_VIRTUAL_CALL;
3504                                     }
3505                                 }
3506                             }
3507                             if (mBluetoothHeadset == null) {
3508                                 if (getBluetoothHeadset()) {
3509                                     mScoAudioState = SCO_STATE_ACTIVATE_REQ;
3510                                 } else {
3511                                     Log.w(TAG, "requestScoState: getBluetoothHeadset failed during"
3512                                             + " connection, mScoAudioMode=" + mScoAudioMode);
3513                                     broadcastScoConnectionState(
3514                                             AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
3515                                 }
3516                                 break;
3517                             }
3518                             if (mBluetoothHeadsetDevice == null) {
3519                                 Log.w(TAG, "requestScoState: no active device while connecting,"
3520                                         + " mScoAudioMode=" + mScoAudioMode);
3521                                 broadcastScoConnectionState(
3522                                         AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
3523                                 break;
3524                             }
3525                             if (connectBluetoothScoAudioHelper(mBluetoothHeadset,
3526                                     mBluetoothHeadsetDevice, mScoAudioMode)) {
3527                                 mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
3528                             } else {
3529                                 Log.w(TAG, "requestScoState: connect to " + mBluetoothHeadsetDevice
3530                                         + " failed, mScoAudioMode=" + mScoAudioMode);
3531                                 broadcastScoConnectionState(
3532                                         AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
3533                             }
3534                             break;
3535                         case SCO_STATE_DEACTIVATING:
3536                             mScoAudioState = SCO_STATE_ACTIVATE_REQ;
3537                             break;
3538                         case SCO_STATE_DEACTIVATE_REQ:
3539                             mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
3540                             broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTED);
3541                             break;
3542                         default:
3543                             Log.w(TAG, "requestScoState: failed to connect in state "
3544                                     + mScoAudioState + ", scoAudioMode=" + scoAudioMode);
3545                             broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
3546                             break;
3547 
3548                     }
3549                 }
3550             } else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED) {
3551                 switch (mScoAudioState) {
3552                     case SCO_STATE_ACTIVE_INTERNAL:
3553                         if (mBluetoothHeadset == null) {
3554                             if (getBluetoothHeadset()) {
3555                                 mScoAudioState = SCO_STATE_DEACTIVATE_REQ;
3556                             } else {
3557                                 Log.w(TAG, "requestScoState: getBluetoothHeadset failed during"
3558                                         + " disconnection, mScoAudioMode=" + mScoAudioMode);
3559                                 mScoAudioState = SCO_STATE_INACTIVE;
3560                                 broadcastScoConnectionState(
3561                                         AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
3562                             }
3563                             break;
3564                         }
3565                         if (mBluetoothHeadsetDevice == null) {
3566                             mScoAudioState = SCO_STATE_INACTIVE;
3567                             broadcastScoConnectionState(
3568                                     AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
3569                             break;
3570                         }
3571                         if (disconnectBluetoothScoAudioHelper(mBluetoothHeadset,
3572                                 mBluetoothHeadsetDevice, mScoAudioMode)) {
3573                             mScoAudioState = SCO_STATE_DEACTIVATING;
3574                         } else {
3575                             mScoAudioState = SCO_STATE_INACTIVE;
3576                             broadcastScoConnectionState(
3577                                     AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
3578                         }
3579                         break;
3580                     case SCO_STATE_ACTIVATE_REQ:
3581                         mScoAudioState = SCO_STATE_INACTIVE;
3582                         broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
3583                         break;
3584                     default:
3585                         Log.w(TAG, "requestScoState: failed to disconnect in state "
3586                                 + mScoAudioState + ", scoAudioMode=" + scoAudioMode);
3587                         broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
3588                         break;
3589                 }
3590             }
3591         }
3592     }
3593 
checkScoAudioState()3594     private void checkScoAudioState() {
3595         synchronized (mScoClients) {
3596             if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null &&
3597                     mScoAudioState == SCO_STATE_INACTIVE &&
3598                     mBluetoothHeadset.getAudioState(mBluetoothHeadsetDevice)
3599                             != BluetoothHeadset.STATE_AUDIO_DISCONNECTED) {
3600                 mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL;
3601             }
3602         }
3603     }
3604 
3605 
getScoClient(IBinder cb, boolean create)3606     private ScoClient getScoClient(IBinder cb, boolean create) {
3607         synchronized(mScoClients) {
3608             for (ScoClient existingClient : mScoClients) {
3609                 if (existingClient.getBinder() == cb) {
3610                     return existingClient;
3611                 }
3612             }
3613             if (create) {
3614                 ScoClient newClient = new ScoClient(cb);
3615                 mScoClients.add(newClient);
3616                 return newClient;
3617             }
3618             return null;
3619         }
3620     }
3621 
clearAllScoClients(int exceptPid, boolean stopSco)3622     public void clearAllScoClients(int exceptPid, boolean stopSco) {
3623         synchronized(mScoClients) {
3624             ScoClient savedClient = null;
3625             for (ScoClient cl : mScoClients) {
3626                 if (cl.getPid() != exceptPid) {
3627                     cl.clearCount(stopSco);
3628                 } else {
3629                     savedClient = cl;
3630                 }
3631             }
3632             mScoClients.clear();
3633             if (savedClient != null) {
3634                 mScoClients.add(savedClient);
3635             }
3636         }
3637     }
3638 
getBluetoothHeadset()3639     private boolean getBluetoothHeadset() {
3640         boolean result = false;
3641         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
3642         if (adapter != null) {
3643             result = adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
3644                                     BluetoothProfile.HEADSET);
3645         }
3646         // If we could not get a bluetooth headset proxy, send a failure message
3647         // without delay to reset the SCO audio state and clear SCO clients.
3648         // If we could get a proxy, send a delayed failure message that will reset our state
3649         // in case we don't receive onServiceConnected().
3650         sendMsg(mAudioHandler, MSG_BT_HEADSET_CNCT_FAILED,
3651                 SENDMSG_REPLACE, 0, 0, null, result ? BT_HEADSET_CNCT_TIMEOUT_MS : 0);
3652         return result;
3653     }
3654 
3655     /**
3656      * Disconnect all SCO connections started by {@link AudioManager} except those started by
3657      * {@param exceptPid}
3658      *
3659      * @param exceptPid pid whose SCO connections through {@link AudioManager} should be kept
3660      */
disconnectBluetoothSco(int exceptPid)3661     private void disconnectBluetoothSco(int exceptPid) {
3662         synchronized(mScoClients) {
3663             checkScoAudioState();
3664             if (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL) {
3665                 return;
3666             }
3667             clearAllScoClients(exceptPid, true);
3668         }
3669     }
3670 
disconnectBluetoothScoAudioHelper(BluetoothHeadset bluetoothHeadset, BluetoothDevice device, int scoAudioMode)3671     private static boolean disconnectBluetoothScoAudioHelper(BluetoothHeadset bluetoothHeadset,
3672             BluetoothDevice device, int scoAudioMode) {
3673         switch (scoAudioMode) {
3674             case SCO_MODE_RAW:
3675                 return bluetoothHeadset.disconnectAudio();
3676             case SCO_MODE_VIRTUAL_CALL:
3677                 return bluetoothHeadset.stopScoUsingVirtualVoiceCall();
3678             case SCO_MODE_VR:
3679                 return bluetoothHeadset.stopVoiceRecognition(device);
3680             default:
3681                 return false;
3682         }
3683     }
3684 
connectBluetoothScoAudioHelper(BluetoothHeadset bluetoothHeadset, BluetoothDevice device, int scoAudioMode)3685     private static boolean connectBluetoothScoAudioHelper(BluetoothHeadset bluetoothHeadset,
3686             BluetoothDevice device, int scoAudioMode) {
3687         switch (scoAudioMode) {
3688             case SCO_MODE_RAW:
3689                 return bluetoothHeadset.connectAudio();
3690             case SCO_MODE_VIRTUAL_CALL:
3691                 return bluetoothHeadset.startScoUsingVirtualVoiceCall();
3692             case SCO_MODE_VR:
3693                 return bluetoothHeadset.startVoiceRecognition(device);
3694             default:
3695                 return false;
3696         }
3697     }
3698 
resetBluetoothSco()3699     private void resetBluetoothSco() {
3700         synchronized(mScoClients) {
3701             clearAllScoClients(0, false);
3702             mScoAudioState = SCO_STATE_INACTIVE;
3703             broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
3704         }
3705         AudioSystem.setParameters("A2dpSuspended=false");
3706         setBluetoothScoOnInt(false, "resetBluetoothSco");
3707     }
3708 
broadcastScoConnectionState(int state)3709     private void broadcastScoConnectionState(int state) {
3710         sendMsg(mAudioHandler, MSG_BROADCAST_BT_CONNECTION_STATE,
3711                 SENDMSG_QUEUE, state, 0, null, 0);
3712     }
3713 
onBroadcastScoConnectionState(int state)3714     private void onBroadcastScoConnectionState(int state) {
3715         if (state != mScoConnectionState) {
3716             Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
3717             newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, state);
3718             newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_PREVIOUS_STATE,
3719                     mScoConnectionState);
3720             sendStickyBroadcastToAll(newIntent);
3721             mScoConnectionState = state;
3722         }
3723     }
3724 
handleBtScoActiveDeviceChange(BluetoothDevice btDevice, boolean isActive)3725     private boolean handleBtScoActiveDeviceChange(BluetoothDevice btDevice, boolean isActive) {
3726         if (btDevice == null) {
3727             return true;
3728         }
3729         String address = btDevice.getAddress();
3730         BluetoothClass btClass = btDevice.getBluetoothClass();
3731         int inDevice = AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET;
3732         int[] outDeviceTypes = {
3733             AudioSystem.DEVICE_OUT_BLUETOOTH_SCO,
3734             AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET,
3735             AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT
3736         };
3737         if (btClass != null) {
3738             switch (btClass.getDeviceClass()) {
3739                 case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET:
3740                 case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE:
3741                     outDeviceTypes = new int[] { AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET };
3742                     break;
3743                 case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO:
3744                     outDeviceTypes = new int[] { AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT };
3745                     break;
3746             }
3747         }
3748         if (!BluetoothAdapter.checkBluetoothAddress(address)) {
3749             address = "";
3750         }
3751         String btDeviceName =  btDevice.getName();
3752         boolean result = false;
3753         if (isActive) {
3754             result |= handleDeviceConnection(isActive, outDeviceTypes[0], address, btDeviceName);
3755         } else {
3756             for (int outDeviceType : outDeviceTypes) {
3757                 result |= handleDeviceConnection(isActive, outDeviceType, address, btDeviceName);
3758             }
3759         }
3760         // handleDeviceConnection() && result to make sure the method get executed
3761         result = handleDeviceConnection(isActive, inDevice, address, btDeviceName) && result;
3762         return result;
3763     }
3764 
setBtScoActiveDevice(BluetoothDevice btDevice)3765     private void setBtScoActiveDevice(BluetoothDevice btDevice) {
3766         synchronized (mScoClients) {
3767             Log.i(TAG, "setBtScoActiveDevice: " + mBluetoothHeadsetDevice + " -> " + btDevice);
3768             final BluetoothDevice previousActiveDevice = mBluetoothHeadsetDevice;
3769             if (!Objects.equals(btDevice, previousActiveDevice)) {
3770                 if (!handleBtScoActiveDeviceChange(previousActiveDevice, false)) {
3771                     Log.w(TAG, "setBtScoActiveDevice() failed to remove previous device "
3772                             + previousActiveDevice);
3773                 }
3774                 if (!handleBtScoActiveDeviceChange(btDevice, true)) {
3775                     Log.e(TAG, "setBtScoActiveDevice() failed to add new device " + btDevice);
3776                     // set mBluetoothHeadsetDevice to null when failing to add new device
3777                     btDevice = null;
3778                 }
3779                 mBluetoothHeadsetDevice = btDevice;
3780                 if (mBluetoothHeadsetDevice == null) {
3781                     resetBluetoothSco();
3782                 }
3783             }
3784         }
3785     }
3786 
3787     private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
3788         new BluetoothProfile.ServiceListener() {
3789         public void onServiceConnected(int profile, BluetoothProfile proxy) {
3790             BluetoothDevice btDevice;
3791             List<BluetoothDevice> deviceList;
3792             switch(profile) {
3793             case BluetoothProfile.A2DP:
3794                 synchronized (mConnectedDevices) {
3795                     synchronized (mA2dpAvrcpLock) {
3796                         mA2dp = (BluetoothA2dp) proxy;
3797                         deviceList = mA2dp.getConnectedDevices();
3798                         if (deviceList.size() > 0) {
3799                             btDevice = deviceList.get(0);
3800                             int state = mA2dp.getConnectionState(btDevice);
3801                             int intState = (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0;
3802                             int delay = checkSendBecomingNoisyIntent(
3803                                     AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, intState,
3804                                     AudioSystem.DEVICE_NONE);
3805                             queueMsgUnderWakeLock(mAudioHandler,
3806                                     MSG_SET_A2DP_SINK_CONNECTION_STATE,
3807                                     state,
3808                                     -1,
3809                                     btDevice,
3810                                     delay);
3811                         }
3812                     }
3813                 }
3814                 break;
3815 
3816             case BluetoothProfile.A2DP_SINK:
3817                 deviceList = proxy.getConnectedDevices();
3818                 if (deviceList.size() > 0) {
3819                     btDevice = deviceList.get(0);
3820                     synchronized (mConnectedDevices) {
3821                         int state = proxy.getConnectionState(btDevice);
3822                         queueMsgUnderWakeLock(mAudioHandler,
3823                                 MSG_SET_A2DP_SRC_CONNECTION_STATE,
3824                                 state,
3825                                 0 /* arg2 unused */,
3826                                 btDevice,
3827                                 0 /* delay */);
3828                     }
3829                 }
3830                 break;
3831 
3832             case BluetoothProfile.HEADSET:
3833                 synchronized (mScoClients) {
3834                     // Discard timeout message
3835                     mAudioHandler.removeMessages(MSG_BT_HEADSET_CNCT_FAILED);
3836                     mBluetoothHeadset = (BluetoothHeadset) proxy;
3837                     setBtScoActiveDevice(mBluetoothHeadset.getActiveDevice());
3838                     // Refresh SCO audio state
3839                     checkScoAudioState();
3840                     // Continue pending action if any
3841                     if (mScoAudioState == SCO_STATE_ACTIVATE_REQ ||
3842                             mScoAudioState == SCO_STATE_DEACTIVATE_REQ) {
3843                         boolean status = false;
3844                         if (mBluetoothHeadsetDevice != null) {
3845                             switch (mScoAudioState) {
3846                                 case SCO_STATE_ACTIVATE_REQ:
3847                                     status = connectBluetoothScoAudioHelper(mBluetoothHeadset,
3848                                             mBluetoothHeadsetDevice, mScoAudioMode);
3849                                     if (status) {
3850                                         mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
3851                                     }
3852                                     break;
3853                                 case SCO_STATE_DEACTIVATE_REQ:
3854                                     status = disconnectBluetoothScoAudioHelper(mBluetoothHeadset,
3855                                             mBluetoothHeadsetDevice, mScoAudioMode);
3856                                     if (status) {
3857                                         mScoAudioState = SCO_STATE_DEACTIVATING;
3858                                     }
3859                                     break;
3860                             }
3861                         }
3862                         if (!status) {
3863                             mScoAudioState = SCO_STATE_INACTIVE;
3864                             broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
3865                         }
3866                     }
3867                 }
3868                 break;
3869 
3870             case BluetoothProfile.HEARING_AID:
3871                 synchronized (mConnectedDevices) {
3872                     synchronized (mHearingAidLock) {
3873                         mHearingAid = (BluetoothHearingAid) proxy;
3874                         deviceList = mHearingAid.getConnectedDevices();
3875                         if (deviceList.size() > 0) {
3876                             btDevice = deviceList.get(0);
3877                             int state = mHearingAid.getConnectionState(btDevice);
3878                             int intState = (state == BluetoothHearingAid.STATE_CONNECTED) ? 1 : 0;
3879                             int delay = checkSendBecomingNoisyIntent(
3880                                     AudioSystem.DEVICE_OUT_HEARING_AID, intState,
3881                                     AudioSystem.DEVICE_NONE);
3882                             queueMsgUnderWakeLock(mAudioHandler,
3883                                     MSG_SET_HEARING_AID_CONNECTION_STATE,
3884                                     state,
3885                                     0 /* arg2 unused */,
3886                                     btDevice,
3887                                     delay);
3888                         }
3889                     }
3890                 }
3891 
3892                 break;
3893 
3894             default:
3895                 break;
3896             }
3897         }
3898         public void onServiceDisconnected(int profile) {
3899 
3900             switch (profile) {
3901             case BluetoothProfile.A2DP:
3902                 disconnectA2dp();
3903                 break;
3904 
3905             case BluetoothProfile.A2DP_SINK:
3906                 disconnectA2dpSink();
3907                 break;
3908 
3909             case BluetoothProfile.HEADSET:
3910                 disconnectHeadset();
3911                 break;
3912 
3913             case BluetoothProfile.HEARING_AID:
3914                 disconnectHearingAid();
3915                 break;
3916 
3917             default:
3918                 break;
3919             }
3920         }
3921     };
3922 
disconnectAllBluetoothProfiles()3923     void disconnectAllBluetoothProfiles() {
3924         disconnectA2dp();
3925         disconnectA2dpSink();
3926         disconnectHeadset();
3927         disconnectHearingAid();
3928     }
3929 
disconnectA2dp()3930     void disconnectA2dp() {
3931         synchronized (mConnectedDevices) {
3932             synchronized (mA2dpAvrcpLock) {
3933                 ArraySet<String> toRemove = null;
3934                 // Disconnect ALL DEVICE_OUT_BLUETOOTH_A2DP devices
3935                 for (int i = 0; i < mConnectedDevices.size(); i++) {
3936                     DeviceListSpec deviceSpec = mConnectedDevices.valueAt(i);
3937                     if (deviceSpec.mDeviceType == AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) {
3938                         toRemove = toRemove != null ? toRemove : new ArraySet<String>();
3939                         toRemove.add(deviceSpec.mDeviceAddress);
3940                     }
3941                 }
3942                 if (toRemove != null) {
3943                     int delay = checkSendBecomingNoisyIntent(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
3944                             0, AudioSystem.DEVICE_NONE);
3945                     for (int i = 0; i < toRemove.size(); i++) {
3946                         makeA2dpDeviceUnavailableLater(toRemove.valueAt(i), delay);
3947                     }
3948                 }
3949             }
3950         }
3951     }
3952 
disconnectA2dpSink()3953     void disconnectA2dpSink() {
3954         synchronized (mConnectedDevices) {
3955             ArraySet<String> toRemove = null;
3956             // Disconnect ALL DEVICE_IN_BLUETOOTH_A2DP devices
3957             for(int i = 0; i < mConnectedDevices.size(); i++) {
3958                 DeviceListSpec deviceSpec = mConnectedDevices.valueAt(i);
3959                 if (deviceSpec.mDeviceType == AudioSystem.DEVICE_IN_BLUETOOTH_A2DP) {
3960                     toRemove = toRemove != null ? toRemove : new ArraySet<String>();
3961                     toRemove.add(deviceSpec.mDeviceAddress);
3962                 }
3963             }
3964             if (toRemove != null) {
3965                 for (int i = 0; i < toRemove.size(); i++) {
3966                     makeA2dpSrcUnavailable(toRemove.valueAt(i));
3967                 }
3968             }
3969         }
3970     }
3971 
disconnectHeadset()3972     void disconnectHeadset() {
3973         synchronized (mScoClients) {
3974             setBtScoActiveDevice(null);
3975             mBluetoothHeadset = null;
3976         }
3977     }
3978 
disconnectHearingAid()3979     void disconnectHearingAid() {
3980         synchronized (mConnectedDevices) {
3981             synchronized (mHearingAidLock) {
3982                 ArraySet<String> toRemove = null;
3983                 // Disconnect ALL DEVICE_OUT_HEARING_AID devices
3984                 for (int i = 0; i < mConnectedDevices.size(); i++) {
3985                     DeviceListSpec deviceSpec = mConnectedDevices.valueAt(i);
3986                     if (deviceSpec.mDeviceType == AudioSystem.DEVICE_OUT_HEARING_AID) {
3987                         toRemove = toRemove != null ? toRemove : new ArraySet<String>();
3988                         toRemove.add(deviceSpec.mDeviceAddress);
3989                     }
3990                 }
3991                 if (toRemove != null) {
3992                     int delay = checkSendBecomingNoisyIntent(AudioSystem.DEVICE_OUT_HEARING_AID,
3993                             0, AudioSystem.DEVICE_NONE);
3994                     for (int i = 0; i < toRemove.size(); i++) {
3995                         makeHearingAidDeviceUnavailable(toRemove.valueAt(i) /*, delay*/);
3996                     }
3997                 }
3998             }
3999         }
4000     }
4001 
onCheckMusicActive(String caller)4002     private void onCheckMusicActive(String caller) {
4003         synchronized (mSafeMediaVolumeState) {
4004             if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE) {
4005                 int device = getDeviceForStream(AudioSystem.STREAM_MUSIC);
4006 
4007                 if ((device & mSafeMediaVolumeDevices) != 0) {
4008                     sendMsg(mAudioHandler,
4009                             MSG_CHECK_MUSIC_ACTIVE,
4010                             SENDMSG_REPLACE,
4011                             0,
4012                             0,
4013                             caller,
4014                             MUSIC_ACTIVE_POLL_PERIOD_MS);
4015                     int index = mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(device);
4016                     if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0) &&
4017                             (index > safeMediaVolumeIndex(device))) {
4018                         // Approximate cumulative active music time
4019                         mMusicActiveMs += MUSIC_ACTIVE_POLL_PERIOD_MS;
4020                         if (mMusicActiveMs > UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX) {
4021                             setSafeMediaVolumeEnabled(true, caller);
4022                             mMusicActiveMs = 0;
4023                         }
4024                         saveMusicActiveMs();
4025                     }
4026                 }
4027             }
4028         }
4029     }
4030 
saveMusicActiveMs()4031     private void saveMusicActiveMs() {
4032         mAudioHandler.obtainMessage(MSG_PERSIST_MUSIC_ACTIVE_MS, mMusicActiveMs, 0).sendToTarget();
4033     }
4034 
getSafeUsbMediaVolumeIndex()4035     private int getSafeUsbMediaVolumeIndex()
4036     {
4037         // determine UI volume index corresponding to the wanted safe gain in dBFS
4038         int min = MIN_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
4039         int max = MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
4040 
4041         mSafeUsbMediaVolumeDbfs = mContext.getResources().getInteger(
4042                 com.android.internal.R.integer.config_safe_media_volume_usb_mB) / 100.0f;
4043 
4044         while (Math.abs(max-min) > 1) {
4045             int index = (max + min) / 2;
4046             float gainDB = AudioSystem.getStreamVolumeDB(
4047                     AudioSystem.STREAM_MUSIC, index, AudioSystem.DEVICE_OUT_USB_HEADSET);
4048             if (Float.isNaN(gainDB)) {
4049                 //keep last min in case of read error
4050                 break;
4051             } else if (gainDB == mSafeUsbMediaVolumeDbfs) {
4052                 min = index;
4053                 break;
4054             } else if (gainDB < mSafeUsbMediaVolumeDbfs) {
4055                 min = index;
4056             } else {
4057                 max = index;
4058             }
4059         }
4060         return min * 10;
4061     }
4062 
onConfigureSafeVolume(boolean force, String caller)4063     private void onConfigureSafeVolume(boolean force, String caller) {
4064         synchronized (mSafeMediaVolumeState) {
4065             int mcc = mContext.getResources().getConfiguration().mcc;
4066             if ((mMcc != mcc) || ((mMcc == 0) && force)) {
4067                 mSafeMediaVolumeIndex = mContext.getResources().getInteger(
4068                         com.android.internal.R.integer.config_safe_media_volume_index) * 10;
4069 
4070                 mSafeUsbMediaVolumeIndex = getSafeUsbMediaVolumeIndex();
4071 
4072                 boolean safeMediaVolumeEnabled =
4073                         SystemProperties.getBoolean("audio.safemedia.force", false)
4074                         || mContext.getResources().getBoolean(
4075                                 com.android.internal.R.bool.config_safe_media_volume_enabled);
4076 
4077                 boolean safeMediaVolumeBypass =
4078                         SystemProperties.getBoolean("audio.safemedia.bypass", false);
4079 
4080                 // The persisted state is either "disabled" or "active": this is the state applied
4081                 // next time we boot and cannot be "inactive"
4082                 int persistedState;
4083                 if (safeMediaVolumeEnabled && !safeMediaVolumeBypass) {
4084                     persistedState = SAFE_MEDIA_VOLUME_ACTIVE;
4085                     // The state can already be "inactive" here if the user has forced it before
4086                     // the 30 seconds timeout for forced configuration. In this case we don't reset
4087                     // it to "active".
4088                     if (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_INACTIVE) {
4089                         if (mMusicActiveMs == 0) {
4090                             mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE;
4091                             enforceSafeMediaVolume(caller);
4092                         } else {
4093                             // We have existing playback time recorded, already confirmed.
4094                             mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE;
4095                         }
4096                     }
4097                 } else {
4098                     persistedState = SAFE_MEDIA_VOLUME_DISABLED;
4099                     mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_DISABLED;
4100                 }
4101                 mMcc = mcc;
4102                 sendMsg(mAudioHandler,
4103                         MSG_PERSIST_SAFE_VOLUME_STATE,
4104                         SENDMSG_QUEUE,
4105                         persistedState,
4106                         0,
4107                         null,
4108                         0);
4109             }
4110         }
4111     }
4112 
4113     ///////////////////////////////////////////////////////////////////////////
4114     // Internal methods
4115     ///////////////////////////////////////////////////////////////////////////
4116 
4117     /**
4118      * Checks if the adjustment should change ringer mode instead of just
4119      * adjusting volume. If so, this will set the proper ringer mode and volume
4120      * indices on the stream states.
4121      */
checkForRingerModeChange(int oldIndex, int direction, int step, boolean isMuted, String caller, int flags)4122     private int checkForRingerModeChange(int oldIndex, int direction, int step, boolean isMuted,
4123             String caller, int flags) {
4124         int result = FLAG_ADJUST_VOLUME;
4125         if (isPlatformTelevision() || mIsSingleVolume) {
4126             return result;
4127         }
4128 
4129         int ringerMode = getRingerModeInternal();
4130 
4131         switch (ringerMode) {
4132         case RINGER_MODE_NORMAL:
4133             if (direction == AudioManager.ADJUST_LOWER) {
4134                 if (mHasVibrator) {
4135                     // "step" is the delta in internal index units corresponding to a
4136                     // change of 1 in UI index units.
4137                     // Because of rounding when rescaling from one stream index range to its alias
4138                     // index range, we cannot simply test oldIndex == step:
4139                     //   (step <= oldIndex < 2 * step) is equivalent to: (old UI index == 1)
4140                     if (step <= oldIndex && oldIndex < 2 * step) {
4141                         ringerMode = RINGER_MODE_VIBRATE;
4142                         mLoweredFromNormalToVibrateTime = SystemClock.uptimeMillis();
4143                     }
4144                 } else {
4145                     if (oldIndex == step && mVolumePolicy.volumeDownToEnterSilent) {
4146                         ringerMode = RINGER_MODE_SILENT;
4147                     }
4148                 }
4149             } else if (mIsSingleVolume && (direction == AudioManager.ADJUST_TOGGLE_MUTE
4150                     || direction == AudioManager.ADJUST_MUTE)) {
4151                 if (mHasVibrator) {
4152                     ringerMode = RINGER_MODE_VIBRATE;
4153                 } else {
4154                     ringerMode = RINGER_MODE_SILENT;
4155                 }
4156                 // Setting the ringer mode will toggle mute
4157                 result &= ~FLAG_ADJUST_VOLUME;
4158             }
4159             break;
4160         case RINGER_MODE_VIBRATE:
4161             if (!mHasVibrator) {
4162                 Log.e(TAG, "checkForRingerModeChange() current ringer mode is vibrate" +
4163                         "but no vibrator is present");
4164                 break;
4165             }
4166             if ((direction == AudioManager.ADJUST_LOWER)) {
4167                 // This is the case we were muted with the volume turned up
4168                 if (mIsSingleVolume && oldIndex >= 2 * step && isMuted) {
4169                     ringerMode = RINGER_MODE_NORMAL;
4170                 } else if (mPrevVolDirection != AudioManager.ADJUST_LOWER) {
4171                     if (mVolumePolicy.volumeDownToEnterSilent) {
4172                         final long diff = SystemClock.uptimeMillis()
4173                                 - mLoweredFromNormalToVibrateTime;
4174                         if (diff > mVolumePolicy.vibrateToSilentDebounce
4175                                 && mRingerModeDelegate.canVolumeDownEnterSilent()) {
4176                             ringerMode = RINGER_MODE_SILENT;
4177                         }
4178                     } else {
4179                         result |= AudioManager.FLAG_SHOW_VIBRATE_HINT;
4180                     }
4181                 }
4182             } else if (direction == AudioManager.ADJUST_RAISE
4183                     || direction == AudioManager.ADJUST_TOGGLE_MUTE
4184                     || direction == AudioManager.ADJUST_UNMUTE) {
4185                 ringerMode = RINGER_MODE_NORMAL;
4186             }
4187             result &= ~FLAG_ADJUST_VOLUME;
4188             break;
4189         case RINGER_MODE_SILENT:
4190             if (mIsSingleVolume && direction == AudioManager.ADJUST_LOWER && oldIndex >= 2 * step && isMuted) {
4191                 // This is the case we were muted with the volume turned up
4192                 ringerMode = RINGER_MODE_NORMAL;
4193             } else if (direction == AudioManager.ADJUST_RAISE
4194                     || direction == AudioManager.ADJUST_TOGGLE_MUTE
4195                     || direction == AudioManager.ADJUST_UNMUTE) {
4196                 if (!mVolumePolicy.volumeUpToExitSilent) {
4197                     result |= AudioManager.FLAG_SHOW_SILENT_HINT;
4198                 } else {
4199                   if (mHasVibrator && direction == AudioManager.ADJUST_RAISE) {
4200                       ringerMode = RINGER_MODE_VIBRATE;
4201                   } else {
4202                       // If we don't have a vibrator or they were toggling mute
4203                       // go straight back to normal.
4204                       ringerMode = RINGER_MODE_NORMAL;
4205                   }
4206                 }
4207             }
4208             result &= ~FLAG_ADJUST_VOLUME;
4209             break;
4210         default:
4211             Log.e(TAG, "checkForRingerModeChange() wrong ringer mode: "+ringerMode);
4212             break;
4213         }
4214 
4215         if (isAndroidNPlus(caller) && wouldToggleZenMode(ringerMode)
4216                 && !mNm.isNotificationPolicyAccessGrantedForPackage(caller)
4217                 && (flags & AudioManager.FLAG_FROM_KEY) == 0) {
4218             throw new SecurityException("Not allowed to change Do Not Disturb state");
4219         }
4220 
4221         setRingerMode(ringerMode, TAG + ".checkForRingerModeChange", false /*external*/);
4222 
4223         mPrevVolDirection = direction;
4224 
4225         return result;
4226     }
4227 
4228     @Override
isStreamAffectedByRingerMode(int streamType)4229     public boolean isStreamAffectedByRingerMode(int streamType) {
4230         return (mRingerModeAffectedStreams & (1 << streamType)) != 0;
4231     }
4232 
shouldZenMuteStream(int streamType)4233     private boolean shouldZenMuteStream(int streamType) {
4234         if (mNm.getZenMode() != Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
4235             return false;
4236         }
4237 
4238         NotificationManager.Policy zenPolicy = mNm.getNotificationPolicy();
4239         final boolean muteAlarms = (zenPolicy.priorityCategories
4240                 & NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS) == 0;
4241         final boolean muteMedia = (zenPolicy.priorityCategories
4242                 & NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA) == 0;
4243         final boolean muteSystem = (zenPolicy.priorityCategories
4244                 & NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM) == 0;
4245         final boolean muteNotificationAndRing = ZenModeConfig
4246                 .areAllPriorityOnlyNotificationZenSoundsMuted(mNm.getNotificationPolicy());
4247         return muteAlarms && isAlarm(streamType)
4248                 || muteMedia && isMedia(streamType)
4249                 || muteSystem && isSystem(streamType)
4250                 || muteNotificationAndRing && isNotificationOrRinger(streamType);
4251     }
4252 
isStreamMutedByRingerOrZenMode(int streamType)4253     private boolean isStreamMutedByRingerOrZenMode(int streamType) {
4254         return (mRingerAndZenModeMutedStreams & (1 << streamType)) != 0;
4255     }
4256 
4257     /**
4258      * DND total silence: media and alarms streams are tied to the muted ringer
4259      * {@link ZenModeHelper.RingerModeDelegate#getRingerModeAffectedStreams(int)}
4260      * DND alarms only: notification, ringer + system muted (by default tied to muted ringer mode)
4261      * DND priority only: alarms, media, system streams can be muted separate from ringer based on
4262      * zenPolicy (this method determines which streams)
4263      * @return true if changed, else false
4264      */
updateZenModeAffectedStreams()4265     private boolean updateZenModeAffectedStreams() {
4266         int zenModeAffectedStreams = 0;
4267         if (mSystemReady && mNm.getZenMode() == Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
4268             NotificationManager.Policy zenPolicy = mNm.getNotificationPolicy();
4269             if ((zenPolicy.priorityCategories
4270                     & NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS) == 0) {
4271                 zenModeAffectedStreams |= 1 << AudioManager.STREAM_ALARM;
4272             }
4273 
4274             if ((zenPolicy.priorityCategories
4275                     & NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA) == 0) {
4276                 zenModeAffectedStreams |= 1 << AudioManager.STREAM_MUSIC;
4277             }
4278 
4279             if ((zenPolicy.priorityCategories
4280                     & NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM) == 0) {
4281                 zenModeAffectedStreams |= 1 << AudioManager.STREAM_SYSTEM;
4282             }
4283         }
4284 
4285         if (mZenModeAffectedStreams != zenModeAffectedStreams) {
4286             mZenModeAffectedStreams = zenModeAffectedStreams;
4287             return true;
4288         }
4289 
4290         return false;
4291     }
4292 
4293     @GuardedBy("mSettingsLock")
updateRingerAndZenModeAffectedStreams()4294     private boolean updateRingerAndZenModeAffectedStreams() {
4295         boolean updatedZenModeAffectedStreams = updateZenModeAffectedStreams();
4296         int ringerModeAffectedStreams = Settings.System.getIntForUser(mContentResolver,
4297                 Settings.System.MODE_RINGER_STREAMS_AFFECTED,
4298                 ((1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_NOTIFICATION)|
4299                  (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)),
4300                  UserHandle.USER_CURRENT);
4301 
4302         if (mIsSingleVolume) {
4303             ringerModeAffectedStreams = 0;
4304         } else if (mRingerModeDelegate != null) {
4305             ringerModeAffectedStreams = mRingerModeDelegate
4306                     .getRingerModeAffectedStreams(ringerModeAffectedStreams);
4307         }
4308         if (mCameraSoundForced) {
4309             ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
4310         } else {
4311             ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
4312         }
4313         if (mStreamVolumeAlias[AudioSystem.STREAM_DTMF] == AudioSystem.STREAM_RING) {
4314             ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_DTMF);
4315         } else {
4316             ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_DTMF);
4317         }
4318 
4319         if (ringerModeAffectedStreams != mRingerModeAffectedStreams) {
4320             Settings.System.putIntForUser(mContentResolver,
4321                     Settings.System.MODE_RINGER_STREAMS_AFFECTED,
4322                     ringerModeAffectedStreams,
4323                     UserHandle.USER_CURRENT);
4324             mRingerModeAffectedStreams = ringerModeAffectedStreams;
4325             return true;
4326         }
4327         return updatedZenModeAffectedStreams;
4328     }
4329 
4330     @Override
isStreamAffectedByMute(int streamType)4331     public boolean isStreamAffectedByMute(int streamType) {
4332         return (mMuteAffectedStreams & (1 << streamType)) != 0;
4333     }
4334 
ensureValidDirection(int direction)4335     private void ensureValidDirection(int direction) {
4336         switch (direction) {
4337             case AudioManager.ADJUST_LOWER:
4338             case AudioManager.ADJUST_RAISE:
4339             case AudioManager.ADJUST_SAME:
4340             case AudioManager.ADJUST_MUTE:
4341             case AudioManager.ADJUST_UNMUTE:
4342             case AudioManager.ADJUST_TOGGLE_MUTE:
4343                 break;
4344             default:
4345                 throw new IllegalArgumentException("Bad direction " + direction);
4346         }
4347     }
4348 
ensureValidStreamType(int streamType)4349     private void ensureValidStreamType(int streamType) {
4350         if (streamType < 0 || streamType >= mStreamStates.length) {
4351             throw new IllegalArgumentException("Bad stream type " + streamType);
4352         }
4353     }
4354 
isMuteAdjust(int adjust)4355     private boolean isMuteAdjust(int adjust) {
4356         return adjust == AudioManager.ADJUST_MUTE || adjust == AudioManager.ADJUST_UNMUTE
4357                 || adjust == AudioManager.ADJUST_TOGGLE_MUTE;
4358     }
4359 
isInCommunication()4360     private boolean isInCommunication() {
4361         boolean IsInCall = false;
4362 
4363         TelecomManager telecomManager =
4364                 (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
4365 
4366         final long ident = Binder.clearCallingIdentity();
4367         IsInCall = telecomManager.isInCall();
4368         Binder.restoreCallingIdentity(ident);
4369 
4370         return (IsInCall || getMode() == AudioManager.MODE_IN_COMMUNICATION ||
4371                 getMode() == AudioManager.MODE_IN_CALL);
4372     }
4373 
4374     /**
4375      * For code clarity for getActiveStreamType(int)
4376      * @param delay_ms max time since last stream activity to consider
4377      * @return true if stream is active in streams handled by AudioFlinger now or
4378      *     in the last "delay_ms" ms.
4379      */
wasStreamActiveRecently(int stream, int delay_ms)4380     private boolean wasStreamActiveRecently(int stream, int delay_ms) {
4381         return AudioSystem.isStreamActive(stream, delay_ms)
4382                 || AudioSystem.isStreamActiveRemotely(stream, delay_ms);
4383     }
4384 
getActiveStreamType(int suggestedStreamType)4385     private int getActiveStreamType(int suggestedStreamType) {
4386         if (mIsSingleVolume
4387                 && suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
4388             return AudioSystem.STREAM_MUSIC;
4389         }
4390 
4391         switch (mPlatformType) {
4392         case AudioSystem.PLATFORM_VOICE:
4393             if (isInCommunication()) {
4394                 if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION)
4395                         == AudioSystem.FORCE_BT_SCO) {
4396                     // Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO...");
4397                     return AudioSystem.STREAM_BLUETOOTH_SCO;
4398                 } else {
4399                     // Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL...");
4400                     return AudioSystem.STREAM_VOICE_CALL;
4401                 }
4402             } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
4403                 if (wasStreamActiveRecently(AudioSystem.STREAM_RING, sStreamOverrideDelayMs)) {
4404                     if (DEBUG_VOL)
4405                         Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING stream active");
4406                     return AudioSystem.STREAM_RING;
4407                 } else if (wasStreamActiveRecently(
4408                         AudioSystem.STREAM_NOTIFICATION, sStreamOverrideDelayMs)) {
4409                     if (DEBUG_VOL)
4410                         Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION stream active");
4411                     return AudioSystem.STREAM_NOTIFICATION;
4412                 } else {
4413                     if (DEBUG_VOL) {
4414                         Log.v(TAG, "getActiveStreamType: Forcing DEFAULT_VOL_STREAM_NO_PLAYBACK("
4415                                 + DEFAULT_VOL_STREAM_NO_PLAYBACK + ") b/c default");
4416                     }
4417                     return DEFAULT_VOL_STREAM_NO_PLAYBACK;
4418                 }
4419             } else if (
4420                     wasStreamActiveRecently(AudioSystem.STREAM_NOTIFICATION, sStreamOverrideDelayMs)) {
4421                 if (DEBUG_VOL)
4422                     Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION stream active");
4423                 return AudioSystem.STREAM_NOTIFICATION;
4424             } else if (wasStreamActiveRecently(AudioSystem.STREAM_RING, sStreamOverrideDelayMs)) {
4425                 if (DEBUG_VOL)
4426                     Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING stream active");
4427                 return AudioSystem.STREAM_RING;
4428             }
4429         default:
4430             if (isInCommunication()) {
4431                 if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION)
4432                         == AudioSystem.FORCE_BT_SCO) {
4433                     if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO");
4434                     return AudioSystem.STREAM_BLUETOOTH_SCO;
4435                 } else {
4436                     if (DEBUG_VOL)  Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL");
4437                     return AudioSystem.STREAM_VOICE_CALL;
4438                 }
4439             } else if (AudioSystem.isStreamActive(
4440                     AudioSystem.STREAM_NOTIFICATION, sStreamOverrideDelayMs)) {
4441                 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION");
4442                 return AudioSystem.STREAM_NOTIFICATION;
4443             } else if (AudioSystem.isStreamActive(
4444                     AudioSystem.STREAM_RING, sStreamOverrideDelayMs)) {
4445                 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING");
4446                 return AudioSystem.STREAM_RING;
4447             } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
4448                 if (AudioSystem.isStreamActive(
4449                         AudioSystem.STREAM_NOTIFICATION, sStreamOverrideDelayMs)) {
4450                     if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION");
4451                     return AudioSystem.STREAM_NOTIFICATION;
4452                 } else if (AudioSystem.isStreamActive(
4453                         AudioSystem.STREAM_RING, sStreamOverrideDelayMs)) {
4454                     if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING");
4455                     return AudioSystem.STREAM_RING;
4456                 } else {
4457                     if (DEBUG_VOL) {
4458                         Log.v(TAG, "getActiveStreamType: Forcing DEFAULT_VOL_STREAM_NO_PLAYBACK("
4459                                 + DEFAULT_VOL_STREAM_NO_PLAYBACK + ") b/c default");
4460                     }
4461                     return DEFAULT_VOL_STREAM_NO_PLAYBACK;
4462                 }
4463             }
4464             break;
4465         }
4466         if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Returning suggested type "
4467                 + suggestedStreamType);
4468         return suggestedStreamType;
4469     }
4470 
broadcastRingerMode(String action, int ringerMode)4471     private void broadcastRingerMode(String action, int ringerMode) {
4472         // Send sticky broadcast
4473         Intent broadcast = new Intent(action);
4474         broadcast.putExtra(AudioManager.EXTRA_RINGER_MODE, ringerMode);
4475         broadcast.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
4476                 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
4477         sendStickyBroadcastToAll(broadcast);
4478     }
4479 
broadcastVibrateSetting(int vibrateType)4480     private void broadcastVibrateSetting(int vibrateType) {
4481         // Send broadcast
4482         if (mActivityManagerInternal.isSystemReady()) {
4483             Intent broadcast = new Intent(AudioManager.VIBRATE_SETTING_CHANGED_ACTION);
4484             broadcast.putExtra(AudioManager.EXTRA_VIBRATE_TYPE, vibrateType);
4485             broadcast.putExtra(AudioManager.EXTRA_VIBRATE_SETTING, getVibrateSetting(vibrateType));
4486             sendBroadcastToAll(broadcast);
4487         }
4488     }
4489 
4490     // Message helper methods
4491     /**
4492      * Queue a message on the given handler's message queue, after acquiring the service wake lock.
4493      * Note that the wake lock needs to be released after the message has been handled.
4494      */
queueMsgUnderWakeLock(Handler handler, int msg, int arg1, int arg2, Object obj, int delay)4495     private void queueMsgUnderWakeLock(Handler handler, int msg,
4496             int arg1, int arg2, Object obj, int delay) {
4497         final long ident = Binder.clearCallingIdentity();
4498         // Always acquire the wake lock as AudioService because it is released by the
4499         // message handler.
4500         mAudioEventWakeLock.acquire();
4501         Binder.restoreCallingIdentity(ident);
4502         sendMsg(handler, msg, SENDMSG_QUEUE, arg1, arg2, obj, delay);
4503     }
4504 
sendMsg(Handler handler, int msg, int existingMsgPolicy, int arg1, int arg2, Object obj, int delay)4505     private static void sendMsg(Handler handler, int msg,
4506             int existingMsgPolicy, int arg1, int arg2, Object obj, int delay) {
4507 
4508         if (existingMsgPolicy == SENDMSG_REPLACE) {
4509             handler.removeMessages(msg);
4510         } else if (existingMsgPolicy == SENDMSG_NOOP && handler.hasMessages(msg)) {
4511             return;
4512         }
4513         synchronized (mLastDeviceConnectMsgTime) {
4514             long time = SystemClock.uptimeMillis() + delay;
4515 
4516             if (msg == MSG_SET_A2DP_SRC_CONNECTION_STATE ||
4517                 msg == MSG_SET_A2DP_SINK_CONNECTION_STATE ||
4518                 msg == MSG_SET_HEARING_AID_CONNECTION_STATE ||
4519                 msg == MSG_SET_WIRED_DEVICE_CONNECTION_STATE ||
4520                 msg == MSG_A2DP_DEVICE_CONFIG_CHANGE ||
4521                 msg == MSG_BTA2DP_DOCK_TIMEOUT) {
4522                 if (mLastDeviceConnectMsgTime >= time) {
4523                   // add a little delay to make sure messages are ordered as expected
4524                   time = mLastDeviceConnectMsgTime + 30;
4525                 }
4526                 mLastDeviceConnectMsgTime = time;
4527             }
4528 
4529             handler.sendMessageAtTime(handler.obtainMessage(msg, arg1, arg2, obj), time);
4530         }
4531     }
4532 
checkAudioSettingsPermission(String method)4533     boolean checkAudioSettingsPermission(String method) {
4534         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS)
4535                 == PackageManager.PERMISSION_GRANTED) {
4536             return true;
4537         }
4538         String msg = "Audio Settings Permission Denial: " + method + " from pid="
4539                 + Binder.getCallingPid()
4540                 + ", uid=" + Binder.getCallingUid();
4541         Log.w(TAG, msg);
4542         return false;
4543     }
4544 
getDeviceForStream(int stream)4545     private int getDeviceForStream(int stream) {
4546         int device = getDevicesForStream(stream);
4547         if ((device & (device - 1)) != 0) {
4548             // Multiple device selection is either:
4549             //  - speaker + one other device: give priority to speaker in this case.
4550             //  - one A2DP device + another device: happens with duplicated output. In this case
4551             // retain the device on the A2DP output as the other must not correspond to an active
4552             // selection if not the speaker.
4553             //  - HDMI-CEC system audio mode only output: give priority to available item in order.
4554             if ((device & AudioSystem.DEVICE_OUT_SPEAKER) != 0) {
4555                 device = AudioSystem.DEVICE_OUT_SPEAKER;
4556             } else if ((device & AudioSystem.DEVICE_OUT_HDMI_ARC) != 0) {
4557                 device = AudioSystem.DEVICE_OUT_HDMI_ARC;
4558             } else if ((device & AudioSystem.DEVICE_OUT_SPDIF) != 0) {
4559                 device = AudioSystem.DEVICE_OUT_SPDIF;
4560             } else if ((device & AudioSystem.DEVICE_OUT_AUX_LINE) != 0) {
4561                 device = AudioSystem.DEVICE_OUT_AUX_LINE;
4562             } else {
4563                 device &= AudioSystem.DEVICE_OUT_ALL_A2DP;
4564             }
4565         }
4566         return device;
4567     }
4568 
getDevicesForStream(int stream)4569     private int getDevicesForStream(int stream) {
4570         return getDevicesForStream(stream, true /*checkOthers*/);
4571     }
4572 
getDevicesForStream(int stream, boolean checkOthers)4573     private int getDevicesForStream(int stream, boolean checkOthers) {
4574         ensureValidStreamType(stream);
4575         synchronized (VolumeStreamState.class) {
4576             return mStreamStates[stream].observeDevicesForStream_syncVSS(checkOthers);
4577         }
4578     }
4579 
observeDevicesForStreams(int skipStream)4580     private void observeDevicesForStreams(int skipStream) {
4581         synchronized (VolumeStreamState.class) {
4582             for (int stream = 0; stream < mStreamStates.length; stream++) {
4583                 if (stream != skipStream) {
4584                     mStreamStates[stream].observeDevicesForStream_syncVSS(false /*checkOthers*/);
4585                 }
4586             }
4587         }
4588     }
4589 
4590     /*
4591      * A class just for packaging up a set of connection parameters.
4592      */
4593     class WiredDeviceConnectionState {
4594         public final int mType;
4595         public final int mState;
4596         public final String mAddress;
4597         public final String mName;
4598         public final String mCaller;
4599 
WiredDeviceConnectionState(int type, int state, String address, String name, String caller)4600         public WiredDeviceConnectionState(int type, int state, String address, String name,
4601                 String caller) {
4602             mType = type;
4603             mState = state;
4604             mAddress = address;
4605             mName = name;
4606             mCaller = caller;
4607         }
4608     }
4609 
setWiredDeviceConnectionState(int type, int state, String address, String name, String caller)4610     public void setWiredDeviceConnectionState(int type, int state, String address, String name,
4611             String caller) {
4612         synchronized (mConnectedDevices) {
4613             if (DEBUG_DEVICES) {
4614                 Slog.i(TAG, "setWiredDeviceConnectionState(" + state + " nm: " + name + " addr:"
4615                         + address + ")");
4616             }
4617             int delay = checkSendBecomingNoisyIntent(type, state, AudioSystem.DEVICE_NONE);
4618             queueMsgUnderWakeLock(mAudioHandler,
4619                     MSG_SET_WIRED_DEVICE_CONNECTION_STATE,
4620                     0 /* arg1 unused */,
4621                     0 /* arg2 unused */,
4622                     new WiredDeviceConnectionState(type, state, address, name, caller),
4623                     delay);
4624         }
4625     }
4626 
4627     @Override
setHearingAidDeviceConnectionState(BluetoothDevice device, int state)4628     public void setHearingAidDeviceConnectionState(BluetoothDevice device, int state)
4629     {
4630         Log.i(TAG, "setBluetoothHearingAidDeviceConnectionState");
4631 
4632         setBluetoothHearingAidDeviceConnectionState(
4633                 device, state,  false /* suppressNoisyIntent */, AudioSystem.DEVICE_NONE);
4634     }
4635 
setBluetoothHearingAidDeviceConnectionState( BluetoothDevice device, int state, boolean suppressNoisyIntent, int musicDevice)4636     public int setBluetoothHearingAidDeviceConnectionState(
4637             BluetoothDevice device, int state, boolean suppressNoisyIntent,
4638             int musicDevice)
4639     {
4640         int delay;
4641         synchronized (mConnectedDevices) {
4642             if (!suppressNoisyIntent) {
4643                 int intState = (state == BluetoothHearingAid.STATE_CONNECTED) ? 1 : 0;
4644                 delay = checkSendBecomingNoisyIntent(AudioSystem.DEVICE_OUT_HEARING_AID,
4645                         intState, musicDevice);
4646             } else {
4647                 delay = 0;
4648             }
4649             queueMsgUnderWakeLock(mAudioHandler,
4650                     MSG_SET_HEARING_AID_CONNECTION_STATE,
4651                     state,
4652                     0 /* arg2 unused */,
4653                     device,
4654                     delay);
4655         }
4656         return delay;
4657     }
4658 
setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state, int profile)4659     public int setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state, int profile)
4660     {
4661         return setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
4662                 device, state, profile, false /* suppressNoisyIntent */, -1 /* a2dpVolume */);
4663     }
4664 
setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(BluetoothDevice device, int state, int profile, boolean suppressNoisyIntent, int a2dpVolume)4665     public int setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(BluetoothDevice device,
4666                 int state, int profile, boolean suppressNoisyIntent, int a2dpVolume)
4667     {
4668         if (mAudioHandler.hasMessages(MSG_SET_A2DP_SINK_CONNECTION_STATE, device)) {
4669             return 0;
4670         }
4671         return setBluetoothA2dpDeviceConnectionStateInt(
4672                 device, state, profile, suppressNoisyIntent, AudioSystem.DEVICE_NONE, a2dpVolume);
4673     }
4674 
setBluetoothA2dpDeviceConnectionStateInt( BluetoothDevice device, int state, int profile, boolean suppressNoisyIntent, int musicDevice, int a2dpVolume)4675     public int setBluetoothA2dpDeviceConnectionStateInt(
4676             BluetoothDevice device, int state, int profile, boolean suppressNoisyIntent,
4677             int musicDevice, int a2dpVolume)
4678     {
4679         int delay;
4680         if (profile != BluetoothProfile.A2DP && profile != BluetoothProfile.A2DP_SINK) {
4681             throw new IllegalArgumentException("invalid profile " + profile);
4682         }
4683         synchronized (mConnectedDevices) {
4684             if (profile == BluetoothProfile.A2DP && !suppressNoisyIntent) {
4685                 int intState = (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0;
4686                 delay = checkSendBecomingNoisyIntent(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
4687                         intState, musicDevice);
4688             } else {
4689                 delay = 0;
4690             }
4691 
4692             if (DEBUG_DEVICES) {
4693                 Log.d(TAG, "setBluetoothA2dpDeviceConnectionStateInt device: " + device
4694                       + " state: " + state + " delay(ms): " + delay
4695                       + " suppressNoisyIntent: " + suppressNoisyIntent);
4696             }
4697 
4698             queueMsgUnderWakeLock(mAudioHandler,
4699                     (profile == BluetoothProfile.A2DP ?
4700                         MSG_SET_A2DP_SINK_CONNECTION_STATE : MSG_SET_A2DP_SRC_CONNECTION_STATE),
4701                     state,
4702                     a2dpVolume,
4703                     device,
4704                     delay);
4705         }
4706         return delay;
4707     }
4708 
handleBluetoothA2dpDeviceConfigChange(BluetoothDevice device)4709     public void handleBluetoothA2dpDeviceConfigChange(BluetoothDevice device)
4710     {
4711         synchronized (mConnectedDevices) {
4712             queueMsgUnderWakeLock(mAudioHandler,
4713                     MSG_A2DP_DEVICE_CONFIG_CHANGE,
4714                     0 /* arg1 unused */,
4715                     0 /* arg1 unused */,
4716                     device,
4717                     0 /* delay */);
4718         }
4719     }
4720 
4721     private static final int DEVICE_MEDIA_UNMUTED_ON_PLUG =
4722             AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE |
4723             AudioSystem.DEVICE_OUT_LINE |
4724             AudioSystem.DEVICE_OUT_ALL_A2DP |
4725             AudioSystem.DEVICE_OUT_ALL_USB |
4726             AudioSystem.DEVICE_OUT_HDMI;
4727 
onAccessoryPlugMediaUnmute(int newDevice)4728     private void onAccessoryPlugMediaUnmute(int newDevice) {
4729         if (DEBUG_VOL) {
4730             Log.i(TAG, String.format("onAccessoryPlugMediaUnmute newDevice=%d [%s]",
4731                     newDevice, AudioSystem.getOutputDeviceName(newDevice)));
4732         }
4733         synchronized (mConnectedDevices) {
4734             if (mNm.getZenMode() != Settings.Global.ZEN_MODE_NO_INTERRUPTIONS
4735                     && (newDevice & DEVICE_MEDIA_UNMUTED_ON_PLUG) != 0
4736                     && mStreamStates[AudioSystem.STREAM_MUSIC].mIsMuted
4737                     && mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(newDevice) != 0
4738                     && (newDevice & AudioSystem.getDevicesForStream(AudioSystem.STREAM_MUSIC)) != 0)
4739             {
4740                 if (DEBUG_VOL) {
4741                     Log.i(TAG, String.format(" onAccessoryPlugMediaUnmute unmuting device=%d [%s]",
4742                             newDevice, AudioSystem.getOutputDeviceName(newDevice)));
4743                 }
4744                 mStreamStates[AudioSystem.STREAM_MUSIC].mute(false);
4745             }
4746         }
4747     }
4748 
4749     ///////////////////////////////////////////////////////////////////////////
4750     // Inner classes
4751     ///////////////////////////////////////////////////////////////////////////
4752 
4753     // NOTE: Locking order for synchronized objects related to volume or ringer mode management:
4754     //  1 mScoclient OR mSafeMediaVolumeState
4755     //  2   mSetModeDeathHandlers
4756     //  3     mSettingsLock
4757     //  4       VolumeStreamState.class
4758     public class VolumeStreamState {
4759         private final int mStreamType;
4760         private int mIndexMin;
4761         private int mIndexMax;
4762 
4763         private boolean mIsMuted;
4764         private String mVolumeIndexSettingName;
4765         private int mObservedDevices;
4766 
4767         private final SparseIntArray mIndexMap = new SparseIntArray(8);
4768         private final Intent mVolumeChanged;
4769         private final Intent mStreamDevicesChanged;
4770 
VolumeStreamState(String settingName, int streamType)4771         private VolumeStreamState(String settingName, int streamType) {
4772 
4773             mVolumeIndexSettingName = settingName;
4774 
4775             mStreamType = streamType;
4776             mIndexMin = MIN_STREAM_VOLUME[streamType] * 10;
4777             mIndexMax = MAX_STREAM_VOLUME[streamType] * 10;
4778             AudioSystem.initStreamVolume(streamType, mIndexMin / 10, mIndexMax / 10);
4779 
4780             readSettings();
4781             mVolumeChanged = new Intent(AudioManager.VOLUME_CHANGED_ACTION);
4782             mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
4783             mStreamDevicesChanged = new Intent(AudioManager.STREAM_DEVICES_CHANGED_ACTION);
4784             mStreamDevicesChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
4785         }
4786 
observeDevicesForStream_syncVSS(boolean checkOthers)4787         public int observeDevicesForStream_syncVSS(boolean checkOthers) {
4788             final int devices = AudioSystem.getDevicesForStream(mStreamType);
4789             if (devices == mObservedDevices) {
4790                 return devices;
4791             }
4792             final int prevDevices = mObservedDevices;
4793             mObservedDevices = devices;
4794             if (checkOthers) {
4795                 // one stream's devices have changed, check the others
4796                 observeDevicesForStreams(mStreamType);
4797             }
4798             // log base stream changes to the event log
4799             if (mStreamVolumeAlias[mStreamType] == mStreamType) {
4800                 EventLogTags.writeStreamDevicesChanged(mStreamType, prevDevices, devices);
4801             }
4802             sendBroadcastToAll(mStreamDevicesChanged
4803                     .putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_DEVICES, prevDevices)
4804                     .putExtra(AudioManager.EXTRA_VOLUME_STREAM_DEVICES, devices));
4805             return devices;
4806         }
4807 
getSettingNameForDevice(int device)4808         public @Nullable String getSettingNameForDevice(int device) {
4809             if (!hasValidSettingsName()) {
4810                 return null;
4811             }
4812             final String suffix = AudioSystem.getOutputDeviceName(device);
4813             if (suffix.isEmpty()) {
4814                 return mVolumeIndexSettingName;
4815             }
4816             return mVolumeIndexSettingName + "_" + suffix;
4817         }
4818 
hasValidSettingsName()4819         private boolean hasValidSettingsName() {
4820             return (mVolumeIndexSettingName != null && !mVolumeIndexSettingName.isEmpty());
4821         }
4822 
readSettings()4823         public void readSettings() {
4824             synchronized (mSettingsLock) {
4825                 synchronized (VolumeStreamState.class) {
4826                     // force maximum volume on all streams if fixed volume property is set
4827                     if (mUseFixedVolume) {
4828                         mIndexMap.put(AudioSystem.DEVICE_OUT_DEFAULT, mIndexMax);
4829                         return;
4830                     }
4831                     // do not read system stream volume from settings: this stream is always aliased
4832                     // to another stream type and its volume is never persisted. Values in settings can
4833                     // only be stale values
4834                     if ((mStreamType == AudioSystem.STREAM_SYSTEM) ||
4835                             (mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED)) {
4836                         int index = 10 * AudioSystem.DEFAULT_STREAM_VOLUME[mStreamType];
4837                         if (mCameraSoundForced) {
4838                             index = mIndexMax;
4839                         }
4840                         mIndexMap.put(AudioSystem.DEVICE_OUT_DEFAULT, index);
4841                         return;
4842                     }
4843                 }
4844             }
4845             synchronized (VolumeStreamState.class) {
4846                 int remainingDevices = AudioSystem.DEVICE_OUT_ALL;
4847 
4848                 for (int i = 0; remainingDevices != 0; i++) {
4849                     int device = (1 << i);
4850                     if ((device & remainingDevices) == 0) {
4851                         continue;
4852                     }
4853                     remainingDevices &= ~device;
4854 
4855                     // retrieve current volume for device
4856                     // if no volume stored for current stream and device, use default volume if default
4857                     // device, continue otherwise
4858                     int defaultIndex = (device == AudioSystem.DEVICE_OUT_DEFAULT) ?
4859                             AudioSystem.DEFAULT_STREAM_VOLUME[mStreamType] : -1;
4860                     int index;
4861                     if (!hasValidSettingsName()) {
4862                         index = defaultIndex;
4863                     } else {
4864                         String name = getSettingNameForDevice(device);
4865                         index = Settings.System.getIntForUser(
4866                                 mContentResolver, name, defaultIndex, UserHandle.USER_CURRENT);
4867                     }
4868                     if (index == -1) {
4869                         continue;
4870                     }
4871 
4872                     mIndexMap.put(device, getValidIndex(10 * index));
4873                 }
4874             }
4875         }
4876 
getAbsoluteVolumeIndex(int index)4877         private int getAbsoluteVolumeIndex(int index) {
4878             /* Special handling for Bluetooth Absolute Volume scenario
4879              * If we send full audio gain, some accessories are too loud even at its lowest
4880              * volume. We are not able to enumerate all such accessories, so here is the
4881              * workaround from phone side.
4882              * Pre-scale volume at lowest volume steps 1 2 and 3.
4883              * For volume step 0, set audio gain to 0 as some accessories won't mute on their end.
4884              */
4885             if (index == 0) {
4886                 // 0% for volume 0
4887                 index = 0;
4888             } else if (index == 1) {
4889                 // 50% for volume 1
4890                 index = (int)(mIndexMax * 0.5) /10;
4891             } else if (index == 2) {
4892                 // 70% for volume 2
4893                 index = (int)(mIndexMax * 0.70) /10;
4894             } else if (index == 3) {
4895                 // 85% for volume 3
4896                 index = (int)(mIndexMax * 0.85) /10;
4897             } else {
4898                 // otherwise, full gain
4899                 index = (mIndexMax + 5)/10;
4900             }
4901             return index;
4902         }
4903 
4904         // must be called while synchronized VolumeStreamState.class
applyDeviceVolume_syncVSS(int device)4905         public void applyDeviceVolume_syncVSS(int device) {
4906             int index;
4907             if (mIsMuted) {
4908                 index = 0;
4909             } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && mAvrcpAbsVolSupported) {
4910                 index = getAbsoluteVolumeIndex((getIndex(device) + 5)/10);
4911             } else if ((device & mFullVolumeDevices) != 0) {
4912                 index = (mIndexMax + 5)/10;
4913             } else if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
4914                 index = (mIndexMax + 5)/10;
4915             } else {
4916                 index = (getIndex(device) + 5)/10;
4917             }
4918             AudioSystem.setStreamVolumeIndex(mStreamType, index, device);
4919         }
4920 
applyAllVolumes()4921         public void applyAllVolumes() {
4922             synchronized (VolumeStreamState.class) {
4923                 // apply device specific volumes first
4924                 int index;
4925                 for (int i = 0; i < mIndexMap.size(); i++) {
4926                     final int device = mIndexMap.keyAt(i);
4927                     if (device != AudioSystem.DEVICE_OUT_DEFAULT) {
4928                         if (mIsMuted) {
4929                             index = 0;
4930                         } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
4931                                 mAvrcpAbsVolSupported) {
4932                             index = getAbsoluteVolumeIndex((getIndex(device) + 5)/10);
4933                         } else if ((device & mFullVolumeDevices) != 0) {
4934                             index = (mIndexMax + 5)/10;
4935                         } else if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
4936                             index = (mIndexMax + 5)/10;
4937                         } else {
4938                             index = (mIndexMap.valueAt(i) + 5)/10;
4939                         }
4940                         AudioSystem.setStreamVolumeIndex(mStreamType, index, device);
4941                     }
4942                 }
4943                 // apply default volume last: by convention , default device volume will be used
4944                 // by audio policy manager if no explicit volume is present for a given device type
4945                 if (mIsMuted) {
4946                     index = 0;
4947                 } else {
4948                     index = (getIndex(AudioSystem.DEVICE_OUT_DEFAULT) + 5)/10;
4949                 }
4950                 AudioSystem.setStreamVolumeIndex(
4951                         mStreamType, index, AudioSystem.DEVICE_OUT_DEFAULT);
4952             }
4953         }
4954 
adjustIndex(int deltaIndex, int device, String caller)4955         public boolean adjustIndex(int deltaIndex, int device, String caller) {
4956             return setIndex(getIndex(device) + deltaIndex, device, caller);
4957         }
4958 
setIndex(int index, int device, String caller)4959         public boolean setIndex(int index, int device, String caller) {
4960             boolean changed;
4961             int oldIndex;
4962             synchronized (mSettingsLock) {
4963                 synchronized (VolumeStreamState.class) {
4964                     oldIndex = getIndex(device);
4965                     index = getValidIndex(index);
4966                     if ((mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED) && mCameraSoundForced) {
4967                         index = mIndexMax;
4968                     }
4969                     mIndexMap.put(device, index);
4970 
4971                     changed = oldIndex != index;
4972                     // Apply change to all streams using this one as alias if:
4973                     // - the index actually changed OR
4974                     // - there is no volume index stored for this device on alias stream.
4975                     // If changing volume of current device, also change volume of current
4976                     // device on aliased stream
4977                     final boolean isCurrentDevice = (device == getDeviceForStream(mStreamType));
4978                     final int numStreamTypes = AudioSystem.getNumStreamTypes();
4979                     for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
4980                         final VolumeStreamState aliasStreamState = mStreamStates[streamType];
4981                         if (streamType != mStreamType &&
4982                                 mStreamVolumeAlias[streamType] == mStreamType &&
4983                                 (changed || !aliasStreamState.hasIndexForDevice(device))) {
4984                             final int scaledIndex = rescaleIndex(index, mStreamType, streamType);
4985                             aliasStreamState.setIndex(scaledIndex, device, caller);
4986                             if (isCurrentDevice) {
4987                                 aliasStreamState.setIndex(scaledIndex,
4988                                         getDeviceForStream(streamType), caller);
4989                             }
4990                         }
4991                     }
4992                     // Mirror changes in SPEAKER ringtone volume on SCO when
4993                     if (changed && mStreamType == AudioSystem.STREAM_RING
4994                             && device == AudioSystem.DEVICE_OUT_SPEAKER) {
4995                         for (int i = 0; i < mIndexMap.size(); i++) {
4996                             int otherDevice = mIndexMap.keyAt(i);
4997                             if ((otherDevice & AudioSystem.DEVICE_OUT_ALL_SCO) != 0) {
4998                                 mIndexMap.put(otherDevice, index);
4999                             }
5000                         }
5001                     }
5002                 }
5003             }
5004             if (changed) {
5005                 oldIndex = (oldIndex + 5) / 10;
5006                 index = (index + 5) / 10;
5007                 // log base stream changes to the event log
5008                 if (mStreamVolumeAlias[mStreamType] == mStreamType) {
5009                     if (caller == null) {
5010                         Log.w(TAG, "No caller for volume_changed event", new Throwable());
5011                     }
5012                     EventLogTags.writeVolumeChanged(mStreamType, oldIndex, index, mIndexMax / 10,
5013                             caller);
5014                 }
5015                 // fire changed intents for all streams
5016                 mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, index);
5017                 mVolumeChanged.putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, oldIndex);
5018                 mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE_ALIAS,
5019                         mStreamVolumeAlias[mStreamType]);
5020                 sendBroadcastToAll(mVolumeChanged);
5021             }
5022             return changed;
5023         }
5024 
getIndex(int device)5025         public int getIndex(int device) {
5026             synchronized (VolumeStreamState.class) {
5027                 int index = mIndexMap.get(device, -1);
5028                 if (index == -1) {
5029                     // there is always an entry for AudioSystem.DEVICE_OUT_DEFAULT
5030                     index = mIndexMap.get(AudioSystem.DEVICE_OUT_DEFAULT);
5031                 }
5032                 return index;
5033             }
5034         }
5035 
hasIndexForDevice(int device)5036         public boolean hasIndexForDevice(int device) {
5037             synchronized (VolumeStreamState.class) {
5038                 return (mIndexMap.get(device, -1) != -1);
5039             }
5040         }
5041 
getMaxIndex()5042         public int getMaxIndex() {
5043             return mIndexMax;
5044         }
5045 
getMinIndex()5046         public int getMinIndex() {
5047             return mIndexMin;
5048         }
5049 
5050         /**
5051          * Updates the min/max index values from another stream. Use this when changing the alias
5052          * for the current stream type.
5053          * @param sourceStreamType
5054          */
5055         // must be sync'd on mSettingsLock before VolumeStreamState.class
5056         @GuardedBy("VolumeStreamState.class")
refreshRange(int sourceStreamType)5057         public void refreshRange(int sourceStreamType) {
5058             mIndexMin = MIN_STREAM_VOLUME[sourceStreamType] * 10;
5059             mIndexMax = MAX_STREAM_VOLUME[sourceStreamType] * 10;
5060             // verify all current volumes are within bounds
5061             for (int i = 0 ; i < mIndexMap.size(); i++) {
5062                 final int device = mIndexMap.keyAt(i);
5063                 final int index = mIndexMap.valueAt(i);
5064                 mIndexMap.put(device, getValidIndex(index));
5065             }
5066         }
5067 
5068         /**
5069          * Copies all device/index pairs from the given VolumeStreamState after initializing
5070          * them with the volume for DEVICE_OUT_DEFAULT. No-op if the source VolumeStreamState
5071          * has the same stream type as this instance.
5072          * @param srcStream
5073          * @param caller
5074          */
5075         // must be sync'd on mSettingsLock before VolumeStreamState.class
5076         @GuardedBy("VolumeStreamState.class")
setAllIndexes(VolumeStreamState srcStream, String caller)5077         public void setAllIndexes(VolumeStreamState srcStream, String caller) {
5078             if (mStreamType == srcStream.mStreamType) {
5079                 return;
5080             }
5081             int srcStreamType = srcStream.getStreamType();
5082             // apply default device volume from source stream to all devices first in case
5083             // some devices are present in this stream state but not in source stream state
5084             int index = srcStream.getIndex(AudioSystem.DEVICE_OUT_DEFAULT);
5085             index = rescaleIndex(index, srcStreamType, mStreamType);
5086             for (int i = 0; i < mIndexMap.size(); i++) {
5087                 mIndexMap.put(mIndexMap.keyAt(i), index);
5088             }
5089             // Now apply actual volume for devices in source stream state
5090             SparseIntArray srcMap = srcStream.mIndexMap;
5091             for (int i = 0; i < srcMap.size(); i++) {
5092                 int device = srcMap.keyAt(i);
5093                 index = srcMap.valueAt(i);
5094                 index = rescaleIndex(index, srcStreamType, mStreamType);
5095 
5096                 setIndex(index, device, caller);
5097             }
5098         }
5099 
5100         // must be sync'd on mSettingsLock before VolumeStreamState.class
5101         @GuardedBy("VolumeStreamState.class")
setAllIndexesToMax()5102         public void setAllIndexesToMax() {
5103             for (int i = 0; i < mIndexMap.size(); i++) {
5104                 mIndexMap.put(mIndexMap.keyAt(i), mIndexMax);
5105             }
5106         }
5107 
mute(boolean state)5108         public void mute(boolean state) {
5109             boolean changed = false;
5110             synchronized (VolumeStreamState.class) {
5111                 if (state != mIsMuted) {
5112                     changed = true;
5113                     mIsMuted = state;
5114 
5115                     // Set the new mute volume. This propagates the values to
5116                     // the audio system, otherwise the volume won't be changed
5117                     // at the lower level.
5118                     sendMsg(mAudioHandler,
5119                             MSG_SET_ALL_VOLUMES,
5120                             SENDMSG_QUEUE,
5121                             0,
5122                             0,
5123                             this, 0);
5124                 }
5125             }
5126             if (changed) {
5127                 // Stream mute changed, fire the intent.
5128                 Intent intent = new Intent(AudioManager.STREAM_MUTE_CHANGED_ACTION);
5129                 intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
5130                 intent.putExtra(AudioManager.EXTRA_STREAM_VOLUME_MUTED, state);
5131                 sendBroadcastToAll(intent);
5132             }
5133         }
5134 
getStreamType()5135         public int getStreamType() {
5136             return mStreamType;
5137         }
5138 
checkFixedVolumeDevices()5139         public void checkFixedVolumeDevices() {
5140             synchronized (VolumeStreamState.class) {
5141                 // ignore settings for fixed volume devices: volume should always be at max or 0
5142                 if (mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_MUSIC) {
5143                     for (int i = 0; i < mIndexMap.size(); i++) {
5144                         int device = mIndexMap.keyAt(i);
5145                         int index = mIndexMap.valueAt(i);
5146                         if (((device & mFullVolumeDevices) != 0)
5147                                 || (((device & mFixedVolumeDevices) != 0) && index != 0)) {
5148                             mIndexMap.put(device, mIndexMax);
5149                         }
5150                         applyDeviceVolume_syncVSS(device);
5151                     }
5152                 }
5153             }
5154         }
5155 
getValidIndex(int index)5156         private int getValidIndex(int index) {
5157             if (index < mIndexMin) {
5158                 return mIndexMin;
5159             } else if (mUseFixedVolume || index > mIndexMax) {
5160                 return mIndexMax;
5161             }
5162 
5163             return index;
5164         }
5165 
dump(PrintWriter pw)5166         private void dump(PrintWriter pw) {
5167             pw.print("   Muted: ");
5168             pw.println(mIsMuted);
5169             pw.print("   Min: ");
5170             pw.println((mIndexMin + 5) / 10);
5171             pw.print("   Max: ");
5172             pw.println((mIndexMax + 5) / 10);
5173             pw.print("   Current: ");
5174             for (int i = 0; i < mIndexMap.size(); i++) {
5175                 if (i > 0) {
5176                     pw.print(", ");
5177                 }
5178                 final int device = mIndexMap.keyAt(i);
5179                 pw.print(Integer.toHexString(device));
5180                 final String deviceName = device == AudioSystem.DEVICE_OUT_DEFAULT ? "default"
5181                         : AudioSystem.getOutputDeviceName(device);
5182                 if (!deviceName.isEmpty()) {
5183                     pw.print(" (");
5184                     pw.print(deviceName);
5185                     pw.print(")");
5186                 }
5187                 pw.print(": ");
5188                 final int index = (mIndexMap.valueAt(i) + 5) / 10;
5189                 pw.print(index);
5190             }
5191             pw.println();
5192             pw.print("   Devices: ");
5193             final int devices = getDevicesForStream(mStreamType);
5194             int device, i = 0, n = 0;
5195             // iterate all devices from 1 to DEVICE_OUT_DEFAULT exclusive
5196             // (the default device is not returned by getDevicesForStream)
5197             while ((device = 1 << i) != AudioSystem.DEVICE_OUT_DEFAULT) {
5198                 if ((devices & device) != 0) {
5199                     if (n++ > 0) {
5200                         pw.print(", ");
5201                     }
5202                     pw.print(AudioSystem.getOutputDeviceName(device));
5203                 }
5204                 i++;
5205             }
5206         }
5207     }
5208 
5209     /** Thread that handles native AudioSystem control. */
5210     private class AudioSystemThread extends Thread {
AudioSystemThread()5211         AudioSystemThread() {
5212             super("AudioService");
5213         }
5214 
5215         @Override
run()5216         public void run() {
5217             // Set this thread up so the handler will work on it
5218             Looper.prepare();
5219 
5220             synchronized(AudioService.this) {
5221                 mAudioHandler = new AudioHandler();
5222 
5223                 // Notify that the handler has been created
5224                 AudioService.this.notify();
5225             }
5226 
5227             // Listen for volume change requests that are set by VolumePanel
5228             Looper.loop();
5229         }
5230     }
5231 
setDeviceVolume(VolumeStreamState streamState, int device)5232     private void setDeviceVolume(VolumeStreamState streamState, int device) {
5233 
5234         synchronized (VolumeStreamState.class) {
5235             // Apply volume
5236             streamState.applyDeviceVolume_syncVSS(device);
5237 
5238             // Apply change to all streams using this one as alias
5239             int numStreamTypes = AudioSystem.getNumStreamTypes();
5240             for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
5241                 if (streamType != streamState.mStreamType &&
5242                         mStreamVolumeAlias[streamType] == streamState.mStreamType) {
5243                     // Make sure volume is also maxed out on A2DP device for aliased stream
5244                     // that may have a different device selected
5245                     int streamDevice = getDeviceForStream(streamType);
5246                     if ((device != streamDevice) && mAvrcpAbsVolSupported &&
5247                             ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0)) {
5248                         mStreamStates[streamType].applyDeviceVolume_syncVSS(device);
5249                     }
5250                     mStreamStates[streamType].applyDeviceVolume_syncVSS(streamDevice);
5251                 }
5252             }
5253         }
5254         // Post a persist volume msg
5255         sendMsg(mAudioHandler,
5256                 MSG_PERSIST_VOLUME,
5257                 SENDMSG_QUEUE,
5258                 device,
5259                 0,
5260                 streamState,
5261                 PERSIST_DELAY);
5262 
5263     }
5264 
5265     /** Handles internal volume messages in separate volume thread. */
5266     private class AudioHandler extends Handler {
5267 
setAllVolumes(VolumeStreamState streamState)5268         private void setAllVolumes(VolumeStreamState streamState) {
5269 
5270             // Apply volume
5271             streamState.applyAllVolumes();
5272 
5273             // Apply change to all streams using this one as alias
5274             int numStreamTypes = AudioSystem.getNumStreamTypes();
5275             for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
5276                 if (streamType != streamState.mStreamType &&
5277                         mStreamVolumeAlias[streamType] == streamState.mStreamType) {
5278                     mStreamStates[streamType].applyAllVolumes();
5279                 }
5280             }
5281         }
5282 
persistVolume(VolumeStreamState streamState, int device)5283         private void persistVolume(VolumeStreamState streamState, int device) {
5284             if (mUseFixedVolume) {
5285                 return;
5286             }
5287             if (mIsSingleVolume && (streamState.mStreamType != AudioSystem.STREAM_MUSIC)) {
5288                 return;
5289             }
5290             if (streamState.hasValidSettingsName()) {
5291                 System.putIntForUser(mContentResolver,
5292                         streamState.getSettingNameForDevice(device),
5293                         (streamState.getIndex(device) + 5)/ 10,
5294                         UserHandle.USER_CURRENT);
5295             }
5296         }
5297 
persistRingerMode(int ringerMode)5298         private void persistRingerMode(int ringerMode) {
5299             if (mUseFixedVolume) {
5300                 return;
5301             }
5302             Settings.Global.putInt(mContentResolver, Settings.Global.MODE_RINGER, ringerMode);
5303         }
5304 
getSoundEffectFilePath(int effectType)5305         private String getSoundEffectFilePath(int effectType) {
5306             String filePath = Environment.getProductDirectory() + SOUND_EFFECTS_PATH
5307                     + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]);
5308             if (!new File(filePath).isFile()) {
5309                 filePath = Environment.getRootDirectory() + SOUND_EFFECTS_PATH
5310                         + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]);
5311             }
5312             return filePath;
5313         }
5314 
onLoadSoundEffects()5315         private boolean onLoadSoundEffects() {
5316             int status;
5317 
5318             synchronized (mSoundEffectsLock) {
5319                 if (!mSystemReady) {
5320                     Log.w(TAG, "onLoadSoundEffects() called before boot complete");
5321                     return false;
5322                 }
5323 
5324                 if (mSoundPool != null) {
5325                     return true;
5326                 }
5327 
5328                 loadTouchSoundAssets();
5329 
5330                 mSoundPool = new SoundPool.Builder()
5331                         .setMaxStreams(NUM_SOUNDPOOL_CHANNELS)
5332                         .setAudioAttributes(new AudioAttributes.Builder()
5333                             .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
5334                             .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
5335                             .build())
5336                         .build();
5337                 mSoundPoolCallBack = null;
5338                 mSoundPoolListenerThread = new SoundPoolListenerThread();
5339                 mSoundPoolListenerThread.start();
5340                 int attempts = 3;
5341                 while ((mSoundPoolCallBack == null) && (attempts-- > 0)) {
5342                     try {
5343                         // Wait for mSoundPoolCallBack to be set by the other thread
5344                         mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
5345                     } catch (InterruptedException e) {
5346                         Log.w(TAG, "Interrupted while waiting sound pool listener thread.");
5347                     }
5348                 }
5349 
5350                 if (mSoundPoolCallBack == null) {
5351                     Log.w(TAG, "onLoadSoundEffects() SoundPool listener or thread creation error");
5352                     if (mSoundPoolLooper != null) {
5353                         mSoundPoolLooper.quit();
5354                         mSoundPoolLooper = null;
5355                     }
5356                     mSoundPoolListenerThread = null;
5357                     mSoundPool.release();
5358                     mSoundPool = null;
5359                     return false;
5360                 }
5361                 /*
5362                  * poolId table: The value -1 in this table indicates that corresponding
5363                  * file (same index in SOUND_EFFECT_FILES[] has not been loaded.
5364                  * Once loaded, the value in poolId is the sample ID and the same
5365                  * sample can be reused for another effect using the same file.
5366                  */
5367                 int[] poolId = new int[SOUND_EFFECT_FILES.size()];
5368                 for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) {
5369                     poolId[fileIdx] = -1;
5370                 }
5371                 /*
5372                  * Effects whose value in SOUND_EFFECT_FILES_MAP[effect][1] is -1 must be loaded.
5373                  * If load succeeds, value in SOUND_EFFECT_FILES_MAP[effect][1] is > 0:
5374                  * this indicates we have a valid sample loaded for this effect.
5375                  */
5376 
5377                 int numSamples = 0;
5378                 for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
5379                     // Do not load sample if this effect uses the MediaPlayer
5380                     if (SOUND_EFFECT_FILES_MAP[effect][1] == 0) {
5381                         continue;
5382                     }
5383                     if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == -1) {
5384                         String filePath = getSoundEffectFilePath(effect);
5385                         int sampleId = mSoundPool.load(filePath, 0);
5386                         if (sampleId <= 0) {
5387                             Log.w(TAG, "Soundpool could not load file: "+filePath);
5388                         } else {
5389                             SOUND_EFFECT_FILES_MAP[effect][1] = sampleId;
5390                             poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = sampleId;
5391                             numSamples++;
5392                         }
5393                     } else {
5394                         SOUND_EFFECT_FILES_MAP[effect][1] =
5395                                 poolId[SOUND_EFFECT_FILES_MAP[effect][0]];
5396                     }
5397                 }
5398                 // wait for all samples to be loaded
5399                 if (numSamples > 0) {
5400                     mSoundPoolCallBack.setSamples(poolId);
5401 
5402                     attempts = 3;
5403                     status = 1;
5404                     while ((status == 1) && (attempts-- > 0)) {
5405                         try {
5406                             mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
5407                             status = mSoundPoolCallBack.status();
5408                         } catch (InterruptedException e) {
5409                             Log.w(TAG, "Interrupted while waiting sound pool callback.");
5410                         }
5411                     }
5412                 } else {
5413                     status = -1;
5414                 }
5415 
5416                 if (mSoundPoolLooper != null) {
5417                     mSoundPoolLooper.quit();
5418                     mSoundPoolLooper = null;
5419                 }
5420                 mSoundPoolListenerThread = null;
5421                 if (status != 0) {
5422                     Log.w(TAG,
5423                             "onLoadSoundEffects(), Error "+status+ " while loading samples");
5424                     for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
5425                         if (SOUND_EFFECT_FILES_MAP[effect][1] > 0) {
5426                             SOUND_EFFECT_FILES_MAP[effect][1] = -1;
5427                         }
5428                     }
5429 
5430                     mSoundPool.release();
5431                     mSoundPool = null;
5432                 }
5433             }
5434             return (status == 0);
5435         }
5436 
5437         /**
5438          *  Unloads samples from the sound pool.
5439          *  This method can be called to free some memory when
5440          *  sound effects are disabled.
5441          */
onUnloadSoundEffects()5442         private void onUnloadSoundEffects() {
5443             synchronized (mSoundEffectsLock) {
5444                 if (mSoundPool == null) {
5445                     return;
5446                 }
5447 
5448                 int[] poolId = new int[SOUND_EFFECT_FILES.size()];
5449                 for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) {
5450                     poolId[fileIdx] = 0;
5451                 }
5452 
5453                 for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
5454                     if (SOUND_EFFECT_FILES_MAP[effect][1] <= 0) {
5455                         continue;
5456                     }
5457                     if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == 0) {
5458                         mSoundPool.unload(SOUND_EFFECT_FILES_MAP[effect][1]);
5459                         SOUND_EFFECT_FILES_MAP[effect][1] = -1;
5460                         poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = -1;
5461                     }
5462                 }
5463                 mSoundPool.release();
5464                 mSoundPool = null;
5465             }
5466         }
5467 
onPlaySoundEffect(int effectType, int volume)5468         private void onPlaySoundEffect(int effectType, int volume) {
5469             synchronized (mSoundEffectsLock) {
5470 
5471                 onLoadSoundEffects();
5472 
5473                 if (mSoundPool == null) {
5474                     return;
5475                 }
5476                 float volFloat;
5477                 // use default if volume is not specified by caller
5478                 if (volume < 0) {
5479                     volFloat = (float)Math.pow(10, (float)sSoundEffectVolumeDb/20);
5480                 } else {
5481                     volFloat = volume / 1000.0f;
5482                 }
5483 
5484                 if (SOUND_EFFECT_FILES_MAP[effectType][1] > 0) {
5485                     mSoundPool.play(SOUND_EFFECT_FILES_MAP[effectType][1],
5486                                         volFloat, volFloat, 0, 0, 1.0f);
5487                 } else {
5488                     MediaPlayer mediaPlayer = new MediaPlayer();
5489                     try {
5490                         String filePath = getSoundEffectFilePath(effectType);
5491                         mediaPlayer.setDataSource(filePath);
5492                         mediaPlayer.setAudioStreamType(AudioSystem.STREAM_SYSTEM);
5493                         mediaPlayer.prepare();
5494                         mediaPlayer.setVolume(volFloat);
5495                         mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
5496                             public void onCompletion(MediaPlayer mp) {
5497                                 cleanupPlayer(mp);
5498                             }
5499                         });
5500                         mediaPlayer.setOnErrorListener(new OnErrorListener() {
5501                             public boolean onError(MediaPlayer mp, int what, int extra) {
5502                                 cleanupPlayer(mp);
5503                                 return true;
5504                             }
5505                         });
5506                         mediaPlayer.start();
5507                     } catch (IOException ex) {
5508                         Log.w(TAG, "MediaPlayer IOException: "+ex);
5509                     } catch (IllegalArgumentException ex) {
5510                         Log.w(TAG, "MediaPlayer IllegalArgumentException: "+ex);
5511                     } catch (IllegalStateException ex) {
5512                         Log.w(TAG, "MediaPlayer IllegalStateException: "+ex);
5513                     }
5514                 }
5515             }
5516         }
5517 
cleanupPlayer(MediaPlayer mp)5518         private void cleanupPlayer(MediaPlayer mp) {
5519             if (mp != null) {
5520                 try {
5521                     mp.stop();
5522                     mp.release();
5523                 } catch (IllegalStateException ex) {
5524                     Log.w(TAG, "MediaPlayer IllegalStateException: "+ex);
5525                 }
5526             }
5527         }
5528 
setForceUse(int usage, int config, String eventSource)5529         private void setForceUse(int usage, int config, String eventSource) {
5530             synchronized (mConnectedDevices) {
5531                 setForceUseInt_SyncDevices(usage, config, eventSource);
5532             }
5533         }
5534 
onPersistSafeVolumeState(int state)5535         private void onPersistSafeVolumeState(int state) {
5536             Settings.Global.putInt(mContentResolver,
5537                     Settings.Global.AUDIO_SAFE_VOLUME_STATE,
5538                     state);
5539         }
5540 
onNotifyVolumeEvent(@onNull IAudioPolicyCallback apc, @AudioManager.VolumeAdjustment int direction)5541         private void onNotifyVolumeEvent(@NonNull IAudioPolicyCallback apc,
5542                 @AudioManager.VolumeAdjustment int direction) {
5543             try {
5544                 apc.notifyVolumeAdjust(direction);
5545             } catch(Exception e) {
5546                 // nothing we can do about this. Do not log error, too much potential for spam
5547             }
5548         }
5549 
5550         @Override
handleMessage(Message msg)5551         public void handleMessage(Message msg) {
5552             switch (msg.what) {
5553 
5554                 case MSG_SET_DEVICE_VOLUME:
5555                     setDeviceVolume((VolumeStreamState) msg.obj, msg.arg1);
5556                     break;
5557 
5558                 case MSG_SET_ALL_VOLUMES:
5559                     setAllVolumes((VolumeStreamState) msg.obj);
5560                     break;
5561 
5562                 case MSG_PERSIST_VOLUME:
5563                     persistVolume((VolumeStreamState) msg.obj, msg.arg1);
5564                     break;
5565 
5566                 case MSG_PERSIST_RINGER_MODE:
5567                     // note that the value persisted is the current ringer mode, not the
5568                     // value of ringer mode as of the time the request was made to persist
5569                     persistRingerMode(getRingerModeInternal());
5570                     break;
5571 
5572                 case MSG_AUDIO_SERVER_DIED:
5573                     onAudioServerDied();
5574                     break;
5575 
5576                 case MSG_DISPATCH_AUDIO_SERVER_STATE:
5577                     onDispatchAudioServerStateChange(msg.arg1 == 1);
5578                     break;
5579 
5580                 case MSG_UNLOAD_SOUND_EFFECTS:
5581                     onUnloadSoundEffects();
5582                     break;
5583 
5584                 case MSG_LOAD_SOUND_EFFECTS:
5585                     //FIXME: onLoadSoundEffects() should be executed in a separate thread as it
5586                     // can take several dozens of milliseconds to complete
5587                     boolean loaded = onLoadSoundEffects();
5588                     if (msg.obj != null) {
5589                         LoadSoundEffectReply reply = (LoadSoundEffectReply)msg.obj;
5590                         synchronized (reply) {
5591                             reply.mStatus = loaded ? 0 : -1;
5592                             reply.notify();
5593                         }
5594                     }
5595                     break;
5596 
5597                 case MSG_PLAY_SOUND_EFFECT:
5598                     onPlaySoundEffect(msg.arg1, msg.arg2);
5599                     break;
5600 
5601                 case MSG_BTA2DP_DOCK_TIMEOUT:
5602                     // msg.obj  == address of BTA2DP device
5603                     synchronized (mConnectedDevices) {
5604                         makeA2dpDeviceUnavailableNow( (String) msg.obj );
5605                     }
5606                     mAudioEventWakeLock.release();
5607                     break;
5608 
5609                 case MSG_SET_FORCE_USE:
5610                 case MSG_SET_FORCE_BT_A2DP_USE:
5611                     setForceUse(msg.arg1, msg.arg2, (String) msg.obj);
5612                     break;
5613 
5614                 case MSG_BT_HEADSET_CNCT_FAILED:
5615                     resetBluetoothSco();
5616                     break;
5617 
5618                 case MSG_SET_WIRED_DEVICE_CONNECTION_STATE:
5619                     {   WiredDeviceConnectionState connectState =
5620                             (WiredDeviceConnectionState)msg.obj;
5621                         mWiredDevLogger.log(new WiredDevConnectEvent(connectState));
5622                         onSetWiredDeviceConnectionState(connectState.mType, connectState.mState,
5623                                 connectState.mAddress, connectState.mName, connectState.mCaller);
5624                         mAudioEventWakeLock.release();
5625                     }
5626                     break;
5627 
5628                 case MSG_SET_A2DP_SRC_CONNECTION_STATE:
5629                     onSetA2dpSourceConnectionState((BluetoothDevice)msg.obj, msg.arg1);
5630                     mAudioEventWakeLock.release();
5631                     break;
5632 
5633                 case MSG_SET_A2DP_SINK_CONNECTION_STATE:
5634                     onSetA2dpSinkConnectionState((BluetoothDevice)msg.obj, msg.arg1, msg.arg2);
5635                     mAudioEventWakeLock.release();
5636                     break;
5637 
5638                 case MSG_SET_HEARING_AID_CONNECTION_STATE:
5639                     onSetHearingAidConnectionState((BluetoothDevice)msg.obj, msg.arg1);
5640                     mAudioEventWakeLock.release();
5641                     break;
5642 
5643                 case MSG_A2DP_DEVICE_CONFIG_CHANGE:
5644                     onBluetoothA2dpDeviceConfigChange((BluetoothDevice)msg.obj);
5645                     mAudioEventWakeLock.release();
5646                     break;
5647 
5648                 case MSG_DISABLE_AUDIO_FOR_UID:
5649                     mPlaybackMonitor.disableAudioForUid( msg.arg1 == 1 /* disable */,
5650                             msg.arg2 /* uid */);
5651                     mAudioEventWakeLock.release();
5652                     break;
5653 
5654                 case MSG_REPORT_NEW_ROUTES: {
5655                     int N = mRoutesObservers.beginBroadcast();
5656                     if (N > 0) {
5657                         AudioRoutesInfo routes;
5658                         synchronized (mCurAudioRoutes) {
5659                             routes = new AudioRoutesInfo(mCurAudioRoutes);
5660                         }
5661                         while (N > 0) {
5662                             N--;
5663                             IAudioRoutesObserver obs = mRoutesObservers.getBroadcastItem(N);
5664                             try {
5665                                 obs.dispatchAudioRoutesChanged(routes);
5666                             } catch (RemoteException e) {
5667                             }
5668                         }
5669                     }
5670                     mRoutesObservers.finishBroadcast();
5671                     observeDevicesForStreams(-1);
5672                     break;
5673                 }
5674 
5675                 case MSG_CHECK_MUSIC_ACTIVE:
5676                     onCheckMusicActive((String) msg.obj);
5677                     break;
5678 
5679                 case MSG_BROADCAST_AUDIO_BECOMING_NOISY:
5680                     onSendBecomingNoisyIntent();
5681                     break;
5682 
5683                 case MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED:
5684                 case MSG_CONFIGURE_SAFE_MEDIA_VOLUME:
5685                     onConfigureSafeVolume((msg.what == MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED),
5686                             (String) msg.obj);
5687                     break;
5688                 case MSG_PERSIST_SAFE_VOLUME_STATE:
5689                     onPersistSafeVolumeState(msg.arg1);
5690                     break;
5691 
5692                 case MSG_BROADCAST_BT_CONNECTION_STATE:
5693                     onBroadcastScoConnectionState(msg.arg1);
5694                     break;
5695 
5696                 case MSG_SYSTEM_READY:
5697                     onSystemReady();
5698                     break;
5699 
5700                 case MSG_INDICATE_SYSTEM_READY:
5701                     onIndicateSystemReady();
5702                     break;
5703 
5704                 case MSG_ACCESSORY_PLUG_MEDIA_UNMUTE:
5705                     onAccessoryPlugMediaUnmute(msg.arg1);
5706                     break;
5707 
5708                 case MSG_PERSIST_MUSIC_ACTIVE_MS:
5709                     final int musicActiveMs = msg.arg1;
5710                     Settings.Secure.putIntForUser(mContentResolver,
5711                             Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS, musicActiveMs,
5712                             UserHandle.USER_CURRENT);
5713                     break;
5714 
5715                 case MSG_UNMUTE_STREAM:
5716                     onUnmuteStream(msg.arg1, msg.arg2);
5717                     break;
5718 
5719                 case MSG_DYN_POLICY_MIX_STATE_UPDATE:
5720                     onDynPolicyMixStateUpdate((String) msg.obj, msg.arg1);
5721                     break;
5722 
5723                 case MSG_NOTIFY_VOL_EVENT:
5724                     onNotifyVolumeEvent((IAudioPolicyCallback) msg.obj, msg.arg1);
5725                     break;
5726 
5727                 case MSG_ENABLE_SURROUND_FORMATS:
5728                     onEnableSurroundFormats((ArrayList<Integer>) msg.obj);
5729                     break;
5730             }
5731         }
5732     }
5733 
5734     private class SettingsObserver extends ContentObserver {
5735 
SettingsObserver()5736         SettingsObserver() {
5737             super(new Handler());
5738             mContentResolver.registerContentObserver(Settings.Global.getUriFor(
5739                     Settings.Global.ZEN_MODE), false, this);
5740             mContentResolver.registerContentObserver(Settings.Global.getUriFor(
5741                     Settings.Global.ZEN_MODE_CONFIG_ETAG), false, this);
5742             mContentResolver.registerContentObserver(Settings.System.getUriFor(
5743                 Settings.System.MODE_RINGER_STREAMS_AFFECTED), false, this);
5744             mContentResolver.registerContentObserver(Settings.Global.getUriFor(
5745                 Settings.Global.DOCK_AUDIO_MEDIA_ENABLED), false, this);
5746             mContentResolver.registerContentObserver(Settings.System.getUriFor(
5747                     Settings.System.MASTER_MONO), false, this);
5748 
5749             mEncodedSurroundMode = Settings.Global.getInt(
5750                     mContentResolver, Settings.Global.ENCODED_SURROUND_OUTPUT,
5751                     Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
5752             mContentResolver.registerContentObserver(Settings.Global.getUriFor(
5753                     Settings.Global.ENCODED_SURROUND_OUTPUT), false, this);
5754 
5755             mEnabledSurroundFormats = Settings.Global.getString(
5756                     mContentResolver, Settings.Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS);
5757             mContentResolver.registerContentObserver(Settings.Global.getUriFor(
5758                     Settings.Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS), false, this);
5759         }
5760 
5761         @Override
onChange(boolean selfChange)5762         public void onChange(boolean selfChange) {
5763             super.onChange(selfChange);
5764             // FIXME This synchronized is not necessary if mSettingsLock only protects mRingerMode.
5765             //       However there appear to be some missing locks around mRingerAndZenModeMutedStreams
5766             //       and mRingerModeAffectedStreams, so will leave this synchronized for now.
5767             //       mRingerAndZenModeMutedStreams and mMuteAffectedStreams are safe (only accessed once).
5768             synchronized (mSettingsLock) {
5769                 if (updateRingerAndZenModeAffectedStreams()) {
5770                     /*
5771                      * Ensure all stream types that should be affected by ringer mode
5772                      * are in the proper state.
5773                      */
5774                     setRingerModeInt(getRingerModeInternal(), false);
5775                 }
5776                 readDockAudioSettings(mContentResolver);
5777                 updateMasterMono(mContentResolver);
5778                 updateEncodedSurroundOutput();
5779                 sendEnabledSurroundFormats(mContentResolver, mSurroundModeChanged);
5780             }
5781         }
5782 
updateEncodedSurroundOutput()5783         private void updateEncodedSurroundOutput() {
5784             int newSurroundMode = Settings.Global.getInt(
5785                 mContentResolver, Settings.Global.ENCODED_SURROUND_OUTPUT,
5786                 Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
5787             // Did it change?
5788             if (mEncodedSurroundMode != newSurroundMode) {
5789                 // Send to AudioPolicyManager
5790                 sendEncodedSurroundMode(newSurroundMode, "SettingsObserver");
5791                 synchronized(mConnectedDevices) {
5792                     // Is HDMI connected?
5793                     String key = makeDeviceListKey(AudioSystem.DEVICE_OUT_HDMI, "");
5794                     DeviceListSpec deviceSpec = mConnectedDevices.get(key);
5795                     if (deviceSpec != null) {
5796                         // Toggle HDMI to retrigger broadcast with proper formats.
5797                         setWiredDeviceConnectionState(AudioSystem.DEVICE_OUT_HDMI,
5798                                 AudioSystem.DEVICE_STATE_UNAVAILABLE, "", "",
5799                                 "android"); // disconnect
5800                         setWiredDeviceConnectionState(AudioSystem.DEVICE_OUT_HDMI,
5801                                 AudioSystem.DEVICE_STATE_AVAILABLE, "", "",
5802                                 "android"); // reconnect
5803                     }
5804                 }
5805                 mEncodedSurroundMode = newSurroundMode;
5806                 mSurroundModeChanged = true;
5807             } else {
5808                 mSurroundModeChanged = false;
5809             }
5810         }
5811     }
5812 
5813     // must be called synchronized on mConnectedDevices
makeA2dpDeviceAvailable(String address, String name, String eventSource)5814     private void makeA2dpDeviceAvailable(String address, String name, String eventSource) {
5815         // enable A2DP before notifying A2DP connection to avoid unnecessary processing in
5816         // audio policy manager
5817         VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC];
5818         setBluetoothA2dpOnInt(true, eventSource);
5819         AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
5820                 AudioSystem.DEVICE_STATE_AVAILABLE, address, name);
5821         // Reset A2DP suspend state each time a new sink is connected
5822         AudioSystem.setParameters("A2dpSuspended=false");
5823         mConnectedDevices.put(
5824                 makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address),
5825                 new DeviceListSpec(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, name,
5826                                    address));
5827         sendMsg(mAudioHandler, MSG_ACCESSORY_PLUG_MEDIA_UNMUTE, SENDMSG_QUEUE,
5828                 AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0, null, 0);
5829     }
5830 
onSendBecomingNoisyIntent()5831     private void onSendBecomingNoisyIntent() {
5832         sendBroadcastToAll(new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY));
5833     }
5834 
5835     // must be called synchronized on mConnectedDevices
makeA2dpDeviceUnavailableNow(String address)5836     private void makeA2dpDeviceUnavailableNow(String address) {
5837         if (address == null) {
5838             return;
5839         }
5840         synchronized (mA2dpAvrcpLock) {
5841             mAvrcpAbsVolSupported = false;
5842         }
5843         AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
5844                 AudioSystem.DEVICE_STATE_UNAVAILABLE, address, "");
5845         mConnectedDevices.remove(
5846                 makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address));
5847         // Remove A2DP routes as well
5848         setCurrentAudioRouteName(null);
5849         if (mDockAddress == address) {
5850             mDockAddress = null;
5851         }
5852     }
5853 
5854     // must be called synchronized on mConnectedDevices
makeA2dpDeviceUnavailableLater(String address, int delayMs)5855     private void makeA2dpDeviceUnavailableLater(String address, int delayMs) {
5856         // prevent any activity on the A2DP audio output to avoid unwanted
5857         // reconnection of the sink.
5858         AudioSystem.setParameters("A2dpSuspended=true");
5859         // the device will be made unavailable later, so consider it disconnected right away
5860         mConnectedDevices.remove(
5861                 makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address));
5862         // send the delayed message to make the device unavailable later
5863         queueMsgUnderWakeLock(mAudioHandler,
5864             MSG_BTA2DP_DOCK_TIMEOUT,
5865             0,
5866             0,
5867             address,
5868             delayMs);
5869     }
5870 
5871     // must be called synchronized on mConnectedDevices
makeA2dpSrcAvailable(String address)5872     private void makeA2dpSrcAvailable(String address) {
5873         AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP,
5874                 AudioSystem.DEVICE_STATE_AVAILABLE, address, "");
5875         mConnectedDevices.put(
5876                 makeDeviceListKey(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, address),
5877                 new DeviceListSpec(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, "",
5878                                    address));
5879     }
5880 
5881     // must be called synchronized on mConnectedDevices
makeA2dpSrcUnavailable(String address)5882     private void makeA2dpSrcUnavailable(String address) {
5883         AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP,
5884                 AudioSystem.DEVICE_STATE_UNAVAILABLE, address, "");
5885         mConnectedDevices.remove(
5886                 makeDeviceListKey(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, address));
5887     }
5888 
setHearingAidVolume(int index, int streamType)5889     private void setHearingAidVolume(int index, int streamType) {
5890         synchronized (mHearingAidLock) {
5891             if (mHearingAid != null) {
5892                 //hearing aid expect volume value in range -128dB to 0dB
5893                 int gainDB = (int)AudioSystem.getStreamVolumeDB(streamType, index/10,
5894                         AudioSystem.DEVICE_OUT_HEARING_AID);
5895                 if (gainDB < BT_HEARING_AID_GAIN_MIN)
5896                     gainDB = BT_HEARING_AID_GAIN_MIN;
5897                 mHearingAid.setVolume(gainDB);
5898             }
5899         }
5900     }
5901 
5902     // must be called synchronized on mConnectedDevices
makeHearingAidDeviceAvailable(String address, String name, String eventSource)5903     private void makeHearingAidDeviceAvailable(String address, String name, String eventSource) {
5904         int index = mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(AudioSystem.DEVICE_OUT_HEARING_AID);
5905         setHearingAidVolume(index, AudioSystem.STREAM_MUSIC);
5906 
5907         AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_HEARING_AID,
5908                 AudioSystem.DEVICE_STATE_AVAILABLE, address, name);
5909         mConnectedDevices.put(
5910                 makeDeviceListKey(AudioSystem.DEVICE_OUT_HEARING_AID, address),
5911                 new DeviceListSpec(AudioSystem.DEVICE_OUT_HEARING_AID, name,
5912                                    address));
5913         sendMsg(mAudioHandler, MSG_ACCESSORY_PLUG_MEDIA_UNMUTE, SENDMSG_QUEUE,
5914                 AudioSystem.DEVICE_OUT_HEARING_AID, 0, null, 0);
5915     }
5916 
5917     // must be called synchronized on mConnectedDevices
makeHearingAidDeviceUnavailable(String address)5918     private void makeHearingAidDeviceUnavailable(String address) {
5919         AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_HEARING_AID,
5920                 AudioSystem.DEVICE_STATE_UNAVAILABLE, address, "");
5921         mConnectedDevices.remove(
5922                 makeDeviceListKey(AudioSystem.DEVICE_OUT_HEARING_AID, address));
5923         // Remove Hearing Aid routes as well
5924         setCurrentAudioRouteName(null);
5925     }
5926 
5927     // must be called synchronized on mConnectedDevices
cancelA2dpDeviceTimeout()5928     private void cancelA2dpDeviceTimeout() {
5929         mAudioHandler.removeMessages(MSG_BTA2DP_DOCK_TIMEOUT);
5930     }
5931 
5932     // must be called synchronized on mConnectedDevices
hasScheduledA2dpDockTimeout()5933     private boolean hasScheduledA2dpDockTimeout() {
5934         return mAudioHandler.hasMessages(MSG_BTA2DP_DOCK_TIMEOUT);
5935     }
5936 
onSetA2dpSinkConnectionState(BluetoothDevice btDevice, int state, int a2dpVolume)5937     private void onSetA2dpSinkConnectionState(BluetoothDevice btDevice, int state, int a2dpVolume)
5938     {
5939         if (DEBUG_DEVICES) {
5940             Log.d(TAG, "onSetA2dpSinkConnectionState btDevice= " + btDevice+" state= " + state
5941                 + " is dock: "+btDevice.isBluetoothDock());
5942         }
5943         if (btDevice == null) {
5944             return;
5945         }
5946         String address = btDevice.getAddress();
5947         if (!BluetoothAdapter.checkBluetoothAddress(address)) {
5948             address = "";
5949         }
5950 
5951         synchronized (mConnectedDevices) {
5952             final String key = makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
5953                                                  btDevice.getAddress());
5954             final DeviceListSpec deviceSpec = mConnectedDevices.get(key);
5955             boolean isConnected = deviceSpec != null;
5956 
5957             if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
5958                 if (btDevice.isBluetoothDock()) {
5959                     if (state == BluetoothProfile.STATE_DISCONNECTED) {
5960                         // introduction of a delay for transient disconnections of docks when
5961                         // power is rapidly turned off/on, this message will be canceled if
5962                         // we reconnect the dock under a preset delay
5963                         makeA2dpDeviceUnavailableLater(address, BTA2DP_DOCK_TIMEOUT_MILLIS);
5964                         // the next time isConnected is evaluated, it will be false for the dock
5965                     }
5966                 } else {
5967                     makeA2dpDeviceUnavailableNow(address);
5968                 }
5969                 setCurrentAudioRouteName(null);
5970             } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
5971                 if (btDevice.isBluetoothDock()) {
5972                     // this could be a reconnection after a transient disconnection
5973                     cancelA2dpDeviceTimeout();
5974                     mDockAddress = address;
5975                 } else {
5976                     // this could be a connection of another A2DP device before the timeout of
5977                     // a dock: cancel the dock timeout, and make the dock unavailable now
5978                     if (hasScheduledA2dpDockTimeout() && mDockAddress != null) {
5979                         cancelA2dpDeviceTimeout();
5980                         makeA2dpDeviceUnavailableNow(mDockAddress);
5981                     }
5982                 }
5983                 if (a2dpVolume != -1) {
5984                     VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC];
5985                     // Convert index to internal representation in VolumeStreamState
5986                     a2dpVolume = a2dpVolume * 10;
5987                     streamState.setIndex(a2dpVolume, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
5988                             "onSetA2dpSinkConnectionState");
5989                     setDeviceVolume(streamState, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
5990                 }
5991                 makeA2dpDeviceAvailable(address, btDevice.getName(),
5992                         "onSetA2dpSinkConnectionState");
5993                 setCurrentAudioRouteName(btDevice.getAliasName());
5994             }
5995         }
5996     }
5997 
onSetA2dpSourceConnectionState(BluetoothDevice btDevice, int state)5998     private void onSetA2dpSourceConnectionState(BluetoothDevice btDevice, int state)
5999     {
6000         if (DEBUG_VOL) {
6001             Log.d(TAG, "onSetA2dpSourceConnectionState btDevice=" + btDevice + " state=" + state);
6002         }
6003         if (btDevice == null) {
6004             return;
6005         }
6006         String address = btDevice.getAddress();
6007         if (!BluetoothAdapter.checkBluetoothAddress(address)) {
6008             address = "";
6009         }
6010 
6011         synchronized (mConnectedDevices) {
6012             final String key = makeDeviceListKey(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, address);
6013             final DeviceListSpec deviceSpec = mConnectedDevices.get(key);
6014             boolean isConnected = deviceSpec != null;
6015 
6016             if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
6017                 makeA2dpSrcUnavailable(address);
6018             } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
6019                 makeA2dpSrcAvailable(address);
6020             }
6021         }
6022     }
6023 
onSetHearingAidConnectionState(BluetoothDevice btDevice, int state)6024     private void onSetHearingAidConnectionState(BluetoothDevice btDevice, int state)
6025     {
6026         if (DEBUG_DEVICES) {
6027             Log.d(TAG, "onSetHearingAidConnectionState btDevice=" + btDevice+", state=" + state);
6028         }
6029         if (btDevice == null) {
6030             return;
6031         }
6032         String address = btDevice.getAddress();
6033         if (!BluetoothAdapter.checkBluetoothAddress(address)) {
6034             address = "";
6035         }
6036 
6037         synchronized (mConnectedDevices) {
6038             final String key = makeDeviceListKey(AudioSystem.DEVICE_OUT_HEARING_AID,
6039                                                  btDevice.getAddress());
6040             final DeviceListSpec deviceSpec = mConnectedDevices.get(key);
6041             boolean isConnected = deviceSpec != null;
6042 
6043             if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
6044                 makeHearingAidDeviceUnavailable(address);
6045                 setCurrentAudioRouteName(null);
6046             } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
6047                 makeHearingAidDeviceAvailable(address, btDevice.getName(),
6048                         "onSetHearingAidConnectionState");
6049                 setCurrentAudioRouteName(btDevice.getAliasName());
6050             }
6051         }
6052     }
6053 
setCurrentAudioRouteName(String name)6054     private void setCurrentAudioRouteName(String name){
6055         synchronized (mCurAudioRoutes) {
6056             if (!TextUtils.equals(mCurAudioRoutes.bluetoothName, name)) {
6057                 mCurAudioRoutes.bluetoothName = name;
6058                 sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES,
6059                         SENDMSG_NOOP, 0, 0, null, 0);
6060             }
6061         }
6062     }
6063 
onBluetoothA2dpDeviceConfigChange(BluetoothDevice btDevice)6064     private void onBluetoothA2dpDeviceConfigChange(BluetoothDevice btDevice)
6065     {
6066         if (DEBUG_DEVICES) {
6067             Log.d(TAG, "onBluetoothA2dpDeviceConfigChange btDevice=" + btDevice);
6068         }
6069         if (btDevice == null) {
6070             return;
6071         }
6072         String address = btDevice.getAddress();
6073         if (!BluetoothAdapter.checkBluetoothAddress(address)) {
6074             address = "";
6075         }
6076 
6077         int device = AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP;
6078         synchronized (mConnectedDevices) {
6079             if (mAudioHandler.hasMessages(MSG_SET_A2DP_SINK_CONNECTION_STATE, btDevice)) {
6080                 return;
6081             }
6082             final String key = makeDeviceListKey(device, address);
6083             final DeviceListSpec deviceSpec = mConnectedDevices.get(key);
6084             if (deviceSpec != null) {
6085                 // Device is connected
6086                int musicDevice = getDeviceForStream(AudioSystem.STREAM_MUSIC);
6087                if (AudioSystem.handleDeviceConfigChange(device, address,
6088                         btDevice.getName()) != AudioSystem.AUDIO_STATUS_OK) {
6089                    // force A2DP device disconnection in case of error so that AudioService state is
6090                    // consistent with audio policy manager state
6091                    setBluetoothA2dpDeviceConnectionStateInt(
6092                            btDevice, BluetoothA2dp.STATE_DISCONNECTED, BluetoothProfile.A2DP,
6093                            false /* suppressNoisyIntent */, musicDevice, -1 /* a2dpVolume */);
6094                }
6095             }
6096         }
6097     }
6098 
avrcpSupportsAbsoluteVolume(String address, boolean support)6099     public void avrcpSupportsAbsoluteVolume(String address, boolean support) {
6100         // address is not used for now, but may be used when multiple a2dp devices are supported
6101         synchronized (mA2dpAvrcpLock) {
6102             mAvrcpAbsVolSupported = support;
6103             sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE,
6104                     AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0,
6105                     mStreamStates[AudioSystem.STREAM_MUSIC], 0);
6106         }
6107     }
6108 
handleDeviceConnection(boolean connect, int device, String address, String deviceName)6109     private boolean handleDeviceConnection(boolean connect, int device, String address,
6110             String deviceName) {
6111         if (DEBUG_DEVICES) {
6112             Slog.i(TAG, "handleDeviceConnection(" + connect + " dev:" + Integer.toHexString(device)
6113                     + " address:" + address + " name:" + deviceName + ")");
6114         }
6115         synchronized (mConnectedDevices) {
6116             String deviceKey = makeDeviceListKey(device, address);
6117             if (DEBUG_DEVICES) {
6118                 Slog.i(TAG, "deviceKey:" + deviceKey);
6119             }
6120             DeviceListSpec deviceSpec = mConnectedDevices.get(deviceKey);
6121             boolean isConnected = deviceSpec != null;
6122             if (DEBUG_DEVICES) {
6123                 Slog.i(TAG, "deviceSpec:" + deviceSpec + " is(already)Connected:" + isConnected);
6124             }
6125             if (connect && !isConnected) {
6126                 final int res = AudioSystem.setDeviceConnectionState(device,
6127                         AudioSystem.DEVICE_STATE_AVAILABLE, address, deviceName);
6128                 if (res != AudioSystem.AUDIO_STATUS_OK) {
6129                     Slog.e(TAG, "not connecting device 0x" + Integer.toHexString(device) +
6130                             " due to command error " + res );
6131                     return false;
6132                 }
6133                 mConnectedDevices.put(deviceKey, new DeviceListSpec(device, deviceName, address));
6134                 sendMsg(mAudioHandler, MSG_ACCESSORY_PLUG_MEDIA_UNMUTE, SENDMSG_QUEUE,
6135                         device, 0, null, 0);
6136                 return true;
6137             } else if (!connect && isConnected) {
6138                 AudioSystem.setDeviceConnectionState(device,
6139                         AudioSystem.DEVICE_STATE_UNAVAILABLE, address, deviceName);
6140                 // always remove even if disconnection failed
6141                 mConnectedDevices.remove(deviceKey);
6142                 return true;
6143             }
6144             Log.w(TAG, "handleDeviceConnection() failed, deviceKey=" + deviceKey + ", deviceSpec="
6145                        + deviceSpec + ", connect=" + connect);
6146         }
6147         return false;
6148     }
6149 
6150     // Devices which removal triggers intent ACTION_AUDIO_BECOMING_NOISY. The intent is only
6151     // sent if:
6152     // - none of these devices are connected anymore after one is disconnected AND
6153     // - the device being disconnected is actually used for music.
6154     // Access synchronized on mConnectedDevices
6155     int mBecomingNoisyIntentDevices =
6156             AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE |
6157             AudioSystem.DEVICE_OUT_ALL_A2DP | AudioSystem.DEVICE_OUT_HDMI |
6158             AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET | AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET |
6159             AudioSystem.DEVICE_OUT_ALL_USB | AudioSystem.DEVICE_OUT_LINE |
6160             AudioSystem.DEVICE_OUT_HEARING_AID;
6161 
6162     // must be called before removing the device from mConnectedDevices
6163     // Called synchronized on mConnectedDevices
6164     // musicDevice argument is used when not AudioSystem.DEVICE_NONE instead of querying
6165     // from AudioSystem
checkSendBecomingNoisyIntent(int device, int state, int musicDevice)6166     private int checkSendBecomingNoisyIntent(int device, int state, int musicDevice) {
6167         int delay = 0;
6168         if ((state == 0) && ((device & mBecomingNoisyIntentDevices) != 0)) {
6169             int devices = 0;
6170             for (int i = 0; i < mConnectedDevices.size(); i++) {
6171                 int dev = mConnectedDevices.valueAt(i).mDeviceType;
6172                 if (((dev & AudioSystem.DEVICE_BIT_IN) == 0)
6173                         && ((dev & mBecomingNoisyIntentDevices) != 0)) {
6174                     devices |= dev;
6175                 }
6176             }
6177             if (musicDevice == AudioSystem.DEVICE_NONE) {
6178                 musicDevice = getDeviceForStream(AudioSystem.STREAM_MUSIC);
6179             }
6180             // ignore condition on device being actually used for music when in communication
6181             // because music routing is altered in this case.
6182             // also checks whether media routing if affected by a dynamic policy
6183             if (((device == musicDevice) || isInCommunication()) && (device == devices)
6184                     && !hasMediaDynamicPolicy()) {
6185                 mAudioHandler.removeMessages(MSG_BROADCAST_AUDIO_BECOMING_NOISY);
6186                 sendMsg(mAudioHandler,
6187                         MSG_BROADCAST_AUDIO_BECOMING_NOISY,
6188                         SENDMSG_REPLACE,
6189                         0,
6190                         0,
6191                         null,
6192                         0);
6193                 delay = 1000;
6194             }
6195         }
6196 
6197         return delay;
6198     }
6199 
6200     /**
6201      * @return true if there is currently a registered dynamic mixing policy that affects media
6202      */
hasMediaDynamicPolicy()6203     private boolean hasMediaDynamicPolicy() {
6204         synchronized (mAudioPolicies) {
6205             if (mAudioPolicies.isEmpty()) {
6206                 return false;
6207             }
6208             final Collection<AudioPolicyProxy> appColl = mAudioPolicies.values();
6209             for (AudioPolicyProxy app : appColl) {
6210                 if (app.hasMixAffectingUsage(AudioAttributes.USAGE_MEDIA)) {
6211                     return true;
6212                 }
6213             }
6214             return false;
6215         }
6216     }
6217 
updateAudioRoutes(int device, int state)6218     private void updateAudioRoutes(int device, int state)
6219     {
6220         int connType = 0;
6221 
6222         if (device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) {
6223             connType = AudioRoutesInfo.MAIN_HEADSET;
6224         } else if (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE ||
6225                    device == AudioSystem.DEVICE_OUT_LINE) {
6226             connType = AudioRoutesInfo.MAIN_HEADPHONES;
6227         } else if (device == AudioSystem.DEVICE_OUT_HDMI ||
6228                 device == AudioSystem.DEVICE_OUT_HDMI_ARC) {
6229             connType = AudioRoutesInfo.MAIN_HDMI;
6230         } else if (device == AudioSystem.DEVICE_OUT_USB_DEVICE||
6231                 device == AudioSystem.DEVICE_OUT_USB_HEADSET) {
6232             connType = AudioRoutesInfo.MAIN_USB;
6233         }
6234 
6235         synchronized (mCurAudioRoutes) {
6236             if (connType != 0) {
6237                 int newConn = mCurAudioRoutes.mainType;
6238                 if (state != 0) {
6239                     newConn |= connType;
6240                 } else {
6241                     newConn &= ~connType;
6242                 }
6243                 if (newConn != mCurAudioRoutes.mainType) {
6244                     mCurAudioRoutes.mainType = newConn;
6245                     sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES,
6246                             SENDMSG_NOOP, 0, 0, null, 0);
6247                 }
6248             }
6249         }
6250     }
6251 
sendDeviceConnectionIntent(int device, int state, String address, String deviceName)6252     private void sendDeviceConnectionIntent(int device, int state, String address,
6253             String deviceName) {
6254         if (DEBUG_DEVICES) {
6255             Slog.i(TAG, "sendDeviceConnectionIntent(dev:0x" + Integer.toHexString(device) +
6256                     " state:0x" + Integer.toHexString(state) + " address:" + address +
6257                     " name:" + deviceName + ");");
6258         }
6259         Intent intent = new Intent();
6260 
6261         if (device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) {
6262             intent.setAction(Intent.ACTION_HEADSET_PLUG);
6263             intent.putExtra("microphone", 1);
6264         } else if (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE ||
6265                    device == AudioSystem.DEVICE_OUT_LINE) {
6266             intent.setAction(Intent.ACTION_HEADSET_PLUG);
6267             intent.putExtra("microphone",  0);
6268         } else if (device == AudioSystem.DEVICE_OUT_USB_HEADSET) {
6269             intent.setAction(Intent.ACTION_HEADSET_PLUG);
6270             intent.putExtra("microphone",
6271                     AudioSystem.getDeviceConnectionState(AudioSystem.DEVICE_IN_USB_HEADSET, "")
6272                         == AudioSystem.DEVICE_STATE_AVAILABLE ? 1 : 0);
6273         } else if (device == AudioSystem.DEVICE_IN_USB_HEADSET) {
6274             if (AudioSystem.getDeviceConnectionState(AudioSystem.DEVICE_OUT_USB_HEADSET, "")
6275                     == AudioSystem.DEVICE_STATE_AVAILABLE) {
6276                 intent.setAction(Intent.ACTION_HEADSET_PLUG);
6277                 intent.putExtra("microphone", 1);
6278             } else {
6279                 // do not send ACTION_HEADSET_PLUG when only the input side is seen as changing
6280                 return;
6281             }
6282         } else if (device == AudioSystem.DEVICE_OUT_HDMI ||
6283                 device == AudioSystem.DEVICE_OUT_HDMI_ARC) {
6284             configureHdmiPlugIntent(intent, state);
6285         }
6286 
6287         if (intent.getAction() == null) {
6288             return;
6289         }
6290 
6291         intent.putExtra(CONNECT_INTENT_KEY_STATE, state);
6292         intent.putExtra(CONNECT_INTENT_KEY_ADDRESS, address);
6293         intent.putExtra(CONNECT_INTENT_KEY_PORT_NAME, deviceName);
6294 
6295         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
6296 
6297         final long ident = Binder.clearCallingIdentity();
6298         try {
6299             ActivityManager.broadcastStickyIntent(intent, UserHandle.USER_ALL);
6300         } finally {
6301             Binder.restoreCallingIdentity(ident);
6302         }
6303     }
6304 
6305     private static final int DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG =
6306             AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE |
6307             AudioSystem.DEVICE_OUT_LINE |
6308             AudioSystem.DEVICE_OUT_ALL_USB;
6309 
onSetWiredDeviceConnectionState(int device, int state, String address, String deviceName, String caller)6310     private void onSetWiredDeviceConnectionState(int device, int state, String address,
6311             String deviceName, String caller) {
6312         if (DEBUG_DEVICES) {
6313             Slog.i(TAG, "onSetWiredDeviceConnectionState(dev:" + Integer.toHexString(device)
6314                     + " state:" + Integer.toHexString(state)
6315                     + " address:" + address
6316                     + " deviceName:" + deviceName
6317                     + " caller: " + caller + ");");
6318         }
6319 
6320         synchronized (mConnectedDevices) {
6321             if ((state == 0) && ((device & DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG) != 0)) {
6322                 setBluetoothA2dpOnInt(true, "onSetWiredDeviceConnectionState state 0");
6323             }
6324 
6325             if (!handleDeviceConnection(state == 1, device, address, deviceName)) {
6326                 // change of connection state failed, bailout
6327                 return;
6328             }
6329             if (state != 0) {
6330                 if ((device & DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG) != 0) {
6331                     setBluetoothA2dpOnInt(false, "onSetWiredDeviceConnectionState state not 0");
6332                 }
6333                 if ((device & mSafeMediaVolumeDevices) != 0) {
6334                     sendMsg(mAudioHandler,
6335                             MSG_CHECK_MUSIC_ACTIVE,
6336                             SENDMSG_REPLACE,
6337                             0,
6338                             0,
6339                             caller,
6340                             MUSIC_ACTIVE_POLL_PERIOD_MS);
6341                 }
6342                 // Television devices without CEC service apply software volume on HDMI output
6343                 if (isPlatformTelevision() && ((device & AudioSystem.DEVICE_OUT_HDMI) != 0)) {
6344                     mFixedVolumeDevices |= AudioSystem.DEVICE_OUT_HDMI;
6345                     checkAllFixedVolumeDevices();
6346                     if (mHdmiManager != null) {
6347                         synchronized (mHdmiManager) {
6348                             if (mHdmiPlaybackClient != null) {
6349                                 mHdmiCecSink = false;
6350                                 mHdmiPlaybackClient.queryDisplayStatus(mHdmiDisplayStatusCallback);
6351                             }
6352                         }
6353                     }
6354                 }
6355                 if ((device & AudioSystem.DEVICE_OUT_HDMI) != 0) {
6356                     sendEnabledSurroundFormats(mContentResolver, true);
6357                 }
6358             } else {
6359                 if (isPlatformTelevision() && ((device & AudioSystem.DEVICE_OUT_HDMI) != 0)) {
6360                     if (mHdmiManager != null) {
6361                         synchronized (mHdmiManager) {
6362                             mHdmiCecSink = false;
6363                         }
6364                     }
6365                 }
6366             }
6367             sendDeviceConnectionIntent(device, state, address, deviceName);
6368             updateAudioRoutes(device, state);
6369         }
6370     }
6371 
configureHdmiPlugIntent(Intent intent, int state)6372     private void configureHdmiPlugIntent(Intent intent, int state) {
6373         intent.setAction(AudioManager.ACTION_HDMI_AUDIO_PLUG);
6374         intent.putExtra(AudioManager.EXTRA_AUDIO_PLUG_STATE, state);
6375         if (state == 1) {
6376             ArrayList<AudioPort> ports = new ArrayList<AudioPort>();
6377             int[] portGeneration = new int[1];
6378             int status = AudioSystem.listAudioPorts(ports, portGeneration);
6379             if (status == AudioManager.SUCCESS) {
6380                 for (AudioPort port : ports) {
6381                     if (port instanceof AudioDevicePort) {
6382                         final AudioDevicePort devicePort = (AudioDevicePort) port;
6383                         if (devicePort.type() == AudioManager.DEVICE_OUT_HDMI ||
6384                                 devicePort.type() == AudioManager.DEVICE_OUT_HDMI_ARC) {
6385                             // format the list of supported encodings
6386                             int[] formats = AudioFormat.filterPublicFormats(devicePort.formats());
6387                             if (formats.length > 0) {
6388                                 ArrayList<Integer> encodingList = new ArrayList(1);
6389                                 for (int format : formats) {
6390                                     // a format in the list can be 0, skip it
6391                                     if (format != AudioFormat.ENCODING_INVALID) {
6392                                         encodingList.add(format);
6393                                     }
6394                                 }
6395                                 int[] encodingArray = new int[encodingList.size()];
6396                                 for (int i = 0 ; i < encodingArray.length ; i++) {
6397                                     encodingArray[i] = encodingList.get(i);
6398                                 }
6399                                 intent.putExtra(AudioManager.EXTRA_ENCODINGS, encodingArray);
6400                             }
6401                             // find the maximum supported number of channels
6402                             int maxChannels = 0;
6403                             for (int mask : devicePort.channelMasks()) {
6404                                 int channelCount = AudioFormat.channelCountFromOutChannelMask(mask);
6405                                 if (channelCount > maxChannels) {
6406                                     maxChannels = channelCount;
6407                                 }
6408                             }
6409                             intent.putExtra(AudioManager.EXTRA_MAX_CHANNEL_COUNT, maxChannels);
6410                         }
6411                     }
6412                 }
6413             }
6414         }
6415     }
6416 
6417     /* cache of the address of the last dock the device was connected to */
6418     private String mDockAddress;
6419 
6420     /**
6421      * Receiver for misc intent broadcasts the Phone app cares about.
6422      */
6423     private class AudioServiceBroadcastReceiver extends BroadcastReceiver {
6424         @Override
onReceive(Context context, Intent intent)6425         public void onReceive(Context context, Intent intent) {
6426             String action = intent.getAction();
6427             int outDevice;
6428             int inDevice;
6429             int state;
6430 
6431             if (action.equals(Intent.ACTION_DOCK_EVENT)) {
6432                 int dockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
6433                         Intent.EXTRA_DOCK_STATE_UNDOCKED);
6434                 int config;
6435                 switch (dockState) {
6436                     case Intent.EXTRA_DOCK_STATE_DESK:
6437                         config = AudioSystem.FORCE_BT_DESK_DOCK;
6438                         break;
6439                     case Intent.EXTRA_DOCK_STATE_CAR:
6440                         config = AudioSystem.FORCE_BT_CAR_DOCK;
6441                         break;
6442                     case Intent.EXTRA_DOCK_STATE_LE_DESK:
6443                         config = AudioSystem.FORCE_ANALOG_DOCK;
6444                         break;
6445                     case Intent.EXTRA_DOCK_STATE_HE_DESK:
6446                         config = AudioSystem.FORCE_DIGITAL_DOCK;
6447                         break;
6448                     case Intent.EXTRA_DOCK_STATE_UNDOCKED:
6449                     default:
6450                         config = AudioSystem.FORCE_NONE;
6451                 }
6452                 // Low end docks have a menu to enable or disable audio
6453                 // (see mDockAudioMediaEnabled)
6454                 if (!((dockState == Intent.EXTRA_DOCK_STATE_LE_DESK) ||
6455                       ((dockState == Intent.EXTRA_DOCK_STATE_UNDOCKED) &&
6456                        (mDockState == Intent.EXTRA_DOCK_STATE_LE_DESK)))) {
6457                     mForceUseLogger.log(new ForceUseEvent(AudioSystem.FOR_DOCK, config,
6458                             "ACTION_DOCK_EVENT intent"));
6459                     AudioSystem.setForceUse(AudioSystem.FOR_DOCK, config);
6460                 }
6461                 mDockState = dockState;
6462             } else if (action.equals(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED)) {
6463                 BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
6464                 setBtScoActiveDevice(btDevice);
6465             } else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
6466                 boolean broadcast = false;
6467                 int scoAudioState = AudioManager.SCO_AUDIO_STATE_ERROR;
6468                 synchronized (mScoClients) {
6469                     int btState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
6470                     // broadcast intent if the connection was initated by AudioService
6471                     if (!mScoClients.isEmpty() &&
6472                             (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL ||
6473                              mScoAudioState == SCO_STATE_ACTIVATE_REQ ||
6474                              mScoAudioState == SCO_STATE_DEACTIVATE_REQ ||
6475                              mScoAudioState == SCO_STATE_DEACTIVATING)) {
6476                         broadcast = true;
6477                     }
6478                     switch (btState) {
6479                         case BluetoothHeadset.STATE_AUDIO_CONNECTED:
6480                             scoAudioState = AudioManager.SCO_AUDIO_STATE_CONNECTED;
6481                             if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL &&
6482                                 mScoAudioState != SCO_STATE_DEACTIVATE_REQ) {
6483                                 mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL;
6484                             }
6485                             setBluetoothScoOn(true);
6486                             break;
6487                         case BluetoothHeadset.STATE_AUDIO_DISCONNECTED:
6488                             setBluetoothScoOn(false);
6489                             scoAudioState = AudioManager.SCO_AUDIO_STATE_DISCONNECTED;
6490                             // startBluetoothSco called after stopBluetoothSco
6491                             if (mScoAudioState == SCO_STATE_ACTIVATE_REQ) {
6492                                 if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null
6493                                         && connectBluetoothScoAudioHelper(mBluetoothHeadset,
6494                                         mBluetoothHeadsetDevice, mScoAudioMode)) {
6495                                     mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
6496                                     broadcast = false;
6497                                     break;
6498                                 }
6499                             }
6500                             // Tear down SCO if disconnected from external
6501                             clearAllScoClients(0, mScoAudioState == SCO_STATE_ACTIVE_INTERNAL);
6502                             mScoAudioState = SCO_STATE_INACTIVE;
6503                             break;
6504                         case BluetoothHeadset.STATE_AUDIO_CONNECTING:
6505                             if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL &&
6506                                 mScoAudioState != SCO_STATE_DEACTIVATE_REQ) {
6507                                 mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL;
6508                             }
6509                         default:
6510                             // do not broadcast CONNECTING or invalid state
6511                             broadcast = false;
6512                             break;
6513                     }
6514                 }
6515                 if (broadcast) {
6516                     broadcastScoConnectionState(scoAudioState);
6517                     //FIXME: this is to maintain compatibility with deprecated intent
6518                     // AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. Remove when appropriate.
6519                     Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED);
6520                     newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, scoAudioState);
6521                     sendStickyBroadcastToAll(newIntent);
6522                 }
6523             } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
6524                 if (mMonitorRotation) {
6525                     RotationHelper.enable();
6526                 }
6527                 AudioSystem.setParameters("screen_state=on");
6528             } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
6529                 if (mMonitorRotation) {
6530                     //reduce wakeups (save current) by only listening when display is on
6531                     RotationHelper.disable();
6532                 }
6533                 AudioSystem.setParameters("screen_state=off");
6534             } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
6535                 handleConfigurationChanged(context);
6536             } else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
6537                 if (mUserSwitchedReceived) {
6538                     // attempt to stop music playback for background user except on first user
6539                     // switch (i.e. first boot)
6540                     sendMsg(mAudioHandler,
6541                             MSG_BROADCAST_AUDIO_BECOMING_NOISY,
6542                             SENDMSG_REPLACE,
6543                             0,
6544                             0,
6545                             null,
6546                             0);
6547                 }
6548                 mUserSwitchedReceived = true;
6549                 // the current audio focus owner is no longer valid
6550                 mMediaFocusControl.discardAudioFocusOwner();
6551 
6552                 // load volume settings for new user
6553                 readAudioSettings(true /*userSwitch*/);
6554                 // preserve STREAM_MUSIC volume from one user to the next.
6555                 sendMsg(mAudioHandler,
6556                         MSG_SET_ALL_VOLUMES,
6557                         SENDMSG_QUEUE,
6558                         0,
6559                         0,
6560                         mStreamStates[AudioSystem.STREAM_MUSIC], 0);
6561             } else if (action.equals(Intent.ACTION_USER_BACKGROUND)) {
6562                 // Disable audio recording for the background user/profile
6563                 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
6564                 if (userId >= 0) {
6565                     // TODO Kill recording streams instead of killing processes holding permission
6566                     UserInfo userInfo = UserManagerService.getInstance().getUserInfo(userId);
6567                     killBackgroundUserProcessesWithRecordAudioPermission(userInfo);
6568                 }
6569                 UserManagerService.getInstance().setUserRestriction(
6570                         UserManager.DISALLOW_RECORD_AUDIO, true, userId);
6571             } else if (action.equals(Intent.ACTION_USER_FOREGROUND)) {
6572                 // Enable audio recording for foreground user/profile
6573                 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
6574                 UserManagerService.getInstance().setUserRestriction(
6575                         UserManager.DISALLOW_RECORD_AUDIO, false, userId);
6576             } else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
6577                 state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
6578                 if (state == BluetoothAdapter.STATE_OFF ||
6579                         state == BluetoothAdapter.STATE_TURNING_OFF) {
6580                     disconnectAllBluetoothProfiles();
6581                 }
6582             } else if (action.equals(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION) ||
6583                     action.equals(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION)) {
6584                 handleAudioEffectBroadcast(context, intent);
6585             }
6586         }
6587     } // end class AudioServiceBroadcastReceiver
6588 
6589     private class AudioServiceUserRestrictionsListener implements UserRestrictionsListener {
6590 
6591         @Override
onUserRestrictionsChanged(int userId, Bundle newRestrictions, Bundle prevRestrictions)6592         public void onUserRestrictionsChanged(int userId, Bundle newRestrictions,
6593                 Bundle prevRestrictions) {
6594             // Update mic mute state.
6595             {
6596                 final boolean wasRestricted =
6597                         prevRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_MICROPHONE);
6598                 final boolean isRestricted =
6599                         newRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_MICROPHONE);
6600                 if (wasRestricted != isRestricted) {
6601                     setMicrophoneMuteNoCallerCheck(isRestricted, userId);
6602                 }
6603             }
6604 
6605             // Update speaker mute state.
6606             {
6607                 final boolean wasRestricted =
6608                         prevRestrictions.getBoolean(UserManager.DISALLOW_ADJUST_VOLUME)
6609                                 || prevRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_DEVICE);
6610                 final boolean isRestricted =
6611                         newRestrictions.getBoolean(UserManager.DISALLOW_ADJUST_VOLUME)
6612                                 || newRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_DEVICE);
6613                 if (wasRestricted != isRestricted) {
6614                     setMasterMuteInternalNoCallerCheck(isRestricted, /* flags =*/ 0, userId);
6615                 }
6616             }
6617         }
6618     } // end class AudioServiceUserRestrictionsListener
6619 
handleAudioEffectBroadcast(Context context, Intent intent)6620     private void handleAudioEffectBroadcast(Context context, Intent intent) {
6621         String target = intent.getPackage();
6622         if (target != null) {
6623             Log.w(TAG, "effect broadcast already targeted to " + target);
6624             return;
6625         }
6626         intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
6627         // TODO this should target a user-selected panel
6628         List<ResolveInfo> ril = context.getPackageManager().queryBroadcastReceivers(
6629                 intent, 0 /* flags */);
6630         if (ril != null && ril.size() != 0) {
6631             ResolveInfo ri = ril.get(0);
6632             if (ri != null && ri.activityInfo != null && ri.activityInfo.packageName != null) {
6633                 intent.setPackage(ri.activityInfo.packageName);
6634                 context.sendBroadcastAsUser(intent, UserHandle.ALL);
6635                 return;
6636             }
6637         }
6638         Log.w(TAG, "couldn't find receiver package for effect intent");
6639     }
6640 
killBackgroundUserProcessesWithRecordAudioPermission(UserInfo oldUser)6641     private void killBackgroundUserProcessesWithRecordAudioPermission(UserInfo oldUser) {
6642         PackageManager pm = mContext.getPackageManager();
6643         // Find the home activity of the user. It should not be killed to avoid expensive restart,
6644         // when the user switches back. For managed profiles, we should kill all recording apps
6645         ComponentName homeActivityName = null;
6646         if (!oldUser.isManagedProfile()) {
6647             homeActivityName = mActivityManagerInternal.getHomeActivityForUser(oldUser.id);
6648         }
6649         final String[] permissions = { Manifest.permission.RECORD_AUDIO };
6650         List<PackageInfo> packages;
6651         try {
6652             packages = AppGlobals.getPackageManager()
6653                     .getPackagesHoldingPermissions(permissions, 0, oldUser.id).getList();
6654         } catch (RemoteException e) {
6655             throw new AndroidRuntimeException(e);
6656         }
6657         for (int j = packages.size() - 1; j >= 0; j--) {
6658             PackageInfo pkg = packages.get(j);
6659             // Skip system processes
6660             if (UserHandle.getAppId(pkg.applicationInfo.uid) < FIRST_APPLICATION_UID) {
6661                 continue;
6662             }
6663             // Skip packages that have permission to interact across users
6664             if (pm.checkPermission(Manifest.permission.INTERACT_ACROSS_USERS, pkg.packageName)
6665                     == PackageManager.PERMISSION_GRANTED) {
6666                 continue;
6667             }
6668             if (homeActivityName != null
6669                     && pkg.packageName.equals(homeActivityName.getPackageName())
6670                     && pkg.applicationInfo.isSystemApp()) {
6671                 continue;
6672             }
6673             try {
6674                 final int uid = pkg.applicationInfo.uid;
6675                 ActivityManager.getService().killUid(UserHandle.getAppId(uid),
6676                         UserHandle.getUserId(uid),
6677                         "killBackgroundUserProcessesWithAudioRecordPermission");
6678             } catch (RemoteException e) {
6679                 Log.w(TAG, "Error calling killUid", e);
6680             }
6681         }
6682     }
6683 
6684 
6685     //==========================================================================================
6686     // Audio Focus
6687     //==========================================================================================
6688     /**
6689      * Returns whether a focus request is eligible to force ducking.
6690      * Will return true if:
6691      * - the AudioAttributes have a usage of USAGE_ASSISTANCE_ACCESSIBILITY,
6692      * - the focus request is AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK,
6693      * - the associated Bundle has KEY_ACCESSIBILITY_FORCE_FOCUS_DUCKING set to true,
6694      * - the uid of the requester is a known accessibility service or root.
6695      * @param aa AudioAttributes of the focus request
6696      * @param uid uid of the focus requester
6697      * @return true if ducking is to be forced
6698      */
forceFocusDuckingForAccessibility(@ullable AudioAttributes aa, int request, int uid)6699     private boolean forceFocusDuckingForAccessibility(@Nullable AudioAttributes aa,
6700             int request, int uid) {
6701         if (aa == null || aa.getUsage() != AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY
6702                 || request != AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK) {
6703             return false;
6704         }
6705         final Bundle extraInfo = aa.getBundle();
6706         if (extraInfo == null ||
6707                 !extraInfo.getBoolean(AudioFocusRequest.KEY_ACCESSIBILITY_FORCE_FOCUS_DUCKING)) {
6708             return false;
6709         }
6710         if (uid == 0) {
6711             return true;
6712         }
6713         synchronized (mAccessibilityServiceUidsLock) {
6714             if (mAccessibilityServiceUids != null) {
6715                 int callingUid = Binder.getCallingUid();
6716                 for (int i = 0; i < mAccessibilityServiceUids.length; i++) {
6717                     if (mAccessibilityServiceUids[i] == callingUid) {
6718                         return true;
6719                     }
6720                 }
6721             }
6722         }
6723         return false;
6724     }
6725 
requestAudioFocus(AudioAttributes aa, int durationHint, IBinder cb, IAudioFocusDispatcher fd, String clientId, String callingPackageName, int flags, IAudioPolicyCallback pcb, int sdk)6726     public int requestAudioFocus(AudioAttributes aa, int durationHint, IBinder cb,
6727             IAudioFocusDispatcher fd, String clientId, String callingPackageName, int flags,
6728             IAudioPolicyCallback pcb, int sdk) {
6729         // permission checks
6730         if ((flags & AudioManager.AUDIOFOCUS_FLAG_LOCK) == AudioManager.AUDIOFOCUS_FLAG_LOCK) {
6731             if (AudioSystem.IN_VOICE_COMM_FOCUS_ID.equals(clientId)) {
6732                 if (PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission(
6733                             android.Manifest.permission.MODIFY_PHONE_STATE)) {
6734                     Log.e(TAG, "Invalid permission to (un)lock audio focus", new Exception());
6735                     return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
6736                 }
6737             } else {
6738                 // only a registered audio policy can be used to lock focus
6739                 synchronized (mAudioPolicies) {
6740                     if (!mAudioPolicies.containsKey(pcb.asBinder())) {
6741                         Log.e(TAG, "Invalid unregistered AudioPolicy to (un)lock audio focus");
6742                         return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
6743                     }
6744                 }
6745             }
6746         }
6747 
6748         return mMediaFocusControl.requestAudioFocus(aa, durationHint, cb, fd,
6749                 clientId, callingPackageName, flags, sdk,
6750                 forceFocusDuckingForAccessibility(aa, durationHint, Binder.getCallingUid()));
6751     }
6752 
abandonAudioFocus(IAudioFocusDispatcher fd, String clientId, AudioAttributes aa, String callingPackageName)6753     public int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId, AudioAttributes aa,
6754             String callingPackageName) {
6755         return mMediaFocusControl.abandonAudioFocus(fd, clientId, aa, callingPackageName);
6756     }
6757 
unregisterAudioFocusClient(String clientId)6758     public void unregisterAudioFocusClient(String clientId) {
6759         mMediaFocusControl.unregisterAudioFocusClient(clientId);
6760     }
6761 
getCurrentAudioFocus()6762     public int getCurrentAudioFocus() {
6763         return mMediaFocusControl.getCurrentAudioFocus();
6764     }
6765 
getFocusRampTimeMs(int focusGain, AudioAttributes attr)6766     public int getFocusRampTimeMs(int focusGain, AudioAttributes attr) {
6767         return mMediaFocusControl.getFocusRampTimeMs(focusGain, attr);
6768     }
6769 
6770     //==========================================================================================
readCameraSoundForced()6771     private boolean readCameraSoundForced() {
6772         return SystemProperties.getBoolean("audio.camerasound.force", false) ||
6773                 mContext.getResources().getBoolean(
6774                         com.android.internal.R.bool.config_camera_sound_forced);
6775     }
6776 
6777     //==========================================================================================
6778     // Device orientation
6779     //==========================================================================================
6780     /**
6781      * Handles device configuration changes that may map to a change in rotation.
6782      * Monitoring rotation is optional, and is defined by the definition and value
6783      * of the "ro.audio.monitorRotation" system property.
6784      */
handleConfigurationChanged(Context context)6785     private void handleConfigurationChanged(Context context) {
6786         try {
6787             // reading new configuration "safely" (i.e. under try catch) in case anything
6788             // goes wrong.
6789             Configuration config = context.getResources().getConfiguration();
6790             sendMsg(mAudioHandler,
6791                     MSG_CONFIGURE_SAFE_MEDIA_VOLUME,
6792                     SENDMSG_REPLACE,
6793                     0,
6794                     0,
6795                     TAG,
6796                     0);
6797 
6798             boolean cameraSoundForced = readCameraSoundForced();
6799             synchronized (mSettingsLock) {
6800                 final boolean cameraSoundForcedChanged = (cameraSoundForced != mCameraSoundForced);
6801                 mCameraSoundForced = cameraSoundForced;
6802                 if (cameraSoundForcedChanged) {
6803                     if (!mIsSingleVolume) {
6804                         synchronized (VolumeStreamState.class) {
6805                             VolumeStreamState s = mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED];
6806                             if (cameraSoundForced) {
6807                                 s.setAllIndexesToMax();
6808                                 mRingerModeAffectedStreams &=
6809                                         ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
6810                             } else {
6811                                 s.setAllIndexes(mStreamStates[AudioSystem.STREAM_SYSTEM], TAG);
6812                                 mRingerModeAffectedStreams |=
6813                                         (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
6814                             }
6815                         }
6816                         // take new state into account for streams muted by ringer mode
6817                         setRingerModeInt(getRingerModeInternal(), false);
6818                     }
6819 
6820                     sendMsg(mAudioHandler,
6821                             MSG_SET_FORCE_USE,
6822                             SENDMSG_QUEUE,
6823                             AudioSystem.FOR_SYSTEM,
6824                             cameraSoundForced ?
6825                                     AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE,
6826                             new String("handleConfigurationChanged"),
6827                             0);
6828 
6829                     sendMsg(mAudioHandler,
6830                             MSG_SET_ALL_VOLUMES,
6831                             SENDMSG_QUEUE,
6832                             0,
6833                             0,
6834                             mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED], 0);
6835                 }
6836             }
6837             mVolumeController.setLayoutDirection(config.getLayoutDirection());
6838         } catch (Exception e) {
6839             Log.e(TAG, "Error handling configuration change: ", e);
6840         }
6841     }
6842 
6843     // Handles request to override default use of A2DP for media.
6844     // Must be called synchronized on mConnectedDevices
setBluetoothA2dpOnInt(boolean on, String eventSource)6845     public void setBluetoothA2dpOnInt(boolean on, String eventSource) {
6846         synchronized (mBluetoothA2dpEnabledLock) {
6847             mBluetoothA2dpEnabled = on;
6848             mAudioHandler.removeMessages(MSG_SET_FORCE_BT_A2DP_USE);
6849             setForceUseInt_SyncDevices(AudioSystem.FOR_MEDIA,
6850                     mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP,
6851                             eventSource);
6852         }
6853     }
6854 
6855     // Must be called synchronized on mConnectedDevices
setForceUseInt_SyncDevices(int usage, int config, String eventSource)6856     private void setForceUseInt_SyncDevices(int usage, int config, String eventSource) {
6857         if (usage == AudioSystem.FOR_MEDIA) {
6858             sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES,
6859                     SENDMSG_NOOP, 0, 0, null, 0);
6860         }
6861         mForceUseLogger.log(new ForceUseEvent(usage, config, eventSource));
6862         AudioSystem.setForceUse(usage, config);
6863     }
6864 
6865     @Override
setRingtonePlayer(IRingtonePlayer player)6866     public void setRingtonePlayer(IRingtonePlayer player) {
6867         mContext.enforceCallingOrSelfPermission(REMOTE_AUDIO_PLAYBACK, null);
6868         mRingtonePlayer = player;
6869     }
6870 
6871     @Override
getRingtonePlayer()6872     public IRingtonePlayer getRingtonePlayer() {
6873         return mRingtonePlayer;
6874     }
6875 
6876     @Override
startWatchingRoutes(IAudioRoutesObserver observer)6877     public AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) {
6878         synchronized (mCurAudioRoutes) {
6879             AudioRoutesInfo routes = new AudioRoutesInfo(mCurAudioRoutes);
6880             mRoutesObservers.register(observer);
6881             return routes;
6882         }
6883     }
6884 
6885 
6886     //==========================================================================================
6887     // Safe media volume management.
6888     // MUSIC stream volume level is limited when headphones are connected according to safety
6889     // regulation. When the user attempts to raise the volume above the limit, a warning is
6890     // displayed and the user has to acknowlegde before the volume is actually changed.
6891     // The volume index corresponding to the limit is stored in config_safe_media_volume_index
6892     // property. Platforms with a different limit must set this property accordingly in their
6893     // overlay.
6894     //==========================================================================================
6895 
6896     // mSafeMediaVolumeState indicates whether the media volume is limited over headphones.
6897     // It is SAFE_MEDIA_VOLUME_NOT_CONFIGURED at boot time until a network service is connected
6898     // or the configure time is elapsed. It is then set to SAFE_MEDIA_VOLUME_ACTIVE or
6899     // SAFE_MEDIA_VOLUME_DISABLED according to country option. If not SAFE_MEDIA_VOLUME_DISABLED, it
6900     // can be set to SAFE_MEDIA_VOLUME_INACTIVE by calling AudioService.disableSafeMediaVolume()
6901     // (when user opts out).
6902     private static final int SAFE_MEDIA_VOLUME_NOT_CONFIGURED = 0;
6903     private static final int SAFE_MEDIA_VOLUME_DISABLED = 1;
6904     private static final int SAFE_MEDIA_VOLUME_INACTIVE = 2;  // confirmed
6905     private static final int SAFE_MEDIA_VOLUME_ACTIVE = 3;  // unconfirmed
6906     private Integer mSafeMediaVolumeState;
6907 
6908     private int mMcc = 0;
6909     // mSafeMediaVolumeIndex is the cached value of config_safe_media_volume_index property
6910     private int mSafeMediaVolumeIndex;
6911     // mSafeUsbMediaVolumeDbfs is the cached value of the config_safe_media_volume_usb_mB
6912     // property, divided by 100.0.
6913     private float mSafeUsbMediaVolumeDbfs;
6914     // mSafeUsbMediaVolumeIndex is used for USB Headsets and is the music volume UI index
6915     // corresponding to a gain of mSafeUsbMediaVolumeDbfs (defaulting to -37dB) in audio
6916     // flinger mixer.
6917     // We remove -22 dBs from the theoretical -15dB to account for the EQ + bass boost
6918     // amplification when both effects are on with all band gains at maximum.
6919     // This level corresponds to a loudness of 85 dB SPL for the warning to be displayed when
6920     // the headset is compliant to EN 60950 with a max loudness of 100dB SPL.
6921     private int mSafeUsbMediaVolumeIndex;
6922     // mSafeMediaVolumeDevices lists the devices for which safe media volume is enforced,
6923     private final int mSafeMediaVolumeDevices = AudioSystem.DEVICE_OUT_WIRED_HEADSET |
6924                                                 AudioSystem.DEVICE_OUT_WIRED_HEADPHONE |
6925                                                 AudioSystem.DEVICE_OUT_USB_HEADSET;
6926     // mMusicActiveMs is the cumulative time of music activity since safe volume was disabled.
6927     // When this time reaches UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX, the safe media volume is re-enabled
6928     // automatically. mMusicActiveMs is rounded to a multiple of MUSIC_ACTIVE_POLL_PERIOD_MS.
6929     private int mMusicActiveMs;
6930     private static final int UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX = (20 * 3600 * 1000); // 20 hours
6931     private static final int MUSIC_ACTIVE_POLL_PERIOD_MS = 60000;  // 1 minute polling interval
6932     private static final int SAFE_VOLUME_CONFIGURE_TIMEOUT_MS = 30000;  // 30s after boot completed
6933 
safeMediaVolumeIndex(int device)6934     private int safeMediaVolumeIndex(int device) {
6935         if ((device & mSafeMediaVolumeDevices) == 0) {
6936             return MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
6937         }
6938         if (device == AudioSystem.DEVICE_OUT_USB_HEADSET) {
6939             return mSafeUsbMediaVolumeIndex;
6940         } else {
6941             return mSafeMediaVolumeIndex;
6942         }
6943     }
6944 
setSafeMediaVolumeEnabled(boolean on, String caller)6945     private void setSafeMediaVolumeEnabled(boolean on, String caller) {
6946         synchronized (mSafeMediaVolumeState) {
6947             if ((mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_NOT_CONFIGURED) &&
6948                     (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_DISABLED)) {
6949                 if (on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE)) {
6950                     mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE;
6951                     enforceSafeMediaVolume(caller);
6952                 } else if (!on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE)) {
6953                     mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE;
6954                     mMusicActiveMs = 1;  // nonzero = confirmed
6955                     saveMusicActiveMs();
6956                     sendMsg(mAudioHandler,
6957                             MSG_CHECK_MUSIC_ACTIVE,
6958                             SENDMSG_REPLACE,
6959                             0,
6960                             0,
6961                             caller,
6962                             MUSIC_ACTIVE_POLL_PERIOD_MS);
6963                 }
6964             }
6965         }
6966     }
6967 
enforceSafeMediaVolume(String caller)6968     private void enforceSafeMediaVolume(String caller) {
6969         VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC];
6970         int devices = mSafeMediaVolumeDevices;
6971         int i = 0;
6972 
6973         while (devices != 0) {
6974             int device = 1 << i++;
6975             if ((device & devices) == 0) {
6976                 continue;
6977             }
6978             int index = streamState.getIndex(device);
6979             if (index > safeMediaVolumeIndex(device)) {
6980                 streamState.setIndex(safeMediaVolumeIndex(device), device, caller);
6981                 sendMsg(mAudioHandler,
6982                         MSG_SET_DEVICE_VOLUME,
6983                         SENDMSG_QUEUE,
6984                         device,
6985                         0,
6986                         streamState,
6987                         0);
6988             }
6989             devices &= ~device;
6990         }
6991     }
6992 
checkSafeMediaVolume(int streamType, int index, int device)6993     private boolean checkSafeMediaVolume(int streamType, int index, int device) {
6994         synchronized (mSafeMediaVolumeState) {
6995             if ((mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) &&
6996                     (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
6997                     ((device & mSafeMediaVolumeDevices) != 0) &&
6998                     (index > safeMediaVolumeIndex(device))) {
6999                 return false;
7000             }
7001             return true;
7002         }
7003     }
7004 
7005     @Override
disableSafeMediaVolume(String callingPackage)7006     public void disableSafeMediaVolume(String callingPackage) {
7007         enforceVolumeController("disable the safe media volume");
7008         synchronized (mSafeMediaVolumeState) {
7009             setSafeMediaVolumeEnabled(false, callingPackage);
7010             if (mPendingVolumeCommand != null) {
7011                 onSetStreamVolume(mPendingVolumeCommand.mStreamType,
7012                                   mPendingVolumeCommand.mIndex,
7013                                   mPendingVolumeCommand.mFlags,
7014                                   mPendingVolumeCommand.mDevice,
7015                                   callingPackage);
7016                 mPendingVolumeCommand = null;
7017             }
7018         }
7019     }
7020 
7021     //==========================================================================================
7022     // Hdmi Cec system audio mode.
7023     // If Hdmi Cec's system audio mode is on, audio service should send the volume change
7024     // to HdmiControlService so that the audio receiver can handle it.
7025     //==========================================================================================
7026 
7027     private class MyDisplayStatusCallback implements HdmiPlaybackClient.DisplayStatusCallback {
onComplete(int status)7028         public void onComplete(int status) {
7029             if (mHdmiManager != null) {
7030                 synchronized (mHdmiManager) {
7031                     mHdmiCecSink = (status != HdmiControlManager.POWER_STATUS_UNKNOWN);
7032                     // Television devices without CEC service apply software volume on HDMI output
7033                     if (isPlatformTelevision() && !mHdmiCecSink) {
7034                         mFixedVolumeDevices &= ~AudioSystem.DEVICE_OUT_HDMI;
7035                     }
7036                     checkAllFixedVolumeDevices();
7037                 }
7038             }
7039         }
7040     };
7041 
7042     // If HDMI-CEC system audio is supported
7043     private boolean mHdmiSystemAudioSupported = false;
7044     // Set only when device is tv.
7045     private HdmiTvClient mHdmiTvClient;
7046     // true if the device has system feature PackageManager.FEATURE_LEANBACK.
7047     // cached HdmiControlManager interface
7048     private HdmiControlManager mHdmiManager;
7049     // Set only when device is a set-top box.
7050     private HdmiPlaybackClient mHdmiPlaybackClient;
7051     // true if we are a set-top box, an HDMI sink is connected and it supports CEC.
7052     private boolean mHdmiCecSink;
7053 
7054     private MyDisplayStatusCallback mHdmiDisplayStatusCallback = new MyDisplayStatusCallback();
7055 
7056     @Override
setHdmiSystemAudioSupported(boolean on)7057     public int setHdmiSystemAudioSupported(boolean on) {
7058         int device = AudioSystem.DEVICE_NONE;
7059         if (mHdmiManager != null) {
7060             synchronized (mHdmiManager) {
7061                 if (mHdmiTvClient == null) {
7062                     Log.w(TAG, "Only Hdmi-Cec enabled TV device supports system audio mode.");
7063                     return device;
7064                 }
7065 
7066                 synchronized (mHdmiTvClient) {
7067                     if (mHdmiSystemAudioSupported != on) {
7068                         mHdmiSystemAudioSupported = on;
7069                         final int config = on ? AudioSystem.FORCE_HDMI_SYSTEM_AUDIO_ENFORCED :
7070                             AudioSystem.FORCE_NONE;
7071                         mForceUseLogger.log(new ForceUseEvent(AudioSystem.FOR_HDMI_SYSTEM_AUDIO,
7072                                 config, "setHdmiSystemAudioSupported"));
7073                         AudioSystem.setForceUse(AudioSystem.FOR_HDMI_SYSTEM_AUDIO, config);
7074                     }
7075                     device = getDevicesForStream(AudioSystem.STREAM_MUSIC);
7076                 }
7077             }
7078         }
7079         return device;
7080     }
7081 
7082     @Override
isHdmiSystemAudioSupported()7083     public boolean isHdmiSystemAudioSupported() {
7084         return mHdmiSystemAudioSupported;
7085     }
7086 
7087     //==========================================================================================
7088     // Accessibility
7089 
initA11yMonitoring()7090     private void initA11yMonitoring() {
7091         final AccessibilityManager accessibilityManager =
7092                 (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
7093         updateDefaultStreamOverrideDelay(accessibilityManager.isTouchExplorationEnabled());
7094         updateA11yVolumeAlias(accessibilityManager.isAccessibilityVolumeStreamActive());
7095         accessibilityManager.addTouchExplorationStateChangeListener(this, null);
7096         accessibilityManager.addAccessibilityServicesStateChangeListener(this, null);
7097     }
7098 
7099     //---------------------------------------------------------------------------------
7100     // A11y: taking touch exploration into account for selecting the default
7101     //   stream override timeout when adjusting volume
7102     //---------------------------------------------------------------------------------
7103 
7104     // - STREAM_NOTIFICATION on tablets during this period after a notification stopped
7105     // - STREAM_RING on phones during this period after a notification stopped
7106     // - STREAM_MUSIC otherwise
7107 
7108     private static final int DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS = 0;
7109     private static final int TOUCH_EXPLORE_STREAM_TYPE_OVERRIDE_DELAY_MS = 1000;
7110 
7111     private static int sStreamOverrideDelayMs;
7112 
7113     @Override
onTouchExplorationStateChanged(boolean enabled)7114     public void onTouchExplorationStateChanged(boolean enabled) {
7115         updateDefaultStreamOverrideDelay(enabled);
7116     }
7117 
updateDefaultStreamOverrideDelay(boolean touchExploreEnabled)7118     private void updateDefaultStreamOverrideDelay(boolean touchExploreEnabled) {
7119         if (touchExploreEnabled) {
7120             sStreamOverrideDelayMs = TOUCH_EXPLORE_STREAM_TYPE_OVERRIDE_DELAY_MS;
7121         } else {
7122             sStreamOverrideDelayMs = DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS;
7123         }
7124         if (DEBUG_VOL) Log.d(TAG, "Touch exploration enabled=" + touchExploreEnabled
7125                 + " stream override delay is now " + sStreamOverrideDelayMs + " ms");
7126     }
7127 
7128     //---------------------------------------------------------------------------------
7129     // A11y: taking a11y state into account for the handling of a11y prompts volume
7130     //---------------------------------------------------------------------------------
7131 
7132     private static boolean sIndependentA11yVolume = false;
7133 
7134     // implementation of AccessibilityServicesStateChangeListener
7135     @Override
onAccessibilityServicesStateChanged(AccessibilityManager accessibilityManager)7136     public void onAccessibilityServicesStateChanged(AccessibilityManager accessibilityManager) {
7137         updateA11yVolumeAlias(accessibilityManager.isAccessibilityVolumeStreamActive());
7138     }
7139 
updateA11yVolumeAlias(boolean a11VolEnabled)7140     private void updateA11yVolumeAlias(boolean a11VolEnabled) {
7141         if (DEBUG_VOL) Log.d(TAG, "Accessibility volume enabled = " + a11VolEnabled);
7142         if (sIndependentA11yVolume != a11VolEnabled) {
7143             sIndependentA11yVolume = a11VolEnabled;
7144             // update the volume mapping scheme
7145             updateStreamVolumeAlias(true /*updateVolumes*/, TAG);
7146             // update the volume controller behavior
7147             mVolumeController.setA11yMode(sIndependentA11yVolume ?
7148                     VolumePolicy.A11Y_MODE_INDEPENDENT_A11Y_VOLUME :
7149                         VolumePolicy.A11Y_MODE_MEDIA_A11Y_VOLUME);
7150             mVolumeController.postVolumeChanged(AudioManager.STREAM_ACCESSIBILITY, 0);
7151         }
7152     }
7153 
7154     //==========================================================================================
7155     // Camera shutter sound policy.
7156     // config_camera_sound_forced configuration option in config.xml defines if the camera shutter
7157     // sound is forced (sound even if the device is in silent mode) or not. This option is false by
7158     // default and can be overridden by country specific overlay in values-mccXXX/config.xml.
7159     //==========================================================================================
7160 
7161     // cached value of com.android.internal.R.bool.config_camera_sound_forced
7162     @GuardedBy("mSettingsLock")
7163     private boolean mCameraSoundForced;
7164 
7165     // called by android.hardware.Camera to populate CameraInfo.canDisableShutterSound
isCameraSoundForced()7166     public boolean isCameraSoundForced() {
7167         synchronized (mSettingsLock) {
7168             return mCameraSoundForced;
7169         }
7170     }
7171 
7172     //==========================================================================================
7173     // AudioService logging and dumpsys
7174     //==========================================================================================
7175     final int LOG_NB_EVENTS_PHONE_STATE = 20;
7176     final int LOG_NB_EVENTS_WIRED_DEV_CONNECTION = 30;
7177     final int LOG_NB_EVENTS_FORCE_USE = 20;
7178     final int LOG_NB_EVENTS_VOLUME = 40;
7179     final int LOG_NB_EVENTS_DYN_POLICY = 10;
7180 
7181     final private AudioEventLogger mModeLogger = new AudioEventLogger(LOG_NB_EVENTS_PHONE_STATE,
7182             "phone state (logged after successfull call to AudioSystem.setPhoneState(int))");
7183 
7184     final private AudioEventLogger mWiredDevLogger = new AudioEventLogger(
7185             LOG_NB_EVENTS_WIRED_DEV_CONNECTION,
7186             "wired device connection (logged before onSetWiredDeviceConnectionState() is executed)"
7187             );
7188 
7189     final private AudioEventLogger mForceUseLogger = new AudioEventLogger(
7190             LOG_NB_EVENTS_FORCE_USE,
7191             "force use (logged before setForceUse() is executed)");
7192 
7193     final private AudioEventLogger mVolumeLogger = new AudioEventLogger(LOG_NB_EVENTS_VOLUME,
7194             "volume changes (logged when command received by AudioService)");
7195 
7196     final private AudioEventLogger mDynPolicyLogger = new AudioEventLogger(LOG_NB_EVENTS_DYN_POLICY,
7197             "dynamic policy events (logged when command received by AudioService)");
7198 
7199     private static final String[] RINGER_MODE_NAMES = new String[] {
7200             "SILENT",
7201             "VIBRATE",
7202             "NORMAL"
7203     };
7204 
dumpRingerMode(PrintWriter pw)7205     private void dumpRingerMode(PrintWriter pw) {
7206         pw.println("\nRinger mode: ");
7207         pw.println("- mode (internal) = " + RINGER_MODE_NAMES[mRingerMode]);
7208         pw.println("- mode (external) = " + RINGER_MODE_NAMES[mRingerModeExternal]);
7209         dumpRingerModeStreams(pw, "affected", mRingerModeAffectedStreams);
7210         dumpRingerModeStreams(pw, "muted", mRingerAndZenModeMutedStreams);
7211         pw.print("- delegate = "); pw.println(mRingerModeDelegate);
7212     }
7213 
dumpRingerModeStreams(PrintWriter pw, String type, int streams)7214     private void dumpRingerModeStreams(PrintWriter pw, String type, int streams) {
7215         pw.print("- ringer mode "); pw.print(type); pw.print(" streams = 0x");
7216         pw.print(Integer.toHexString(streams));
7217         if (streams != 0) {
7218             pw.print(" (");
7219             boolean first = true;
7220             for (int i = 0; i < AudioSystem.STREAM_NAMES.length; i++) {
7221                 final int stream = (1 << i);
7222                 if ((streams & stream) != 0) {
7223                     if (!first) pw.print(',');
7224                     pw.print(AudioSystem.STREAM_NAMES[i]);
7225                     streams &= ~stream;
7226                     first = false;
7227                 }
7228             }
7229             if (streams != 0) {
7230                 if (!first) pw.print(',');
7231                 pw.print(streams);
7232             }
7233             pw.print(')');
7234         }
7235         pw.println();
7236     }
7237 
7238     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)7239     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
7240         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
7241 
7242         mMediaFocusControl.dump(pw);
7243         dumpStreamStates(pw);
7244         dumpRingerMode(pw);
7245         pw.println("\nAudio routes:");
7246         pw.print("  mMainType=0x"); pw.println(Integer.toHexString(mCurAudioRoutes.mainType));
7247         pw.print("  mBluetoothName="); pw.println(mCurAudioRoutes.bluetoothName);
7248 
7249         pw.println("\nOther state:");
7250         pw.print("  mVolumeController="); pw.println(mVolumeController);
7251         pw.print("  mSafeMediaVolumeState=");
7252         pw.println(safeMediaVolumeStateToString(mSafeMediaVolumeState));
7253         pw.print("  mSafeMediaVolumeIndex="); pw.println(mSafeMediaVolumeIndex);
7254         pw.print("  mSafeUsbMediaVolumeIndex="); pw.println(mSafeUsbMediaVolumeIndex);
7255         pw.print("  mSafeUsbMediaVolumeDbfs="); pw.println(mSafeUsbMediaVolumeDbfs);
7256         pw.print("  sIndependentA11yVolume="); pw.println(sIndependentA11yVolume);
7257         pw.print("  mPendingVolumeCommand="); pw.println(mPendingVolumeCommand);
7258         pw.print("  mMusicActiveMs="); pw.println(mMusicActiveMs);
7259         pw.print("  mMcc="); pw.println(mMcc);
7260         pw.print("  mCameraSoundForced="); pw.println(mCameraSoundForced);
7261         pw.print("  mHasVibrator="); pw.println(mHasVibrator);
7262         pw.print("  mVolumePolicy="); pw.println(mVolumePolicy);
7263         pw.print("  mAvrcpAbsVolSupported="); pw.println(mAvrcpAbsVolSupported);
7264 
7265         dumpAudioPolicies(pw);
7266         mDynPolicyLogger.dump(pw);
7267 
7268         mPlaybackMonitor.dump(pw);
7269 
7270         mRecordMonitor.dump(pw);
7271 
7272         pw.println("\n");
7273         pw.println("\nEvent logs:");
7274         mModeLogger.dump(pw);
7275         pw.println("\n");
7276         mWiredDevLogger.dump(pw);
7277         pw.println("\n");
7278         mForceUseLogger.dump(pw);
7279         pw.println("\n");
7280         mVolumeLogger.dump(pw);
7281     }
7282 
safeMediaVolumeStateToString(Integer state)7283     private static String safeMediaVolumeStateToString(Integer state) {
7284         switch(state) {
7285             case SAFE_MEDIA_VOLUME_NOT_CONFIGURED: return "SAFE_MEDIA_VOLUME_NOT_CONFIGURED";
7286             case SAFE_MEDIA_VOLUME_DISABLED: return "SAFE_MEDIA_VOLUME_DISABLED";
7287             case SAFE_MEDIA_VOLUME_INACTIVE: return "SAFE_MEDIA_VOLUME_INACTIVE";
7288             case SAFE_MEDIA_VOLUME_ACTIVE: return "SAFE_MEDIA_VOLUME_ACTIVE";
7289         }
7290         return null;
7291     }
7292 
7293     // Inform AudioFlinger of our device's low RAM attribute
readAndSetLowRamDevice()7294     private static void readAndSetLowRamDevice()
7295     {
7296         boolean isLowRamDevice = ActivityManager.isLowRamDeviceStatic();
7297         long totalMemory = 1024 * 1024 * 1024; // 1GB is the default if ActivityManager fails.
7298 
7299         try {
7300             final ActivityManager.MemoryInfo info = new ActivityManager.MemoryInfo();
7301             ActivityManager.getService().getMemoryInfo(info);
7302             totalMemory = info.totalMem;
7303         } catch (RemoteException e) {
7304             Log.w(TAG, "Cannot obtain MemoryInfo from ActivityManager, assume low memory device");
7305             isLowRamDevice = true;
7306         }
7307 
7308         final int status = AudioSystem.setLowRamDevice(isLowRamDevice, totalMemory);
7309         if (status != 0) {
7310             Log.w(TAG, "AudioFlinger informed of device's low RAM attribute; status " + status);
7311         }
7312     }
7313 
enforceVolumeController(String action)7314     private void enforceVolumeController(String action) {
7315         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE,
7316                 "Only SystemUI can " + action);
7317     }
7318 
7319     @Override
setVolumeController(final IVolumeController controller)7320     public void setVolumeController(final IVolumeController controller) {
7321         enforceVolumeController("set the volume controller");
7322 
7323         // return early if things are not actually changing
7324         if (mVolumeController.isSameBinder(controller)) {
7325             return;
7326         }
7327 
7328         // dismiss the old volume controller
7329         mVolumeController.postDismiss();
7330         if (controller != null) {
7331             // we are about to register a new controller, listen for its death
7332             try {
7333                 controller.asBinder().linkToDeath(new DeathRecipient() {
7334                     @Override
7335                     public void binderDied() {
7336                         if (mVolumeController.isSameBinder(controller)) {
7337                             Log.w(TAG, "Current remote volume controller died, unregistering");
7338                             setVolumeController(null);
7339                         }
7340                     }
7341                 }, 0);
7342             } catch (RemoteException e) {
7343                 // noop
7344             }
7345         }
7346         mVolumeController.setController(controller);
7347         if (DEBUG_VOL) Log.d(TAG, "Volume controller: " + mVolumeController);
7348     }
7349 
7350     @Override
notifyVolumeControllerVisible(final IVolumeController controller, boolean visible)7351     public void notifyVolumeControllerVisible(final IVolumeController controller, boolean visible) {
7352         enforceVolumeController("notify about volume controller visibility");
7353 
7354         // return early if the controller is not current
7355         if (!mVolumeController.isSameBinder(controller)) {
7356             return;
7357         }
7358 
7359         mVolumeController.setVisible(visible);
7360         if (DEBUG_VOL) Log.d(TAG, "Volume controller visible: " + visible);
7361     }
7362 
7363     @Override
setVolumePolicy(VolumePolicy policy)7364     public void setVolumePolicy(VolumePolicy policy) {
7365         enforceVolumeController("set volume policy");
7366         if (policy != null && !policy.equals(mVolumePolicy)) {
7367             mVolumePolicy = policy;
7368             if (DEBUG_VOL) Log.d(TAG, "Volume policy changed: " + mVolumePolicy);
7369         }
7370     }
7371 
7372     public static class VolumeController {
7373         private static final String TAG = "VolumeController";
7374 
7375         private IVolumeController mController;
7376         private boolean mVisible;
7377         private long mNextLongPress;
7378         private int mLongPressTimeout;
7379 
setController(IVolumeController controller)7380         public void setController(IVolumeController controller) {
7381             mController = controller;
7382             mVisible = false;
7383         }
7384 
loadSettings(ContentResolver cr)7385         public void loadSettings(ContentResolver cr) {
7386             mLongPressTimeout = Settings.Secure.getIntForUser(cr,
7387                     Settings.Secure.LONG_PRESS_TIMEOUT, 500, UserHandle.USER_CURRENT);
7388         }
7389 
suppressAdjustment(int resolvedStream, int flags, boolean isMute)7390         public boolean suppressAdjustment(int resolvedStream, int flags, boolean isMute) {
7391             if (isMute) {
7392                 return false;
7393             }
7394             boolean suppress = false;
7395             if (resolvedStream == DEFAULT_VOL_STREAM_NO_PLAYBACK && mController != null) {
7396                 final long now = SystemClock.uptimeMillis();
7397                 if ((flags & AudioManager.FLAG_SHOW_UI) != 0 && !mVisible) {
7398                     // ui will become visible
7399                     if (mNextLongPress < now) {
7400                         mNextLongPress = now + mLongPressTimeout;
7401                     }
7402                     suppress = true;
7403                 } else if (mNextLongPress > 0) {  // in a long-press
7404                     if (now > mNextLongPress) {
7405                         // long press triggered, no more suppression
7406                         mNextLongPress = 0;
7407                     } else {
7408                         // keep suppressing until the long press triggers
7409                         suppress = true;
7410                     }
7411                 }
7412             }
7413             return suppress;
7414         }
7415 
setVisible(boolean visible)7416         public void setVisible(boolean visible) {
7417             mVisible = visible;
7418         }
7419 
isSameBinder(IVolumeController controller)7420         public boolean isSameBinder(IVolumeController controller) {
7421             return Objects.equals(asBinder(), binder(controller));
7422         }
7423 
asBinder()7424         public IBinder asBinder() {
7425             return binder(mController);
7426         }
7427 
binder(IVolumeController controller)7428         private static IBinder binder(IVolumeController controller) {
7429             return controller == null ? null : controller.asBinder();
7430         }
7431 
7432         @Override
toString()7433         public String toString() {
7434             return "VolumeController(" + asBinder() + ",mVisible=" + mVisible + ")";
7435         }
7436 
postDisplaySafeVolumeWarning(int flags)7437         public void postDisplaySafeVolumeWarning(int flags) {
7438             if (mController == null)
7439                 return;
7440             try {
7441                 mController.displaySafeVolumeWarning(flags);
7442             } catch (RemoteException e) {
7443                 Log.w(TAG, "Error calling displaySafeVolumeWarning", e);
7444             }
7445         }
7446 
postVolumeChanged(int streamType, int flags)7447         public void postVolumeChanged(int streamType, int flags) {
7448             if (mController == null)
7449                 return;
7450             try {
7451                 mController.volumeChanged(streamType, flags);
7452             } catch (RemoteException e) {
7453                 Log.w(TAG, "Error calling volumeChanged", e);
7454             }
7455         }
7456 
postMasterMuteChanged(int flags)7457         public void postMasterMuteChanged(int flags) {
7458             if (mController == null)
7459                 return;
7460             try {
7461                 mController.masterMuteChanged(flags);
7462             } catch (RemoteException e) {
7463                 Log.w(TAG, "Error calling masterMuteChanged", e);
7464             }
7465         }
7466 
setLayoutDirection(int layoutDirection)7467         public void setLayoutDirection(int layoutDirection) {
7468             if (mController == null)
7469                 return;
7470             try {
7471                 mController.setLayoutDirection(layoutDirection);
7472             } catch (RemoteException e) {
7473                 Log.w(TAG, "Error calling setLayoutDirection", e);
7474             }
7475         }
7476 
postDismiss()7477         public void postDismiss() {
7478             if (mController == null)
7479                 return;
7480             try {
7481                 mController.dismiss();
7482             } catch (RemoteException e) {
7483                 Log.w(TAG, "Error calling dismiss", e);
7484             }
7485         }
7486 
setA11yMode(int a11yMode)7487         public void setA11yMode(int a11yMode) {
7488             if (mController == null)
7489                 return;
7490             try {
7491                 mController.setA11yMode(a11yMode);
7492             } catch (RemoteException e) {
7493                 Log.w(TAG, "Error calling setA11Mode", e);
7494             }
7495         }
7496     }
7497 
7498     /**
7499      * Interface for system components to get some extra functionality through
7500      * LocalServices.
7501      */
7502     final class AudioServiceInternal extends AudioManagerInternal {
7503         @Override
setRingerModeDelegate(RingerModeDelegate delegate)7504         public void setRingerModeDelegate(RingerModeDelegate delegate) {
7505             mRingerModeDelegate = delegate;
7506             if (mRingerModeDelegate != null) {
7507                 synchronized (mSettingsLock) {
7508                     updateRingerAndZenModeAffectedStreams();
7509                 }
7510                 setRingerModeInternal(getRingerModeInternal(), TAG + ".setRingerModeDelegate");
7511             }
7512         }
7513 
7514         @Override
adjustSuggestedStreamVolumeForUid(int streamType, int direction, int flags, String callingPackage, int uid)7515         public void adjustSuggestedStreamVolumeForUid(int streamType, int direction, int flags,
7516                 String callingPackage, int uid) {
7517             // direction and stream type swap here because the public
7518             // adjustSuggested has a different order than the other methods.
7519             adjustSuggestedStreamVolume(direction, streamType, flags, callingPackage,
7520                     callingPackage, uid);
7521         }
7522 
7523         @Override
adjustStreamVolumeForUid(int streamType, int direction, int flags, String callingPackage, int uid)7524         public void adjustStreamVolumeForUid(int streamType, int direction, int flags,
7525                 String callingPackage, int uid) {
7526             adjustStreamVolume(streamType, direction, flags, callingPackage,
7527                     callingPackage, uid);
7528         }
7529 
7530         @Override
setStreamVolumeForUid(int streamType, int direction, int flags, String callingPackage, int uid)7531         public void setStreamVolumeForUid(int streamType, int direction, int flags,
7532                 String callingPackage, int uid) {
7533             setStreamVolume(streamType, direction, flags, callingPackage, callingPackage, uid);
7534         }
7535 
7536         @Override
getRingerModeInternal()7537         public int getRingerModeInternal() {
7538             return AudioService.this.getRingerModeInternal();
7539         }
7540 
7541         @Override
setRingerModeInternal(int ringerMode, String caller)7542         public void setRingerModeInternal(int ringerMode, String caller) {
7543             AudioService.this.setRingerModeInternal(ringerMode, caller);
7544         }
7545 
7546         @Override
silenceRingerModeInternal(String caller)7547         public void silenceRingerModeInternal(String caller) {
7548             AudioService.this.silenceRingerModeInternal(caller);
7549         }
7550 
7551         @Override
updateRingerModeAffectedStreamsInternal()7552         public void updateRingerModeAffectedStreamsInternal() {
7553             synchronized (mSettingsLock) {
7554                 if (updateRingerAndZenModeAffectedStreams()) {
7555                     setRingerModeInt(getRingerModeInternal(), false);
7556                 }
7557             }
7558         }
7559 
7560         @Override
setAccessibilityServiceUids(IntArray uids)7561         public void setAccessibilityServiceUids(IntArray uids) {
7562             synchronized (mAccessibilityServiceUidsLock) {
7563                 if (uids.size() == 0) {
7564                     mAccessibilityServiceUids = null;
7565                 } else {
7566                     boolean changed = (mAccessibilityServiceUids == null)
7567                             || (mAccessibilityServiceUids.length != uids.size());
7568                     if (!changed) {
7569                         for (int i = 0; i < mAccessibilityServiceUids.length; i++) {
7570                             if (uids.get(i) != mAccessibilityServiceUids[i]) {
7571                                 changed = true;
7572                                 break;
7573                             }
7574                         }
7575                     }
7576                     if (changed) {
7577                         mAccessibilityServiceUids = uids.toArray();
7578                     }
7579                 }
7580             }
7581         }
7582     }
7583 
7584     //==========================================================================================
7585     // Audio policy management
7586     //==========================================================================================
registerAudioPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb, boolean hasFocusListener, boolean isFocusPolicy, boolean isVolumeController)7587     public String registerAudioPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb,
7588             boolean hasFocusListener, boolean isFocusPolicy, boolean isVolumeController) {
7589         AudioSystem.setDynamicPolicyCallback(mDynPolicyCallback);
7590 
7591         String regId = null;
7592         // error handling
7593         boolean hasPermissionForPolicy =
7594                 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
7595                         android.Manifest.permission.MODIFY_AUDIO_ROUTING));
7596         if (!hasPermissionForPolicy) {
7597             Slog.w(TAG, "Can't register audio policy for pid " + Binder.getCallingPid() + " / uid "
7598                     + Binder.getCallingUid() + ", need MODIFY_AUDIO_ROUTING");
7599             return null;
7600         }
7601 
7602         mDynPolicyLogger.log((new AudioEventLogger.StringEvent("registerAudioPolicy for "
7603                 + pcb.asBinder() + " with config:" + policyConfig)).printLog(TAG));
7604         synchronized (mAudioPolicies) {
7605             try {
7606                 if (mAudioPolicies.containsKey(pcb.asBinder())) {
7607                     Slog.e(TAG, "Cannot re-register policy");
7608                     return null;
7609                 }
7610                 AudioPolicyProxy app = new AudioPolicyProxy(policyConfig, pcb, hasFocusListener,
7611                         isFocusPolicy, isVolumeController);
7612                 pcb.asBinder().linkToDeath(app, 0/*flags*/);
7613                 regId = app.getRegistrationId();
7614                 mAudioPolicies.put(pcb.asBinder(), app);
7615             } catch (RemoteException e) {
7616                 // audio policy owner has already died!
7617                 Slog.w(TAG, "Audio policy registration failed, could not link to " + pcb +
7618                         " binder death", e);
7619                 return null;
7620             }
7621         }
7622         return regId;
7623     }
7624 
unregisterAudioPolicyAsync(IAudioPolicyCallback pcb)7625     public void unregisterAudioPolicyAsync(IAudioPolicyCallback pcb) {
7626         mDynPolicyLogger.log((new AudioEventLogger.StringEvent("unregisterAudioPolicyAsync for "
7627                 + pcb.asBinder()).printLog(TAG)));
7628         synchronized (mAudioPolicies) {
7629             AudioPolicyProxy app = mAudioPolicies.remove(pcb.asBinder());
7630             if (app == null) {
7631                 Slog.w(TAG, "Trying to unregister unknown audio policy for pid "
7632                         + Binder.getCallingPid() + " / uid " + Binder.getCallingUid());
7633                 return;
7634             } else {
7635                 pcb.asBinder().unlinkToDeath(app, 0/*flags*/);
7636             }
7637             app.release();
7638         }
7639         // TODO implement clearing mix attribute matching info in native audio policy
7640     }
7641 
7642     /**
7643      * Checks whether caller has MODIFY_AUDIO_ROUTING permission, and the policy is registered.
7644      * @param errorMsg log warning if permission check failed.
7645      * @return null if the operation on the audio mixes should be cancelled.
7646      */
7647     @GuardedBy("mAudioPolicies")
checkUpdateForPolicy(IAudioPolicyCallback pcb, String errorMsg)7648     private AudioPolicyProxy checkUpdateForPolicy(IAudioPolicyCallback pcb, String errorMsg) {
7649         // permission check
7650         final boolean hasPermissionForPolicy =
7651                 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
7652                         android.Manifest.permission.MODIFY_AUDIO_ROUTING));
7653         if (!hasPermissionForPolicy) {
7654             Slog.w(TAG, errorMsg + " for pid " +
7655                     + Binder.getCallingPid() + " / uid "
7656                     + Binder.getCallingUid() + ", need MODIFY_AUDIO_ROUTING");
7657             return null;
7658         }
7659         // policy registered?
7660         final AudioPolicyProxy app = mAudioPolicies.get(pcb.asBinder());
7661         if (app == null) {
7662             Slog.w(TAG, errorMsg + " for pid " +
7663                     + Binder.getCallingPid() + " / uid "
7664                     + Binder.getCallingUid() + ", unregistered policy");
7665             return null;
7666         }
7667         return app;
7668     }
7669 
addMixForPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb)7670     public int addMixForPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb) {
7671         if (DEBUG_AP) { Log.d(TAG, "addMixForPolicy for " + pcb.asBinder()
7672                 + " with config:" + policyConfig); }
7673         synchronized (mAudioPolicies) {
7674             final AudioPolicyProxy app =
7675                     checkUpdateForPolicy(pcb, "Cannot add AudioMix in audio policy");
7676             if (app == null){
7677                 return AudioManager.ERROR;
7678             }
7679             app.addMixes(policyConfig.getMixes());
7680         }
7681         return AudioManager.SUCCESS;
7682     }
7683 
removeMixForPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb)7684     public int removeMixForPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb) {
7685         if (DEBUG_AP) { Log.d(TAG, "removeMixForPolicy for " + pcb.asBinder()
7686                 + " with config:" + policyConfig); }
7687         synchronized (mAudioPolicies) {
7688             final AudioPolicyProxy app =
7689                     checkUpdateForPolicy(pcb, "Cannot add AudioMix in audio policy");
7690             if (app == null) {
7691                 return AudioManager.ERROR;
7692             }
7693             app.removeMixes(policyConfig.getMixes());
7694         }
7695         return AudioManager.SUCCESS;
7696     }
7697 
setFocusPropertiesForPolicy(int duckingBehavior, IAudioPolicyCallback pcb)7698     public int setFocusPropertiesForPolicy(int duckingBehavior, IAudioPolicyCallback pcb) {
7699         if (DEBUG_AP) Log.d(TAG, "setFocusPropertiesForPolicy() duck behavior=" + duckingBehavior
7700                 + " policy " +  pcb.asBinder());
7701         synchronized (mAudioPolicies) {
7702             final AudioPolicyProxy app =
7703                     checkUpdateForPolicy(pcb, "Cannot change audio policy focus properties");
7704             if (app == null){
7705                 return AudioManager.ERROR;
7706             }
7707             if (!mAudioPolicies.containsKey(pcb.asBinder())) {
7708                 Slog.e(TAG, "Cannot change audio policy focus properties, unregistered policy");
7709                 return AudioManager.ERROR;
7710             }
7711             if (duckingBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) {
7712                 // is there already one policy managing ducking?
7713                 for (AudioPolicyProxy policy : mAudioPolicies.values()) {
7714                     if (policy.mFocusDuckBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) {
7715                         Slog.e(TAG, "Cannot change audio policy ducking behavior, already handled");
7716                         return AudioManager.ERROR;
7717                     }
7718                 }
7719             }
7720             app.mFocusDuckBehavior = duckingBehavior;
7721             mMediaFocusControl.setDuckingInExtPolicyAvailable(
7722                     duckingBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY);
7723         }
7724         return AudioManager.SUCCESS;
7725     }
7726 
7727     private final Object mExtVolumeControllerLock = new Object();
7728     private IAudioPolicyCallback mExtVolumeController;
setExtVolumeController(IAudioPolicyCallback apc)7729     private void setExtVolumeController(IAudioPolicyCallback apc) {
7730         if (!mContext.getResources().getBoolean(
7731                 com.android.internal.R.bool.config_handleVolumeKeysInWindowManager)) {
7732             Log.e(TAG, "Cannot set external volume controller: device not set for volume keys" +
7733                     " handled in PhoneWindowManager");
7734             return;
7735         }
7736         synchronized (mExtVolumeControllerLock) {
7737             if (mExtVolumeController != null && !mExtVolumeController.asBinder().pingBinder()) {
7738                 Log.e(TAG, "Cannot set external volume controller: existing controller");
7739             }
7740             mExtVolumeController = apc;
7741         }
7742     }
7743 
dumpAudioPolicies(PrintWriter pw)7744     private void dumpAudioPolicies(PrintWriter pw) {
7745         pw.println("\nAudio policies:");
7746         synchronized (mAudioPolicies) {
7747             for (AudioPolicyProxy policy : mAudioPolicies.values()) {
7748                 pw.println(policy.toLogFriendlyString());
7749             }
7750         }
7751     }
7752 
7753     //======================
7754     // Audio policy callbacks from AudioSystem for dynamic policies
7755     //======================
7756     private final AudioSystem.DynamicPolicyCallback mDynPolicyCallback =
7757             new AudioSystem.DynamicPolicyCallback() {
7758         public void onDynamicPolicyMixStateUpdate(String regId, int state) {
7759             if (!TextUtils.isEmpty(regId)) {
7760                 sendMsg(mAudioHandler, MSG_DYN_POLICY_MIX_STATE_UPDATE, SENDMSG_QUEUE,
7761                         state /*arg1*/, 0 /*arg2 ignored*/, regId /*obj*/, 0 /*delay*/);
7762             }
7763         }
7764     };
7765 
onDynPolicyMixStateUpdate(String regId, int state)7766     private void onDynPolicyMixStateUpdate(String regId, int state) {
7767         if (DEBUG_AP) Log.d(TAG, "onDynamicPolicyMixStateUpdate("+ regId + ", " + state +")");
7768         synchronized (mAudioPolicies) {
7769             for (AudioPolicyProxy policy : mAudioPolicies.values()) {
7770                 for (AudioMix mix : policy.getMixes()) {
7771                     if (mix.getRegistration().equals(regId)) {
7772                         try {
7773                             policy.mPolicyCallback.notifyMixStateUpdate(regId, state);
7774                         } catch (RemoteException e) {
7775                             Log.e(TAG, "Can't call notifyMixStateUpdate() on IAudioPolicyCallback "
7776                                     + policy.mPolicyCallback.asBinder(), e);
7777                         }
7778                         return;
7779                     }
7780                 }
7781             }
7782         }
7783     }
7784 
7785     //======================
7786     // Audio policy callbacks from AudioSystem for recording configuration updates
7787     //======================
7788     private final RecordingActivityMonitor mRecordMonitor;
7789 
registerRecordingCallback(IRecordingConfigDispatcher rcdb)7790     public void registerRecordingCallback(IRecordingConfigDispatcher rcdb) {
7791         final boolean isPrivileged =
7792                 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
7793                         android.Manifest.permission.MODIFY_AUDIO_ROUTING));
7794         mRecordMonitor.registerRecordingCallback(rcdb, isPrivileged);
7795     }
7796 
unregisterRecordingCallback(IRecordingConfigDispatcher rcdb)7797     public void unregisterRecordingCallback(IRecordingConfigDispatcher rcdb) {
7798         mRecordMonitor.unregisterRecordingCallback(rcdb);
7799     }
7800 
getActiveRecordingConfigurations()7801     public List<AudioRecordingConfiguration> getActiveRecordingConfigurations() {
7802         final boolean isPrivileged =
7803                 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
7804                         android.Manifest.permission.MODIFY_AUDIO_ROUTING));
7805         return mRecordMonitor.getActiveRecordingConfigurations(isPrivileged);
7806     }
7807 
disableRingtoneSync(final int userId)7808     public void disableRingtoneSync(final int userId) {
7809         final int callingUserId = UserHandle.getCallingUserId();
7810         if (callingUserId != userId) {
7811             mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL,
7812                     "disable sound settings syncing for another profile");
7813         }
7814         final long token = Binder.clearCallingIdentity();
7815         try {
7816             // Disable the sync setting so the profile uses its own sound settings.
7817             Settings.Secure.putIntForUser(mContentResolver, Settings.Secure.SYNC_PARENT_SOUNDS,
7818                     0 /* false */, userId);
7819         } finally {
7820             Binder.restoreCallingIdentity(token);
7821         }
7822     }
7823 
7824     //======================
7825     // Audio playback notification
7826     //======================
7827     private final PlaybackActivityMonitor mPlaybackMonitor;
7828 
registerPlaybackCallback(IPlaybackConfigDispatcher pcdb)7829     public void registerPlaybackCallback(IPlaybackConfigDispatcher pcdb) {
7830         final boolean isPrivileged =
7831                 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
7832                         android.Manifest.permission.MODIFY_AUDIO_ROUTING));
7833         mPlaybackMonitor.registerPlaybackCallback(pcdb, isPrivileged);
7834     }
7835 
unregisterPlaybackCallback(IPlaybackConfigDispatcher pcdb)7836     public void unregisterPlaybackCallback(IPlaybackConfigDispatcher pcdb) {
7837         mPlaybackMonitor.unregisterPlaybackCallback(pcdb);
7838     }
7839 
getActivePlaybackConfigurations()7840     public List<AudioPlaybackConfiguration> getActivePlaybackConfigurations() {
7841         final boolean isPrivileged =
7842                 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
7843                         android.Manifest.permission.MODIFY_AUDIO_ROUTING));
7844         return mPlaybackMonitor.getActivePlaybackConfigurations(isPrivileged);
7845     }
7846 
trackPlayer(PlayerBase.PlayerIdCard pic)7847     public int trackPlayer(PlayerBase.PlayerIdCard pic) {
7848         return mPlaybackMonitor.trackPlayer(pic);
7849     }
7850 
playerAttributes(int piid, AudioAttributes attr)7851     public void playerAttributes(int piid, AudioAttributes attr) {
7852         mPlaybackMonitor.playerAttributes(piid, attr, Binder.getCallingUid());
7853     }
7854 
playerEvent(int piid, int event)7855     public void playerEvent(int piid, int event) {
7856         mPlaybackMonitor.playerEvent(piid, event, Binder.getCallingUid());
7857     }
7858 
playerHasOpPlayAudio(int piid, boolean hasOpPlayAudio)7859     public void playerHasOpPlayAudio(int piid, boolean hasOpPlayAudio) {
7860         mPlaybackMonitor.playerHasOpPlayAudio(piid, hasOpPlayAudio, Binder.getCallingUid());
7861     }
7862 
releasePlayer(int piid)7863     public void releasePlayer(int piid) {
7864         mPlaybackMonitor.releasePlayer(piid, Binder.getCallingUid());
7865     }
7866 
7867     //======================
7868     // Audio policy proxy
7869     //======================
7870     /**
7871      * This internal class inherits from AudioPolicyConfig, each instance contains all the
7872      * mixes of an AudioPolicy and their configurations.
7873      */
7874     public class AudioPolicyProxy extends AudioPolicyConfig implements IBinder.DeathRecipient {
7875         private static final String TAG = "AudioPolicyProxy";
7876         final IAudioPolicyCallback mPolicyCallback;
7877         final boolean mHasFocusListener;
7878         final boolean mIsVolumeController;
7879         /**
7880          * Audio focus ducking behavior for an audio policy.
7881          * This variable reflects the value that was successfully set in
7882          * {@link AudioService#setFocusPropertiesForPolicy(int, IAudioPolicyCallback)}. This
7883          * implies that a value of FOCUS_POLICY_DUCKING_IN_POLICY means the corresponding policy
7884          * is handling ducking for audio focus.
7885          */
7886         int mFocusDuckBehavior = AudioPolicy.FOCUS_POLICY_DUCKING_DEFAULT;
7887         boolean mIsFocusPolicy = false;
7888 
AudioPolicyProxy(AudioPolicyConfig config, IAudioPolicyCallback token, boolean hasFocusListener, boolean isFocusPolicy, boolean isVolumeController)7889         AudioPolicyProxy(AudioPolicyConfig config, IAudioPolicyCallback token,
7890                 boolean hasFocusListener, boolean isFocusPolicy, boolean isVolumeController) {
7891             super(config);
7892             setRegistration(new String(config.hashCode() + ":ap:" + mAudioPolicyCounter++));
7893             mPolicyCallback = token;
7894             mHasFocusListener = hasFocusListener;
7895             mIsVolumeController = isVolumeController;
7896             if (mHasFocusListener) {
7897                 mMediaFocusControl.addFocusFollower(mPolicyCallback);
7898                 // can only ever be true if there is a focus listener
7899                 if (isFocusPolicy) {
7900                     mIsFocusPolicy = true;
7901                     mMediaFocusControl.setFocusPolicy(mPolicyCallback);
7902                 }
7903             }
7904             if (mIsVolumeController) {
7905                 setExtVolumeController(mPolicyCallback);
7906             }
7907             connectMixes();
7908         }
7909 
binderDied()7910         public void binderDied() {
7911             synchronized (mAudioPolicies) {
7912                 Log.i(TAG, "audio policy " + mPolicyCallback + " died");
7913                 release();
7914                 mAudioPolicies.remove(mPolicyCallback.asBinder());
7915             }
7916             if (mIsVolumeController) {
7917                 synchronized (mExtVolumeControllerLock) {
7918                     mExtVolumeController = null;
7919                 }
7920             }
7921         }
7922 
getRegistrationId()7923         String getRegistrationId() {
7924             return getRegistration();
7925         }
7926 
release()7927         void release() {
7928             if (mIsFocusPolicy) {
7929                 mMediaFocusControl.unsetFocusPolicy(mPolicyCallback);
7930             }
7931             if (mFocusDuckBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) {
7932                 mMediaFocusControl.setDuckingInExtPolicyAvailable(false);
7933             }
7934             if (mHasFocusListener) {
7935                 mMediaFocusControl.removeFocusFollower(mPolicyCallback);
7936             }
7937             final long identity = Binder.clearCallingIdentity();
7938             AudioSystem.registerPolicyMixes(mMixes, false);
7939             Binder.restoreCallingIdentity(identity);
7940         }
7941 
hasMixAffectingUsage(int usage)7942         boolean hasMixAffectingUsage(int usage) {
7943             for (AudioMix mix : mMixes) {
7944                 if (mix.isAffectingUsage(usage)) {
7945                     return true;
7946                 }
7947             }
7948             return false;
7949         }
7950 
addMixes(@onNull ArrayList<AudioMix> mixes)7951         void addMixes(@NonNull ArrayList<AudioMix> mixes) {
7952             // TODO optimize to not have to unregister the mixes already in place
7953             synchronized (mMixes) {
7954                 AudioSystem.registerPolicyMixes(mMixes, false);
7955                 this.add(mixes);
7956                 AudioSystem.registerPolicyMixes(mMixes, true);
7957             }
7958         }
7959 
removeMixes(@onNull ArrayList<AudioMix> mixes)7960         void removeMixes(@NonNull ArrayList<AudioMix> mixes) {
7961             // TODO optimize to not have to unregister the mixes already in place
7962             synchronized (mMixes) {
7963                 AudioSystem.registerPolicyMixes(mMixes, false);
7964                 this.remove(mixes);
7965                 AudioSystem.registerPolicyMixes(mMixes, true);
7966             }
7967         }
7968 
connectMixes()7969         void connectMixes() {
7970             final long identity = Binder.clearCallingIdentity();
7971             AudioSystem.registerPolicyMixes(mMixes, true);
7972             Binder.restoreCallingIdentity(identity);
7973         }
7974     };
7975 
7976     //======================
7977     // Audio policy: focus
7978     //======================
7979     /**  */
dispatchFocusChange(AudioFocusInfo afi, int focusChange, IAudioPolicyCallback pcb)7980     public int dispatchFocusChange(AudioFocusInfo afi, int focusChange, IAudioPolicyCallback pcb) {
7981         if (afi == null) {
7982             throw new IllegalArgumentException("Illegal null AudioFocusInfo");
7983         }
7984         if (pcb == null) {
7985             throw new IllegalArgumentException("Illegal null AudioPolicy callback");
7986         }
7987         synchronized (mAudioPolicies) {
7988             if (!mAudioPolicies.containsKey(pcb.asBinder())) {
7989                 throw new IllegalStateException("Unregistered AudioPolicy for focus dispatch");
7990             }
7991             return mMediaFocusControl.dispatchFocusChange(afi, focusChange);
7992         }
7993     }
7994 
setFocusRequestResultFromExtPolicy(AudioFocusInfo afi, int requestResult, IAudioPolicyCallback pcb)7995     public void setFocusRequestResultFromExtPolicy(AudioFocusInfo afi, int requestResult,
7996             IAudioPolicyCallback pcb) {
7997         if (afi == null) {
7998             throw new IllegalArgumentException("Illegal null AudioFocusInfo");
7999         }
8000         if (pcb == null) {
8001             throw new IllegalArgumentException("Illegal null AudioPolicy callback");
8002         }
8003         synchronized (mAudioPolicies) {
8004             if (!mAudioPolicies.containsKey(pcb.asBinder())) {
8005                 throw new IllegalStateException("Unregistered AudioPolicy for external focus");
8006             }
8007             mMediaFocusControl.setFocusRequestResultFromExtPolicy(afi, requestResult);
8008         }
8009     }
8010 
8011 
8012     //======================
8013     // Audioserver state displatch
8014     //======================
8015     private class AsdProxy implements IBinder.DeathRecipient {
8016         private final IAudioServerStateDispatcher mAsd;
8017 
AsdProxy(IAudioServerStateDispatcher asd)8018         AsdProxy(IAudioServerStateDispatcher asd) {
8019             mAsd = asd;
8020         }
8021 
binderDied()8022         public void binderDied() {
8023             synchronized (mAudioServerStateListeners) {
8024                 mAudioServerStateListeners.remove(mAsd.asBinder());
8025             }
8026         }
8027 
callback()8028         IAudioServerStateDispatcher callback() {
8029             return mAsd;
8030         }
8031     }
8032 
8033     private HashMap<IBinder, AsdProxy> mAudioServerStateListeners =
8034             new HashMap<IBinder, AsdProxy>();
8035 
checkMonitorAudioServerStatePermission()8036     private void checkMonitorAudioServerStatePermission() {
8037         if (!(mContext.checkCallingOrSelfPermission(
8038                     android.Manifest.permission.MODIFY_PHONE_STATE) ==
8039                 PackageManager.PERMISSION_GRANTED ||
8040               mContext.checkCallingOrSelfPermission(
8041                     android.Manifest.permission.MODIFY_AUDIO_ROUTING) ==
8042                 PackageManager.PERMISSION_GRANTED)) {
8043             throw new SecurityException("Not allowed to monitor audioserver state");
8044         }
8045     }
8046 
registerAudioServerStateDispatcher(IAudioServerStateDispatcher asd)8047     public void registerAudioServerStateDispatcher(IAudioServerStateDispatcher asd) {
8048         checkMonitorAudioServerStatePermission();
8049         synchronized (mAudioServerStateListeners) {
8050             if (mAudioServerStateListeners.containsKey(asd.asBinder())) {
8051                 Slog.w(TAG, "Cannot re-register audio server state dispatcher");
8052                 return;
8053             }
8054             AsdProxy asdp = new AsdProxy(asd);
8055             try {
8056                 asd.asBinder().linkToDeath(asdp, 0/*flags*/);
8057             } catch (RemoteException e) {
8058 
8059             }
8060             mAudioServerStateListeners.put(asd.asBinder(), asdp);
8061         }
8062     }
8063 
unregisterAudioServerStateDispatcher(IAudioServerStateDispatcher asd)8064     public void unregisterAudioServerStateDispatcher(IAudioServerStateDispatcher asd) {
8065         checkMonitorAudioServerStatePermission();
8066         synchronized (mAudioServerStateListeners) {
8067             AsdProxy asdp = mAudioServerStateListeners.remove(asd.asBinder());
8068             if (asdp == null) {
8069                 Slog.w(TAG, "Trying to unregister unknown audioserver state dispatcher for pid "
8070                         + Binder.getCallingPid() + " / uid " + Binder.getCallingUid());
8071                 return;
8072             } else {
8073                 asd.asBinder().unlinkToDeath(asdp, 0/*flags*/);
8074             }
8075         }
8076     }
8077 
isAudioServerRunning()8078     public boolean isAudioServerRunning() {
8079         checkMonitorAudioServerStatePermission();
8080         return (AudioSystem.checkAudioFlinger() == AudioSystem.AUDIO_STATUS_OK);
8081     }
8082 
8083     //======================
8084     // misc
8085     //======================
8086     private final HashMap<IBinder, AudioPolicyProxy> mAudioPolicies =
8087             new HashMap<IBinder, AudioPolicyProxy>();
8088     @GuardedBy("mAudioPolicies")
8089     private int mAudioPolicyCounter = 0;
8090 }
8091