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