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