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