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