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