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