AudioService.java revision 38edfda9bdd282228db08e3cc449b554b8744625
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        final long ident = Binder.clearCallingIdentity();
1404        try {
1405            mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
1406        } finally {
1407            Binder.restoreCallingIdentity(ident);
1408        }
1409    }
1410
1411    private void sendStickyBroadcastToAll(Intent intent) {
1412        final long ident = Binder.clearCallingIdentity();
1413        try {
1414            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
1415        } finally {
1416            Binder.restoreCallingIdentity(ident);
1417        }
1418    }
1419
1420    // UI update and Broadcast Intent
1421    private void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags) {
1422        if (!isPlatformVoice() && (streamType == AudioSystem.STREAM_RING)) {
1423            streamType = AudioSystem.STREAM_NOTIFICATION;
1424        }
1425
1426        if (streamType == AudioSystem.STREAM_MUSIC) {
1427            flags = updateFlagsForSystemAudio(flags);
1428        }
1429        mVolumeController.postVolumeChanged(streamType, flags);
1430
1431        if ((flags & AudioManager.FLAG_FIXED_VOLUME) == 0) {
1432            oldIndex = (oldIndex + 5) / 10;
1433            index = (index + 5) / 10;
1434            Intent intent = new Intent(AudioManager.VOLUME_CHANGED_ACTION);
1435            intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, streamType);
1436            intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, index);
1437            intent.putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, oldIndex);
1438            sendBroadcastToAll(intent);
1439        }
1440    }
1441
1442    // If Hdmi-CEC system audio mode is on, we show volume bar only when TV
1443    // receives volume notification from Audio Receiver.
1444    private int updateFlagsForSystemAudio(int flags) {
1445        if (mHdmiTvClient != null) {
1446            synchronized (mHdmiTvClient) {
1447                if (mHdmiSystemAudioSupported &&
1448                        ((flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) == 0)) {
1449                    flags &= ~AudioManager.FLAG_SHOW_UI;
1450                }
1451            }
1452        }
1453        return flags;
1454    }
1455
1456    // UI update and Broadcast Intent
1457    private void sendMasterVolumeUpdate(int flags, int oldVolume, int newVolume) {
1458        mVolumeController.postMasterVolumeChanged(updateFlagsForSystemAudio(flags));
1459
1460        Intent intent = new Intent(AudioManager.MASTER_VOLUME_CHANGED_ACTION);
1461        intent.putExtra(AudioManager.EXTRA_PREV_MASTER_VOLUME_VALUE, oldVolume);
1462        intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_VALUE, newVolume);
1463        sendBroadcastToAll(intent);
1464    }
1465
1466    // UI update and Broadcast Intent
1467    private void sendMasterMuteUpdate(boolean muted, int flags) {
1468        mVolumeController.postMasterMuteChanged(updateFlagsForSystemAudio(flags));
1469        broadcastMasterMuteStatus(muted);
1470    }
1471
1472    private void broadcastMasterMuteStatus(boolean muted) {
1473        Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION);
1474        intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, muted);
1475        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1476                | Intent.FLAG_RECEIVER_REPLACE_PENDING);
1477        sendStickyBroadcastToAll(intent);
1478    }
1479
1480    /**
1481     * Sets the stream state's index, and posts a message to set system volume.
1482     * This will not call out to the UI. Assumes a valid stream type.
1483     *
1484     * @param streamType Type of the stream
1485     * @param index Desired volume index of the stream
1486     * @param device the device whose volume must be changed
1487     * @param force If true, set the volume even if the desired volume is same
1488     * as the current volume.
1489     */
1490    private void setStreamVolumeInt(int streamType,
1491                                    int index,
1492                                    int device,
1493                                    boolean force) {
1494        VolumeStreamState streamState = mStreamStates[streamType];
1495
1496        if (streamState.setIndex(index, device) || force) {
1497            // Post message to set system volume (it in turn will post a message
1498            // to persist).
1499            sendMsg(mAudioHandler,
1500                    MSG_SET_DEVICE_VOLUME,
1501                    SENDMSG_QUEUE,
1502                    device,
1503                    0,
1504                    streamState,
1505                    0);
1506        }
1507    }
1508
1509    /** @see AudioManager#setStreamSolo(int, boolean) */
1510    public void setStreamSolo(int streamType, boolean state, IBinder cb) {
1511        if (mUseFixedVolume) {
1512            return;
1513        }
1514
1515        for (int stream = 0; stream < mStreamStates.length; stream++) {
1516            if (!isStreamAffectedByMute(stream) || stream == streamType) continue;
1517            mStreamStates[stream].mute(cb, state);
1518         }
1519    }
1520
1521    /** @see AudioManager#setStreamMute(int, boolean) */
1522    public void setStreamMute(int streamType, boolean state, IBinder cb) {
1523        if (mUseFixedVolume) {
1524            return;
1525        }
1526        if (streamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
1527            streamType = getActiveStreamType(streamType);
1528        }
1529
1530        if (isStreamAffectedByMute(streamType)) {
1531            if (streamType == AudioSystem.STREAM_MUSIC) {
1532                setSystemAudioMute(state);
1533            }
1534            mStreamStates[streamType].mute(cb, state);
1535
1536            Intent intent = new Intent(AudioManager.STREAM_MUTE_CHANGED_ACTION);
1537            intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, streamType);
1538            intent.putExtra(AudioManager.EXTRA_STREAM_VOLUME_MUTED, state);
1539            sendBroadcastToAll(intent);
1540        }
1541    }
1542
1543    private void setSystemAudioMute(boolean state) {
1544        if (mHdmiManager == null || mHdmiTvClient == null) return;
1545        synchronized (mHdmiManager) {
1546            if (!mHdmiSystemAudioSupported) return;
1547            synchronized (mHdmiTvClient) {
1548                final long token = Binder.clearCallingIdentity();
1549                try {
1550                    mHdmiTvClient.setSystemAudioMute(state);
1551                } finally {
1552                    Binder.restoreCallingIdentity(token);
1553                }
1554            }
1555        }
1556    }
1557
1558    /** get stream mute state. */
1559    public boolean isStreamMute(int streamType) {
1560        if (streamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
1561            streamType = getActiveStreamType(streamType);
1562        }
1563        synchronized (VolumeStreamState.class) {
1564            return mStreamStates[streamType].isMuted_syncVSS();
1565        }
1566    }
1567
1568    private class RmtSbmxFullVolDeathHandler implements IBinder.DeathRecipient {
1569        private IBinder mICallback; // To be notified of client's death
1570
1571        RmtSbmxFullVolDeathHandler(IBinder cb) {
1572            mICallback = cb;
1573            try {
1574                cb.linkToDeath(this, 0/*flags*/);
1575            } catch (RemoteException e) {
1576                Log.e(TAG, "can't link to death", e);
1577            }
1578        }
1579
1580        boolean isHandlerFor(IBinder cb) {
1581            return mICallback.equals(cb);
1582        }
1583
1584        void forget() {
1585            try {
1586                mICallback.unlinkToDeath(this, 0/*flags*/);
1587            } catch (NoSuchElementException e) {
1588                Log.e(TAG, "error unlinking to death", e);
1589            }
1590        }
1591
1592        public void binderDied() {
1593            Log.w(TAG, "Recorder with remote submix at full volume died " + mICallback);
1594            forceRemoteSubmixFullVolume(false, mICallback);
1595        }
1596    }
1597
1598    /**
1599     * call must be synchronized on mRmtSbmxFullVolDeathHandlers
1600     * @return true if there is a registered death handler, false otherwise */
1601    private boolean discardRmtSbmxFullVolDeathHandlerFor(IBinder cb) {
1602        Iterator<RmtSbmxFullVolDeathHandler> it = mRmtSbmxFullVolDeathHandlers.iterator();
1603        while (it.hasNext()) {
1604            final RmtSbmxFullVolDeathHandler handler = it.next();
1605            if (handler.isHandlerFor(cb)) {
1606                handler.forget();
1607                mRmtSbmxFullVolDeathHandlers.remove(handler);
1608                return true;
1609            }
1610        }
1611        return false;
1612    }
1613
1614    /** call synchronized on mRmtSbmxFullVolDeathHandlers */
1615    private boolean hasRmtSbmxFullVolDeathHandlerFor(IBinder cb) {
1616        Iterator<RmtSbmxFullVolDeathHandler> it = mRmtSbmxFullVolDeathHandlers.iterator();
1617        while (it.hasNext()) {
1618            if (it.next().isHandlerFor(cb)) {
1619                return true;
1620            }
1621        }
1622        return false;
1623    }
1624
1625    private int mRmtSbmxFullVolRefCount = 0;
1626    private ArrayList<RmtSbmxFullVolDeathHandler> mRmtSbmxFullVolDeathHandlers =
1627            new ArrayList<RmtSbmxFullVolDeathHandler>();
1628
1629    public void forceRemoteSubmixFullVolume(boolean startForcing, IBinder cb) {
1630        if (cb == null) {
1631            return;
1632        }
1633        if ((PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission(
1634                        android.Manifest.permission.CAPTURE_AUDIO_OUTPUT))) {
1635            Log.w(TAG, "Trying to call forceRemoteSubmixFullVolume() without CAPTURE_AUDIO_OUTPUT");
1636            return;
1637        }
1638        synchronized(mRmtSbmxFullVolDeathHandlers) {
1639            boolean applyRequired = false;
1640            if (startForcing) {
1641                if (!hasRmtSbmxFullVolDeathHandlerFor(cb)) {
1642                    mRmtSbmxFullVolDeathHandlers.add(new RmtSbmxFullVolDeathHandler(cb));
1643                    if (mRmtSbmxFullVolRefCount == 0) {
1644                        mFullVolumeDevices |= AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
1645                        mFixedVolumeDevices |= AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
1646                        applyRequired = true;
1647                    }
1648                    mRmtSbmxFullVolRefCount++;
1649                }
1650            } else {
1651                if (discardRmtSbmxFullVolDeathHandlerFor(cb) && (mRmtSbmxFullVolRefCount > 0)) {
1652                    mRmtSbmxFullVolRefCount--;
1653                    if (mRmtSbmxFullVolRefCount == 0) {
1654                        mFullVolumeDevices &= ~AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
1655                        mFixedVolumeDevices &= ~AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
1656                        applyRequired = true;
1657                    }
1658                }
1659            }
1660            if (applyRequired) {
1661                // Assumes only STREAM_MUSIC going through DEVICE_OUT_REMOTE_SUBMIX
1662                checkAllFixedVolumeDevices(AudioSystem.STREAM_MUSIC);
1663                mStreamStates[AudioSystem.STREAM_MUSIC].applyAllVolumes();
1664            }
1665        }
1666    }
1667
1668    /** @see AudioManager#setMasterMute(boolean, int) */
1669    public void setMasterMute(boolean state, int flags, String callingPackage, IBinder cb) {
1670        setMasterMuteInternal(state, flags, callingPackage, cb, Binder.getCallingUid());
1671    }
1672
1673    private void setMasterMuteInternal(boolean state, int flags, String callingPackage, IBinder cb,
1674            int uid) {
1675        if (mUseFixedVolume) {
1676            return;
1677        }
1678        if (mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, uid, callingPackage)
1679                != AppOpsManager.MODE_ALLOWED) {
1680            return;
1681        }
1682        if (state != AudioSystem.getMasterMute()) {
1683            setSystemAudioMute(state);
1684            AudioSystem.setMasterMute(state);
1685            // Post a persist master volume msg
1686            sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME_MUTE, SENDMSG_REPLACE, state ? 1
1687                    : 0, UserHandle.getCallingUserId(), null, PERSIST_DELAY);
1688            sendMasterMuteUpdate(state, flags);
1689
1690            Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION);
1691            intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, state);
1692            sendBroadcastToAll(intent);
1693        }
1694    }
1695
1696    /** get master mute state. */
1697    public boolean isMasterMute() {
1698        return AudioSystem.getMasterMute();
1699    }
1700
1701    protected static int getMaxStreamVolume(int streamType) {
1702        return MAX_STREAM_VOLUME[streamType];
1703    }
1704
1705    public static int getDefaultStreamVolume(int streamType) {
1706        return DEFAULT_STREAM_VOLUME[streamType];
1707    }
1708
1709    /** @see AudioManager#getStreamVolume(int) */
1710    public int getStreamVolume(int streamType) {
1711        ensureValidStreamType(streamType);
1712        int device = getDeviceForStream(streamType);
1713        synchronized (VolumeStreamState.class) {
1714            int index = mStreamStates[streamType].getIndex(device);
1715
1716            // by convention getStreamVolume() returns 0 when a stream is muted.
1717            if (mStreamStates[streamType].isMuted_syncVSS()) {
1718                index = 0;
1719            }
1720            if (index != 0 && (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
1721                    (device & mFixedVolumeDevices) != 0) {
1722                index = mStreamStates[streamType].getMaxIndex();
1723            }
1724            return (index + 5) / 10;
1725        }
1726    }
1727
1728    @Override
1729    public int getMasterVolume() {
1730        if (isMasterMute()) return 0;
1731        return getLastAudibleMasterVolume();
1732    }
1733
1734    @Override
1735    public void setMasterVolume(int volume, int flags, String callingPackage) {
1736        setMasterVolume(volume, flags, callingPackage, Binder.getCallingUid());
1737    }
1738
1739    public void setMasterVolume(int volume, int flags, String callingPackage, int uid) {
1740        if (mUseFixedVolume) {
1741            return;
1742        }
1743
1744        if (mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, uid, callingPackage)
1745                != AppOpsManager.MODE_ALLOWED) {
1746            return;
1747        }
1748
1749        if (volume < 0) {
1750            volume = 0;
1751        } else if (volume > MAX_MASTER_VOLUME) {
1752            volume = MAX_MASTER_VOLUME;
1753        }
1754        doSetMasterVolume((float)volume / MAX_MASTER_VOLUME, flags);
1755    }
1756
1757    private void doSetMasterVolume(float volume, int flags) {
1758        // don't allow changing master volume when muted
1759        if (!AudioSystem.getMasterMute()) {
1760            int oldVolume = getMasterVolume();
1761            AudioSystem.setMasterVolume(volume);
1762
1763            int newVolume = getMasterVolume();
1764            if (newVolume != oldVolume) {
1765                // Post a persist master volume msg
1766                sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME, SENDMSG_REPLACE,
1767                        Math.round(volume * (float)1000.0), 0, null, PERSIST_DELAY);
1768                setSystemAudioVolume(oldVolume, newVolume, getMasterMaxVolume(), flags);
1769            }
1770            // Send the volume update regardless whether there was a change.
1771            sendMasterVolumeUpdate(flags, oldVolume, newVolume);
1772        }
1773    }
1774
1775    /** @see AudioManager#getStreamMaxVolume(int) */
1776    public int getStreamMaxVolume(int streamType) {
1777        ensureValidStreamType(streamType);
1778        return (mStreamStates[streamType].getMaxIndex() + 5) / 10;
1779    }
1780
1781    public int getMasterMaxVolume() {
1782        return MAX_MASTER_VOLUME;
1783    }
1784
1785    /** Get last audible volume before stream was muted. */
1786    public int getLastAudibleStreamVolume(int streamType) {
1787        ensureValidStreamType(streamType);
1788        int device = getDeviceForStream(streamType);
1789        return (mStreamStates[streamType].getIndex(device) + 5) / 10;
1790    }
1791
1792    /** Get last audible master volume before it was muted. */
1793    public int getLastAudibleMasterVolume() {
1794        return Math.round(AudioSystem.getMasterVolume() * MAX_MASTER_VOLUME);
1795    }
1796
1797    /** @see AudioManager#getMasterStreamType()  */
1798    public int getMasterStreamType() {
1799        return mStreamVolumeAlias[AudioSystem.STREAM_SYSTEM];
1800    }
1801
1802    /** @see AudioManager#setMicrophoneMute(boolean) */
1803    public void setMicrophoneMute(boolean on, String callingPackage) {
1804        if (mAppOps.noteOp(AppOpsManager.OP_MUTE_MICROPHONE, Binder.getCallingUid(),
1805                callingPackage) != AppOpsManager.MODE_ALLOWED) {
1806            return;
1807        }
1808        if (!checkAudioSettingsPermission("setMicrophoneMute()")) {
1809            return;
1810        }
1811
1812        AudioSystem.muteMicrophone(on);
1813        // Post a persist microphone msg.
1814        sendMsg(mAudioHandler, MSG_PERSIST_MICROPHONE_MUTE, SENDMSG_REPLACE, on ? 1
1815                : 0, UserHandle.getCallingUserId(), null, PERSIST_DELAY);
1816    }
1817
1818    @Override
1819    public int getRingerModeExternal() {
1820        synchronized(mSettingsLock) {
1821            return mRingerModeExternal;
1822        }
1823    }
1824
1825    @Override
1826    public int getRingerModeInternal() {
1827        synchronized(mSettingsLock) {
1828            return mRingerMode;
1829        }
1830    }
1831
1832    private void ensureValidRingerMode(int ringerMode) {
1833        if (!isValidRingerMode(ringerMode)) {
1834            throw new IllegalArgumentException("Bad ringer mode " + ringerMode);
1835        }
1836    }
1837
1838    /** @see AudioManager#isValidRingerMode(int) */
1839    public boolean isValidRingerMode(int ringerMode) {
1840        return ringerMode >= 0 && ringerMode <= AudioManager.RINGER_MODE_MAX;
1841    }
1842
1843    public void setRingerModeExternal(int ringerMode, String caller) {
1844        final long identity = Binder.clearCallingIdentity();
1845        try {
1846            setRingerMode(ringerMode, caller, true /*external*/);
1847        } finally {
1848            Binder.restoreCallingIdentity(identity);
1849        }
1850    }
1851
1852    public void setRingerModeInternal(int ringerMode, String caller) {
1853        enforceSelfOrSystemUI("setRingerModeInternal");
1854        final long identity = Binder.clearCallingIdentity();
1855        try {
1856            setRingerMode(ringerMode, caller, false /*external*/);
1857        } finally {
1858            Binder.restoreCallingIdentity(identity);
1859        }
1860    }
1861
1862    private void setRingerMode(int ringerMode, String caller, boolean external) {
1863        if (mUseFixedVolume || isPlatformTelevision()) {
1864            return;
1865        }
1866        if (caller == null || caller.length() == 0) {
1867            throw new IllegalArgumentException("Bad caller: " + caller);
1868        }
1869        ensureValidRingerMode(ringerMode);
1870        if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) {
1871            ringerMode = AudioManager.RINGER_MODE_SILENT;
1872        }
1873        synchronized (mSettingsLock) {
1874            final int ringerModeInternal = getRingerModeInternal();
1875            final int ringerModeExternal = getRingerModeExternal();
1876            if (external) {
1877                setRingerModeExt(ringerMode);
1878                if (mRingerModeDelegate != null) {
1879                    ringerMode = mRingerModeDelegate.onSetRingerModeExternal(ringerModeExternal,
1880                            ringerMode, caller, ringerModeInternal);
1881                }
1882                if (ringerMode != ringerModeInternal) {
1883                    setRingerModeInt(ringerMode, true /*persist*/);
1884                }
1885            } else /*internal*/ {
1886                if (ringerMode != ringerModeInternal) {
1887                    setRingerModeInt(ringerMode, true /*persist*/);
1888                }
1889                if (mRingerModeDelegate != null) {
1890                    ringerMode = mRingerModeDelegate.onSetRingerModeInternal(ringerModeInternal,
1891                            ringerMode, caller, ringerModeExternal);
1892                }
1893                setRingerModeExt(ringerMode);
1894            }
1895        }
1896    }
1897
1898    private void setRingerModeExt(int ringerMode) {
1899        synchronized(mSettingsLock) {
1900            if (ringerMode == mRingerModeExternal) return;
1901            mRingerModeExternal = ringerMode;
1902        }
1903        // Send sticky broadcast
1904        broadcastRingerMode(AudioManager.RINGER_MODE_CHANGED_ACTION, ringerMode);
1905    }
1906
1907    private void setRingerModeInt(int ringerMode, boolean persist) {
1908        final boolean change;
1909        synchronized(mSettingsLock) {
1910            change = mRingerMode != ringerMode;
1911            mRingerMode = ringerMode;
1912        }
1913
1914        // Mute stream if not previously muted by ringer mode and ringer mode
1915        // is not RINGER_MODE_NORMAL and stream is affected by ringer mode.
1916        // Unmute stream if previously muted by ringer mode and ringer mode
1917        // is RINGER_MODE_NORMAL or stream is not affected by ringer mode.
1918        int numStreamTypes = AudioSystem.getNumStreamTypes();
1919        final boolean ringerModeMute = ringerMode == AudioManager.RINGER_MODE_VIBRATE
1920                || ringerMode == AudioManager.RINGER_MODE_SILENT;
1921        for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
1922            final boolean isMuted = isStreamMutedByRingerMode(streamType);
1923            final boolean shouldMute = ringerModeMute && isStreamAffectedByRingerMode(streamType);
1924            if (isMuted == shouldMute) continue;
1925            if (!shouldMute) {
1926                // unmute
1927                // ring and notifications volume should never be 0 when not silenced
1928                // on voice capable devices or devices that support vibration
1929                if ((isPlatformVoice() || mHasVibrator) &&
1930                        mStreamVolumeAlias[streamType] == AudioSystem.STREAM_RING) {
1931                    synchronized (VolumeStreamState.class) {
1932                        Set set = mStreamStates[streamType].mIndex.entrySet();
1933                        Iterator i = set.iterator();
1934                        while (i.hasNext()) {
1935                            Map.Entry entry = (Map.Entry)i.next();
1936                            if ((Integer)entry.getValue() == 0) {
1937                                entry.setValue(10);
1938                            }
1939                        }
1940                    }
1941                }
1942                mStreamStates[streamType].mute(null, false);
1943                mRingerModeMutedStreams &= ~(1 << streamType);
1944            } else {
1945                // mute
1946                mStreamStates[streamType].mute(null, true);
1947                mRingerModeMutedStreams |= (1 << streamType);
1948            }
1949        }
1950
1951        // Post a persist ringer mode msg
1952        if (persist) {
1953            sendMsg(mAudioHandler, MSG_PERSIST_RINGER_MODE,
1954                    SENDMSG_REPLACE, 0, 0, null, PERSIST_DELAY);
1955        }
1956        if (change) {
1957            // Send sticky broadcast
1958            broadcastRingerMode(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION, ringerMode);
1959        }
1960    }
1961
1962    private void restoreMasterVolume() {
1963        if (mUseFixedVolume) {
1964            AudioSystem.setMasterVolume(1.0f);
1965            return;
1966        }
1967        if (mUseMasterVolume) {
1968            float volume = Settings.System.getFloatForUser(mContentResolver,
1969                    Settings.System.VOLUME_MASTER, -1.0f, UserHandle.USER_CURRENT);
1970            if (volume >= 0.0f) {
1971                AudioSystem.setMasterVolume(volume);
1972            }
1973        }
1974    }
1975
1976    /** @see AudioManager#shouldVibrate(int) */
1977    public boolean shouldVibrate(int vibrateType) {
1978        if (!mHasVibrator) return false;
1979
1980        switch (getVibrateSetting(vibrateType)) {
1981
1982            case AudioManager.VIBRATE_SETTING_ON:
1983                return getRingerModeExternal() != AudioManager.RINGER_MODE_SILENT;
1984
1985            case AudioManager.VIBRATE_SETTING_ONLY_SILENT:
1986                return getRingerModeExternal() == AudioManager.RINGER_MODE_VIBRATE;
1987
1988            case AudioManager.VIBRATE_SETTING_OFF:
1989                // return false, even for incoming calls
1990                return false;
1991
1992            default:
1993                return false;
1994        }
1995    }
1996
1997    /** @see AudioManager#getVibrateSetting(int) */
1998    public int getVibrateSetting(int vibrateType) {
1999        if (!mHasVibrator) return AudioManager.VIBRATE_SETTING_OFF;
2000        return (mVibrateSetting >> (vibrateType * 2)) & 3;
2001    }
2002
2003    /** @see AudioManager#setVibrateSetting(int, int) */
2004    public void setVibrateSetting(int vibrateType, int vibrateSetting) {
2005
2006        if (!mHasVibrator) return;
2007
2008        mVibrateSetting = getValueForVibrateSetting(mVibrateSetting, vibrateType, vibrateSetting);
2009
2010        // Broadcast change
2011        broadcastVibrateSetting(vibrateType);
2012
2013    }
2014
2015    /**
2016     * @see #setVibrateSetting(int, int)
2017     */
2018    public static int getValueForVibrateSetting(int existingValue, int vibrateType,
2019            int vibrateSetting) {
2020
2021        // First clear the existing setting. Each vibrate type has two bits in
2022        // the value. Note '3' is '11' in binary.
2023        existingValue &= ~(3 << (vibrateType * 2));
2024
2025        // Set into the old value
2026        existingValue |= (vibrateSetting & 3) << (vibrateType * 2);
2027
2028        return existingValue;
2029    }
2030
2031    private class SetModeDeathHandler implements IBinder.DeathRecipient {
2032        private IBinder mCb; // To be notified of client's death
2033        private int mPid;
2034        private int mMode = AudioSystem.MODE_NORMAL; // Current mode set by this client
2035
2036        SetModeDeathHandler(IBinder cb, int pid) {
2037            mCb = cb;
2038            mPid = pid;
2039        }
2040
2041        public void binderDied() {
2042            int newModeOwnerPid = 0;
2043            synchronized(mSetModeDeathHandlers) {
2044                Log.w(TAG, "setMode() client died");
2045                int index = mSetModeDeathHandlers.indexOf(this);
2046                if (index < 0) {
2047                    Log.w(TAG, "unregistered setMode() client died");
2048                } else {
2049                    newModeOwnerPid = setModeInt(AudioSystem.MODE_NORMAL, mCb, mPid);
2050                }
2051            }
2052            // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
2053            // SCO connections not started by the application changing the mode
2054            if (newModeOwnerPid != 0) {
2055                final long ident = Binder.clearCallingIdentity();
2056                disconnectBluetoothSco(newModeOwnerPid);
2057                Binder.restoreCallingIdentity(ident);
2058            }
2059        }
2060
2061        public int getPid() {
2062            return mPid;
2063        }
2064
2065        public void setMode(int mode) {
2066            mMode = mode;
2067        }
2068
2069        public int getMode() {
2070            return mMode;
2071        }
2072
2073        public IBinder getBinder() {
2074            return mCb;
2075        }
2076    }
2077
2078    /** @see AudioManager#setMode(int) */
2079    public void setMode(int mode, IBinder cb) {
2080        if (DEBUG_MODE) { Log.v(TAG, "setMode(mode=" + mode + ")"); }
2081        if (!checkAudioSettingsPermission("setMode()")) {
2082            return;
2083        }
2084
2085        if ( (mode == AudioSystem.MODE_IN_CALL) &&
2086                (mContext.checkCallingOrSelfPermission(
2087                        android.Manifest.permission.MODIFY_PHONE_STATE)
2088                            != PackageManager.PERMISSION_GRANTED)) {
2089            Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: setMode(MODE_IN_CALL) from pid="
2090                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
2091            return;
2092        }
2093
2094        if (mode < AudioSystem.MODE_CURRENT || mode >= AudioSystem.NUM_MODES) {
2095            return;
2096        }
2097
2098        int newModeOwnerPid = 0;
2099        synchronized(mSetModeDeathHandlers) {
2100            if (mode == AudioSystem.MODE_CURRENT) {
2101                mode = mMode;
2102            }
2103            newModeOwnerPid = setModeInt(mode, cb, Binder.getCallingPid());
2104        }
2105        // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
2106        // SCO connections not started by the application changing the mode
2107        if (newModeOwnerPid != 0) {
2108             disconnectBluetoothSco(newModeOwnerPid);
2109        }
2110    }
2111
2112    // must be called synchronized on mSetModeDeathHandlers
2113    // setModeInt() returns a valid PID if the audio mode was successfully set to
2114    // any mode other than NORMAL.
2115    private int setModeInt(int mode, IBinder cb, int pid) {
2116        if (DEBUG_MODE) { Log.v(TAG, "setModeInt(mode=" + mode + ", pid=" + pid + ")"); }
2117        int newModeOwnerPid = 0;
2118        if (cb == null) {
2119            Log.e(TAG, "setModeInt() called with null binder");
2120            return newModeOwnerPid;
2121        }
2122
2123        SetModeDeathHandler hdlr = null;
2124        Iterator iter = mSetModeDeathHandlers.iterator();
2125        while (iter.hasNext()) {
2126            SetModeDeathHandler h = (SetModeDeathHandler)iter.next();
2127            if (h.getPid() == pid) {
2128                hdlr = h;
2129                // Remove from client list so that it is re-inserted at top of list
2130                iter.remove();
2131                hdlr.getBinder().unlinkToDeath(hdlr, 0);
2132                break;
2133            }
2134        }
2135        int status = AudioSystem.AUDIO_STATUS_OK;
2136        do {
2137            if (mode == AudioSystem.MODE_NORMAL) {
2138                // get new mode from client at top the list if any
2139                if (!mSetModeDeathHandlers.isEmpty()) {
2140                    hdlr = mSetModeDeathHandlers.get(0);
2141                    cb = hdlr.getBinder();
2142                    mode = hdlr.getMode();
2143                    if (DEBUG_MODE) {
2144                        Log.w(TAG, " using mode=" + mode + " instead due to death hdlr at pid="
2145                                + hdlr.mPid);
2146                    }
2147                }
2148            } else {
2149                if (hdlr == null) {
2150                    hdlr = new SetModeDeathHandler(cb, pid);
2151                }
2152                // Register for client death notification
2153                try {
2154                    cb.linkToDeath(hdlr, 0);
2155                } catch (RemoteException e) {
2156                    // Client has died!
2157                    Log.w(TAG, "setMode() could not link to "+cb+" binder death");
2158                }
2159
2160                // Last client to call setMode() is always at top of client list
2161                // as required by SetModeDeathHandler.binderDied()
2162                mSetModeDeathHandlers.add(0, hdlr);
2163                hdlr.setMode(mode);
2164            }
2165
2166            if (mode != mMode) {
2167                status = AudioSystem.setPhoneState(mode);
2168                if (status == AudioSystem.AUDIO_STATUS_OK) {
2169                    if (DEBUG_MODE) { Log.v(TAG, " mode successfully set to " + mode); }
2170                    mMode = mode;
2171                } else {
2172                    if (hdlr != null) {
2173                        mSetModeDeathHandlers.remove(hdlr);
2174                        cb.unlinkToDeath(hdlr, 0);
2175                    }
2176                    // force reading new top of mSetModeDeathHandlers stack
2177                    if (DEBUG_MODE) { Log.w(TAG, " mode set to MODE_NORMAL after phoneState pb"); }
2178                    mode = AudioSystem.MODE_NORMAL;
2179                }
2180            } else {
2181                status = AudioSystem.AUDIO_STATUS_OK;
2182            }
2183        } while (status != AudioSystem.AUDIO_STATUS_OK && !mSetModeDeathHandlers.isEmpty());
2184
2185        if (status == AudioSystem.AUDIO_STATUS_OK) {
2186            if (mode != AudioSystem.MODE_NORMAL) {
2187                if (mSetModeDeathHandlers.isEmpty()) {
2188                    Log.e(TAG, "setMode() different from MODE_NORMAL with empty mode client stack");
2189                } else {
2190                    newModeOwnerPid = mSetModeDeathHandlers.get(0).getPid();
2191                }
2192            }
2193            int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE);
2194            int device = getDeviceForStream(streamType);
2195            int index = mStreamStates[mStreamVolumeAlias[streamType]].getIndex(device);
2196            setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, true);
2197
2198            updateStreamVolumeAlias(true /*updateVolumes*/);
2199        }
2200        return newModeOwnerPid;
2201    }
2202
2203    /** @see AudioManager#getMode() */
2204    public int getMode() {
2205        return mMode;
2206    }
2207
2208    //==========================================================================================
2209    // Sound Effects
2210    //==========================================================================================
2211
2212    private static final String TAG_AUDIO_ASSETS = "audio_assets";
2213    private static final String ATTR_VERSION = "version";
2214    private static final String TAG_GROUP = "group";
2215    private static final String ATTR_GROUP_NAME = "name";
2216    private static final String TAG_ASSET = "asset";
2217    private static final String ATTR_ASSET_ID = "id";
2218    private static final String ATTR_ASSET_FILE = "file";
2219
2220    private static final String ASSET_FILE_VERSION = "1.0";
2221    private static final String GROUP_TOUCH_SOUNDS = "touch_sounds";
2222
2223    private static final int SOUND_EFFECTS_LOAD_TIMEOUT_MS = 5000;
2224
2225    class LoadSoundEffectReply {
2226        public int mStatus = 1;
2227    };
2228
2229    private void loadTouchSoundAssetDefaults() {
2230        SOUND_EFFECT_FILES.add("Effect_Tick.ogg");
2231        for (int i = 0; i < AudioManager.NUM_SOUND_EFFECTS; i++) {
2232            SOUND_EFFECT_FILES_MAP[i][0] = 0;
2233            SOUND_EFFECT_FILES_MAP[i][1] = -1;
2234        }
2235    }
2236
2237    private void loadTouchSoundAssets() {
2238        XmlResourceParser parser = null;
2239
2240        // only load assets once.
2241        if (!SOUND_EFFECT_FILES.isEmpty()) {
2242            return;
2243        }
2244
2245        loadTouchSoundAssetDefaults();
2246
2247        try {
2248            parser = mContext.getResources().getXml(com.android.internal.R.xml.audio_assets);
2249
2250            XmlUtils.beginDocument(parser, TAG_AUDIO_ASSETS);
2251            String version = parser.getAttributeValue(null, ATTR_VERSION);
2252            boolean inTouchSoundsGroup = false;
2253
2254            if (ASSET_FILE_VERSION.equals(version)) {
2255                while (true) {
2256                    XmlUtils.nextElement(parser);
2257                    String element = parser.getName();
2258                    if (element == null) {
2259                        break;
2260                    }
2261                    if (element.equals(TAG_GROUP)) {
2262                        String name = parser.getAttributeValue(null, ATTR_GROUP_NAME);
2263                        if (GROUP_TOUCH_SOUNDS.equals(name)) {
2264                            inTouchSoundsGroup = true;
2265                            break;
2266                        }
2267                    }
2268                }
2269                while (inTouchSoundsGroup) {
2270                    XmlUtils.nextElement(parser);
2271                    String element = parser.getName();
2272                    if (element == null) {
2273                        break;
2274                    }
2275                    if (element.equals(TAG_ASSET)) {
2276                        String id = parser.getAttributeValue(null, ATTR_ASSET_ID);
2277                        String file = parser.getAttributeValue(null, ATTR_ASSET_FILE);
2278                        int fx;
2279
2280                        try {
2281                            Field field = AudioManager.class.getField(id);
2282                            fx = field.getInt(null);
2283                        } catch (Exception e) {
2284                            Log.w(TAG, "Invalid touch sound ID: "+id);
2285                            continue;
2286                        }
2287
2288                        int i = SOUND_EFFECT_FILES.indexOf(file);
2289                        if (i == -1) {
2290                            i = SOUND_EFFECT_FILES.size();
2291                            SOUND_EFFECT_FILES.add(file);
2292                        }
2293                        SOUND_EFFECT_FILES_MAP[fx][0] = i;
2294                    } else {
2295                        break;
2296                    }
2297                }
2298            }
2299        } catch (Resources.NotFoundException e) {
2300            Log.w(TAG, "audio assets file not found", e);
2301        } catch (XmlPullParserException e) {
2302            Log.w(TAG, "XML parser exception reading touch sound assets", e);
2303        } catch (IOException e) {
2304            Log.w(TAG, "I/O exception reading touch sound assets", e);
2305        } finally {
2306            if (parser != null) {
2307                parser.close();
2308            }
2309        }
2310    }
2311
2312    /** @see AudioManager#playSoundEffect(int) */
2313    public void playSoundEffect(int effectType) {
2314        playSoundEffectVolume(effectType, -1.0f);
2315    }
2316
2317    /** @see AudioManager#playSoundEffect(int, float) */
2318    public void playSoundEffectVolume(int effectType, float volume) {
2319        if (effectType >= AudioManager.NUM_SOUND_EFFECTS || effectType < 0) {
2320            Log.w(TAG, "AudioService effectType value " + effectType + " out of range");
2321            return;
2322        }
2323
2324        sendMsg(mAudioHandler, MSG_PLAY_SOUND_EFFECT, SENDMSG_QUEUE,
2325                effectType, (int) (volume * 1000), null, 0);
2326    }
2327
2328    /**
2329     * Loads samples into the soundpool.
2330     * This method must be called at first when sound effects are enabled
2331     */
2332    public boolean loadSoundEffects() {
2333        int attempts = 3;
2334        LoadSoundEffectReply reply = new LoadSoundEffectReply();
2335
2336        synchronized (reply) {
2337            sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, reply, 0);
2338            while ((reply.mStatus == 1) && (attempts-- > 0)) {
2339                try {
2340                    reply.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
2341                } catch (InterruptedException e) {
2342                    Log.w(TAG, "loadSoundEffects Interrupted while waiting sound pool loaded.");
2343                }
2344            }
2345        }
2346        return (reply.mStatus == 0);
2347    }
2348
2349    /**
2350     *  Unloads samples from the sound pool.
2351     *  This method can be called to free some memory when
2352     *  sound effects are disabled.
2353     */
2354    public void unloadSoundEffects() {
2355        sendMsg(mAudioHandler, MSG_UNLOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, null, 0);
2356    }
2357
2358    class SoundPoolListenerThread extends Thread {
2359        public SoundPoolListenerThread() {
2360            super("SoundPoolListenerThread");
2361        }
2362
2363        @Override
2364        public void run() {
2365
2366            Looper.prepare();
2367            mSoundPoolLooper = Looper.myLooper();
2368
2369            synchronized (mSoundEffectsLock) {
2370                if (mSoundPool != null) {
2371                    mSoundPoolCallBack = new SoundPoolCallback();
2372                    mSoundPool.setOnLoadCompleteListener(mSoundPoolCallBack);
2373                }
2374                mSoundEffectsLock.notify();
2375            }
2376            Looper.loop();
2377        }
2378    }
2379
2380    private final class SoundPoolCallback implements
2381            android.media.SoundPool.OnLoadCompleteListener {
2382
2383        int mStatus = 1; // 1 means neither error nor last sample loaded yet
2384        List<Integer> mSamples = new ArrayList<Integer>();
2385
2386        public int status() {
2387            return mStatus;
2388        }
2389
2390        public void setSamples(int[] samples) {
2391            for (int i = 0; i < samples.length; i++) {
2392                // do not wait ack for samples rejected upfront by SoundPool
2393                if (samples[i] > 0) {
2394                    mSamples.add(samples[i]);
2395                }
2396            }
2397        }
2398
2399        public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
2400            synchronized (mSoundEffectsLock) {
2401                int i = mSamples.indexOf(sampleId);
2402                if (i >= 0) {
2403                    mSamples.remove(i);
2404                }
2405                if ((status != 0) || mSamples. isEmpty()) {
2406                    mStatus = status;
2407                    mSoundEffectsLock.notify();
2408                }
2409            }
2410        }
2411    }
2412
2413    /** @see AudioManager#reloadAudioSettings() */
2414    public void reloadAudioSettings() {
2415        readAudioSettings(false /*userSwitch*/);
2416    }
2417
2418    private void readAudioSettings(boolean userSwitch) {
2419        // restore ringer mode, ringer mode affected streams, mute affected streams and vibrate settings
2420        readPersistedSettings();
2421
2422        // restore volume settings
2423        int numStreamTypes = AudioSystem.getNumStreamTypes();
2424        for (int streamType = 0; streamType < numStreamTypes; streamType++) {
2425            VolumeStreamState streamState = mStreamStates[streamType];
2426
2427            if (userSwitch && mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) {
2428                continue;
2429            }
2430
2431            streamState.readSettings();
2432            synchronized (VolumeStreamState.class) {
2433                // unmute stream that was muted but is not affect by mute anymore
2434                if (streamState.isMuted_syncVSS() && ((!isStreamAffectedByMute(streamType) &&
2435                        !isStreamMutedByRingerMode(streamType)) || mUseFixedVolume)) {
2436                    int size = streamState.mDeathHandlers.size();
2437                    for (int i = 0; i < size; i++) {
2438                        streamState.mDeathHandlers.get(i).mMuteCount = 1;
2439                        streamState.mDeathHandlers.get(i).mute_syncVSS(false);
2440                    }
2441                }
2442            }
2443        }
2444
2445        // apply new ringer mode before checking volume for alias streams so that streams
2446        // muted by ringer mode have the correct volume
2447        setRingerModeInt(getRingerModeInternal(), false);
2448
2449        checkAllFixedVolumeDevices();
2450        checkAllAliasStreamVolumes();
2451
2452        synchronized (mSafeMediaVolumeState) {
2453            mMusicActiveMs = MathUtils.constrain(Settings.Secure.getIntForUser(mContentResolver,
2454                    Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS, 0, UserHandle.USER_CURRENT),
2455                    0, UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX);
2456            if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) {
2457                enforceSafeMediaVolume();
2458            }
2459        }
2460    }
2461
2462    /** @see AudioManager#setSpeakerphoneOn(boolean) */
2463    public void setSpeakerphoneOn(boolean on){
2464        if (!checkAudioSettingsPermission("setSpeakerphoneOn()")) {
2465            return;
2466        }
2467
2468        if (on) {
2469            if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
2470                    sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
2471                            AudioSystem.FOR_RECORD, AudioSystem.FORCE_NONE, null, 0);
2472            }
2473            mForcedUseForComm = AudioSystem.FORCE_SPEAKER;
2474        } else if (mForcedUseForComm == AudioSystem.FORCE_SPEAKER){
2475            mForcedUseForComm = AudioSystem.FORCE_NONE;
2476        }
2477
2478        sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
2479                AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, null, 0);
2480    }
2481
2482    /** @see AudioManager#isSpeakerphoneOn() */
2483    public boolean isSpeakerphoneOn() {
2484        return (mForcedUseForComm == AudioSystem.FORCE_SPEAKER);
2485    }
2486
2487    /** @see AudioManager#setBluetoothScoOn(boolean) */
2488    public void setBluetoothScoOn(boolean on){
2489        if (!checkAudioSettingsPermission("setBluetoothScoOn()")) {
2490            return;
2491        }
2492
2493        if (on) {
2494            mForcedUseForComm = AudioSystem.FORCE_BT_SCO;
2495        } else if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
2496            mForcedUseForComm = AudioSystem.FORCE_NONE;
2497        }
2498
2499        sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
2500                AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, null, 0);
2501        sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
2502                AudioSystem.FOR_RECORD, mForcedUseForComm, null, 0);
2503    }
2504
2505    /** @see AudioManager#isBluetoothScoOn() */
2506    public boolean isBluetoothScoOn() {
2507        return (mForcedUseForComm == AudioSystem.FORCE_BT_SCO);
2508    }
2509
2510    /** @see AudioManager#setBluetoothA2dpOn(boolean) */
2511    public void setBluetoothA2dpOn(boolean on) {
2512        synchronized (mBluetoothA2dpEnabledLock) {
2513            mBluetoothA2dpEnabled = on;
2514            sendMsg(mAudioHandler, MSG_SET_FORCE_BT_A2DP_USE, SENDMSG_QUEUE,
2515                    AudioSystem.FOR_MEDIA,
2516                    mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP,
2517                    null, 0);
2518        }
2519    }
2520
2521    /** @see AudioManager#isBluetoothA2dpOn() */
2522    public boolean isBluetoothA2dpOn() {
2523        synchronized (mBluetoothA2dpEnabledLock) {
2524            return mBluetoothA2dpEnabled;
2525        }
2526    }
2527
2528    /** @see AudioManager#startBluetoothSco() */
2529    public void startBluetoothSco(IBinder cb, int targetSdkVersion) {
2530        int scoAudioMode =
2531                (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR2) ?
2532                        SCO_MODE_VIRTUAL_CALL : SCO_MODE_UNDEFINED;
2533        startBluetoothScoInt(cb, scoAudioMode);
2534    }
2535
2536    /** @see AudioManager#startBluetoothScoVirtualCall() */
2537    public void startBluetoothScoVirtualCall(IBinder cb) {
2538        startBluetoothScoInt(cb, SCO_MODE_VIRTUAL_CALL);
2539    }
2540
2541    void startBluetoothScoInt(IBinder cb, int scoAudioMode){
2542        if (!checkAudioSettingsPermission("startBluetoothSco()") ||
2543                !mSystemReady) {
2544            return;
2545        }
2546        ScoClient client = getScoClient(cb, true);
2547        // The calling identity must be cleared before calling ScoClient.incCount().
2548        // inCount() calls requestScoState() which in turn can call BluetoothHeadset APIs
2549        // and this must be done on behalf of system server to make sure permissions are granted.
2550        // The caller identity must be cleared after getScoClient() because it is needed if a new
2551        // client is created.
2552        final long ident = Binder.clearCallingIdentity();
2553        client.incCount(scoAudioMode);
2554        Binder.restoreCallingIdentity(ident);
2555    }
2556
2557    /** @see AudioManager#stopBluetoothSco() */
2558    public void stopBluetoothSco(IBinder cb){
2559        if (!checkAudioSettingsPermission("stopBluetoothSco()") ||
2560                !mSystemReady) {
2561            return;
2562        }
2563        ScoClient client = getScoClient(cb, false);
2564        // The calling identity must be cleared before calling ScoClient.decCount().
2565        // decCount() calls requestScoState() which in turn can call BluetoothHeadset APIs
2566        // and this must be done on behalf of system server to make sure permissions are granted.
2567        final long ident = Binder.clearCallingIdentity();
2568        if (client != null) {
2569            client.decCount();
2570        }
2571        Binder.restoreCallingIdentity(ident);
2572    }
2573
2574
2575    private class ScoClient implements IBinder.DeathRecipient {
2576        private IBinder mCb; // To be notified of client's death
2577        private int mCreatorPid;
2578        private int mStartcount; // number of SCO connections started by this client
2579
2580        ScoClient(IBinder cb) {
2581            mCb = cb;
2582            mCreatorPid = Binder.getCallingPid();
2583            mStartcount = 0;
2584        }
2585
2586        public void binderDied() {
2587            synchronized(mScoClients) {
2588                Log.w(TAG, "SCO client died");
2589                int index = mScoClients.indexOf(this);
2590                if (index < 0) {
2591                    Log.w(TAG, "unregistered SCO client died");
2592                } else {
2593                    clearCount(true);
2594                    mScoClients.remove(this);
2595                }
2596            }
2597        }
2598
2599        public void incCount(int scoAudioMode) {
2600            synchronized(mScoClients) {
2601                requestScoState(BluetoothHeadset.STATE_AUDIO_CONNECTED, scoAudioMode);
2602                if (mStartcount == 0) {
2603                    try {
2604                        mCb.linkToDeath(this, 0);
2605                    } catch (RemoteException e) {
2606                        // client has already died!
2607                        Log.w(TAG, "ScoClient  incCount() could not link to "+mCb+" binder death");
2608                    }
2609                }
2610                mStartcount++;
2611            }
2612        }
2613
2614        public void decCount() {
2615            synchronized(mScoClients) {
2616                if (mStartcount == 0) {
2617                    Log.w(TAG, "ScoClient.decCount() already 0");
2618                } else {
2619                    mStartcount--;
2620                    if (mStartcount == 0) {
2621                        try {
2622                            mCb.unlinkToDeath(this, 0);
2623                        } catch (NoSuchElementException e) {
2624                            Log.w(TAG, "decCount() going to 0 but not registered to binder");
2625                        }
2626                    }
2627                    requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, 0);
2628                }
2629            }
2630        }
2631
2632        public void clearCount(boolean stopSco) {
2633            synchronized(mScoClients) {
2634                if (mStartcount != 0) {
2635                    try {
2636                        mCb.unlinkToDeath(this, 0);
2637                    } catch (NoSuchElementException e) {
2638                        Log.w(TAG, "clearCount() mStartcount: "+mStartcount+" != 0 but not registered to binder");
2639                    }
2640                }
2641                mStartcount = 0;
2642                if (stopSco) {
2643                    requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, 0);
2644                }
2645            }
2646        }
2647
2648        public int getCount() {
2649            return mStartcount;
2650        }
2651
2652        public IBinder getBinder() {
2653            return mCb;
2654        }
2655
2656        public int getPid() {
2657            return mCreatorPid;
2658        }
2659
2660        public int totalCount() {
2661            synchronized(mScoClients) {
2662                int count = 0;
2663                int size = mScoClients.size();
2664                for (int i = 0; i < size; i++) {
2665                    count += mScoClients.get(i).getCount();
2666                }
2667                return count;
2668            }
2669        }
2670
2671        private void requestScoState(int state, int scoAudioMode) {
2672            checkScoAudioState();
2673            if (totalCount() == 0) {
2674                if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) {
2675                    // Make sure that the state transitions to CONNECTING even if we cannot initiate
2676                    // the connection.
2677                    broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTING);
2678                    // Accept SCO audio activation only in NORMAL audio mode or if the mode is
2679                    // currently controlled by the same client process.
2680                    synchronized(mSetModeDeathHandlers) {
2681                        if ((mSetModeDeathHandlers.isEmpty() ||
2682                                mSetModeDeathHandlers.get(0).getPid() == mCreatorPid) &&
2683                                (mScoAudioState == SCO_STATE_INACTIVE ||
2684                                 mScoAudioState == SCO_STATE_DEACTIVATE_REQ)) {
2685                            if (mScoAudioState == SCO_STATE_INACTIVE) {
2686                                mScoAudioMode = scoAudioMode;
2687                                if (scoAudioMode == SCO_MODE_UNDEFINED) {
2688                                    if (mBluetoothHeadsetDevice != null) {
2689                                        mScoAudioMode = new Integer(Settings.Global.getInt(
2690                                                                mContentResolver,
2691                                                                "bluetooth_sco_channel_"+
2692                                                                mBluetoothHeadsetDevice.getAddress(),
2693                                                                SCO_MODE_VIRTUAL_CALL));
2694                                        if (mScoAudioMode > SCO_MODE_MAX || mScoAudioMode < 0) {
2695                                            mScoAudioMode = SCO_MODE_VIRTUAL_CALL;
2696                                        }
2697                                    } else {
2698                                        mScoAudioMode = SCO_MODE_RAW;
2699                                    }
2700                                }
2701                                if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) {
2702                                    boolean status = false;
2703                                    if (mScoAudioMode == SCO_MODE_RAW) {
2704                                        status = mBluetoothHeadset.connectAudio();
2705                                    } else if (mScoAudioMode == SCO_MODE_VIRTUAL_CALL) {
2706                                        status = mBluetoothHeadset.startScoUsingVirtualVoiceCall(
2707                                                                            mBluetoothHeadsetDevice);
2708                                    } else if (mScoAudioMode == SCO_MODE_VR) {
2709                                        status = mBluetoothHeadset.startVoiceRecognition(
2710                                                                           mBluetoothHeadsetDevice);
2711                                    }
2712
2713                                    if (status) {
2714                                        mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
2715                                    } else {
2716                                        broadcastScoConnectionState(
2717                                                AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
2718                                    }
2719                                } else if (getBluetoothHeadset()) {
2720                                    mScoAudioState = SCO_STATE_ACTIVATE_REQ;
2721                                }
2722                            } else {
2723                                mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
2724                                broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTED);
2725                            }
2726                        } else {
2727                            broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
2728                        }
2729                    }
2730                } else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED &&
2731                              (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL ||
2732                               mScoAudioState == SCO_STATE_ACTIVATE_REQ)) {
2733                    if (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL) {
2734                        if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) {
2735                            boolean status = false;
2736                            if (mScoAudioMode == SCO_MODE_RAW) {
2737                                status = mBluetoothHeadset.disconnectAudio();
2738                            } else if (mScoAudioMode == SCO_MODE_VIRTUAL_CALL) {
2739                                status = mBluetoothHeadset.stopScoUsingVirtualVoiceCall(
2740                                                                        mBluetoothHeadsetDevice);
2741                            } else if (mScoAudioMode == SCO_MODE_VR) {
2742                                        status = mBluetoothHeadset.stopVoiceRecognition(
2743                                                                      mBluetoothHeadsetDevice);
2744                            }
2745
2746                            if (!status) {
2747                                mScoAudioState = SCO_STATE_INACTIVE;
2748                                broadcastScoConnectionState(
2749                                        AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
2750                            }
2751                        } else if (getBluetoothHeadset()) {
2752                            mScoAudioState = SCO_STATE_DEACTIVATE_REQ;
2753                        }
2754                    } else {
2755                        mScoAudioState = SCO_STATE_INACTIVE;
2756                        broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
2757                    }
2758                }
2759            }
2760        }
2761    }
2762
2763    private void checkScoAudioState() {
2764        if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null &&
2765                mScoAudioState == SCO_STATE_INACTIVE &&
2766                mBluetoothHeadset.getAudioState(mBluetoothHeadsetDevice)
2767                != BluetoothHeadset.STATE_AUDIO_DISCONNECTED) {
2768            mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL;
2769        }
2770    }
2771
2772    private ScoClient getScoClient(IBinder cb, boolean create) {
2773        synchronized(mScoClients) {
2774            ScoClient client = null;
2775            int size = mScoClients.size();
2776            for (int i = 0; i < size; i++) {
2777                client = mScoClients.get(i);
2778                if (client.getBinder() == cb)
2779                    return client;
2780            }
2781            if (create) {
2782                client = new ScoClient(cb);
2783                mScoClients.add(client);
2784            }
2785            return client;
2786        }
2787    }
2788
2789    public void clearAllScoClients(int exceptPid, boolean stopSco) {
2790        synchronized(mScoClients) {
2791            ScoClient savedClient = null;
2792            int size = mScoClients.size();
2793            for (int i = 0; i < size; i++) {
2794                ScoClient cl = mScoClients.get(i);
2795                if (cl.getPid() != exceptPid) {
2796                    cl.clearCount(stopSco);
2797                } else {
2798                    savedClient = cl;
2799                }
2800            }
2801            mScoClients.clear();
2802            if (savedClient != null) {
2803                mScoClients.add(savedClient);
2804            }
2805        }
2806    }
2807
2808    private boolean getBluetoothHeadset() {
2809        boolean result = false;
2810        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
2811        if (adapter != null) {
2812            result = adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
2813                                    BluetoothProfile.HEADSET);
2814        }
2815        // If we could not get a bluetooth headset proxy, send a failure message
2816        // without delay to reset the SCO audio state and clear SCO clients.
2817        // If we could get a proxy, send a delayed failure message that will reset our state
2818        // in case we don't receive onServiceConnected().
2819        sendMsg(mAudioHandler, MSG_BT_HEADSET_CNCT_FAILED,
2820                SENDMSG_REPLACE, 0, 0, null, result ? BT_HEADSET_CNCT_TIMEOUT_MS : 0);
2821        return result;
2822    }
2823
2824    private void disconnectBluetoothSco(int exceptPid) {
2825        synchronized(mScoClients) {
2826            checkScoAudioState();
2827            if (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL ||
2828                    mScoAudioState == SCO_STATE_DEACTIVATE_EXT_REQ) {
2829                if (mBluetoothHeadsetDevice != null) {
2830                    if (mBluetoothHeadset != null) {
2831                        if (!mBluetoothHeadset.stopVoiceRecognition(
2832                                mBluetoothHeadsetDevice)) {
2833                            sendMsg(mAudioHandler, MSG_BT_HEADSET_CNCT_FAILED,
2834                                    SENDMSG_REPLACE, 0, 0, null, 0);
2835                        }
2836                    } else if (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL &&
2837                            getBluetoothHeadset()) {
2838                        mScoAudioState = SCO_STATE_DEACTIVATE_EXT_REQ;
2839                    }
2840                }
2841            } else {
2842                clearAllScoClients(exceptPid, true);
2843            }
2844        }
2845    }
2846
2847    private void resetBluetoothSco() {
2848        synchronized(mScoClients) {
2849            clearAllScoClients(0, false);
2850            mScoAudioState = SCO_STATE_INACTIVE;
2851            broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
2852        }
2853    }
2854
2855    private void broadcastScoConnectionState(int state) {
2856        sendMsg(mAudioHandler, MSG_BROADCAST_BT_CONNECTION_STATE,
2857                SENDMSG_QUEUE, state, 0, null, 0);
2858    }
2859
2860    private void onBroadcastScoConnectionState(int state) {
2861        if (state != mScoConnectionState) {
2862            Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
2863            newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, state);
2864            newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_PREVIOUS_STATE,
2865                    mScoConnectionState);
2866            sendStickyBroadcastToAll(newIntent);
2867            mScoConnectionState = state;
2868        }
2869    }
2870
2871    private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
2872        new BluetoothProfile.ServiceListener() {
2873        public void onServiceConnected(int profile, BluetoothProfile proxy) {
2874            BluetoothDevice btDevice;
2875            List<BluetoothDevice> deviceList;
2876            switch(profile) {
2877            case BluetoothProfile.A2DP:
2878                synchronized (mA2dpAvrcpLock) {
2879                    mA2dp = (BluetoothA2dp) proxy;
2880                    deviceList = mA2dp.getConnectedDevices();
2881                    if (deviceList.size() > 0) {
2882                        btDevice = deviceList.get(0);
2883                        synchronized (mConnectedDevices) {
2884                            int state = mA2dp.getConnectionState(btDevice);
2885                            int delay = checkSendBecomingNoisyIntent(
2886                                                AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
2887                                                (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0);
2888                            queueMsgUnderWakeLock(mAudioHandler,
2889                                    MSG_SET_A2DP_SINK_CONNECTION_STATE,
2890                                    state,
2891                                    0,
2892                                    btDevice,
2893                                    delay);
2894                        }
2895                    }
2896                }
2897                break;
2898
2899            case BluetoothProfile.A2DP_SINK:
2900                deviceList = proxy.getConnectedDevices();
2901                if (deviceList.size() > 0) {
2902                    btDevice = deviceList.get(0);
2903                    synchronized (mConnectedDevices) {
2904                        int state = proxy.getConnectionState(btDevice);
2905                        queueMsgUnderWakeLock(mAudioHandler,
2906                                MSG_SET_A2DP_SRC_CONNECTION_STATE,
2907                                state,
2908                                0,
2909                                btDevice,
2910                                0 /* delay */);
2911                    }
2912                }
2913                break;
2914
2915            case BluetoothProfile.HEADSET:
2916                synchronized (mScoClients) {
2917                    // Discard timeout message
2918                    mAudioHandler.removeMessages(MSG_BT_HEADSET_CNCT_FAILED);
2919                    mBluetoothHeadset = (BluetoothHeadset) proxy;
2920                    deviceList = mBluetoothHeadset.getConnectedDevices();
2921                    if (deviceList.size() > 0) {
2922                        mBluetoothHeadsetDevice = deviceList.get(0);
2923                    } else {
2924                        mBluetoothHeadsetDevice = null;
2925                    }
2926                    // Refresh SCO audio state
2927                    checkScoAudioState();
2928                    // Continue pending action if any
2929                    if (mScoAudioState == SCO_STATE_ACTIVATE_REQ ||
2930                            mScoAudioState == SCO_STATE_DEACTIVATE_REQ ||
2931                            mScoAudioState == SCO_STATE_DEACTIVATE_EXT_REQ) {
2932                        boolean status = false;
2933                        if (mBluetoothHeadsetDevice != null) {
2934                            switch (mScoAudioState) {
2935                            case SCO_STATE_ACTIVATE_REQ:
2936                                mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
2937                                if (mScoAudioMode == SCO_MODE_RAW) {
2938                                    status = mBluetoothHeadset.connectAudio();
2939                                } else if (mScoAudioMode == SCO_MODE_VIRTUAL_CALL) {
2940                                    status = mBluetoothHeadset.startScoUsingVirtualVoiceCall(
2941                                                                        mBluetoothHeadsetDevice);
2942                                } else if (mScoAudioMode == SCO_MODE_VR) {
2943                                    status = mBluetoothHeadset.startVoiceRecognition(
2944                                                                      mBluetoothHeadsetDevice);
2945                                }
2946                                break;
2947                            case SCO_STATE_DEACTIVATE_REQ:
2948                                if (mScoAudioMode == SCO_MODE_RAW) {
2949                                    status = mBluetoothHeadset.disconnectAudio();
2950                                } else if (mScoAudioMode == SCO_MODE_VIRTUAL_CALL) {
2951                                    status = mBluetoothHeadset.stopScoUsingVirtualVoiceCall(
2952                                                                        mBluetoothHeadsetDevice);
2953                                } else if (mScoAudioMode == SCO_MODE_VR) {
2954                                    status = mBluetoothHeadset.stopVoiceRecognition(
2955                                                                      mBluetoothHeadsetDevice);
2956                                }
2957                                break;
2958                            case SCO_STATE_DEACTIVATE_EXT_REQ:
2959                                status = mBluetoothHeadset.stopVoiceRecognition(
2960                                        mBluetoothHeadsetDevice);
2961                            }
2962                        }
2963                        if (!status) {
2964                            sendMsg(mAudioHandler, MSG_BT_HEADSET_CNCT_FAILED,
2965                                    SENDMSG_REPLACE, 0, 0, null, 0);
2966                        }
2967                    }
2968                }
2969                break;
2970
2971            default:
2972                break;
2973            }
2974        }
2975        public void onServiceDisconnected(int profile) {
2976            switch(profile) {
2977            case BluetoothProfile.A2DP:
2978                synchronized (mA2dpAvrcpLock) {
2979                    mA2dp = null;
2980                    synchronized (mConnectedDevices) {
2981                        if (mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP)) {
2982                            makeA2dpDeviceUnavailableNow(
2983                                    mConnectedDevices.get(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP));
2984                        }
2985                    }
2986                }
2987                break;
2988
2989            case BluetoothProfile.A2DP_SINK:
2990                synchronized (mConnectedDevices) {
2991                    if (mConnectedDevices.containsKey(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP)) {
2992                        makeA2dpSrcUnavailable(
2993                                mConnectedDevices.get(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP));
2994                    }
2995                }
2996                break;
2997
2998            case BluetoothProfile.HEADSET:
2999                synchronized (mScoClients) {
3000                    mBluetoothHeadset = null;
3001                }
3002                break;
3003
3004            default:
3005                break;
3006            }
3007        }
3008    };
3009
3010    private void onCheckMusicActive() {
3011        synchronized (mSafeMediaVolumeState) {
3012            if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE) {
3013                int device = getDeviceForStream(AudioSystem.STREAM_MUSIC);
3014
3015                if ((device & mSafeMediaVolumeDevices) != 0) {
3016                    sendMsg(mAudioHandler,
3017                            MSG_CHECK_MUSIC_ACTIVE,
3018                            SENDMSG_REPLACE,
3019                            0,
3020                            0,
3021                            null,
3022                            MUSIC_ACTIVE_POLL_PERIOD_MS);
3023                    int index = mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(device);
3024                    if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0) &&
3025                            (index > mSafeMediaVolumeIndex)) {
3026                        // Approximate cumulative active music time
3027                        mMusicActiveMs += MUSIC_ACTIVE_POLL_PERIOD_MS;
3028                        if (mMusicActiveMs > UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX) {
3029                            setSafeMediaVolumeEnabled(true);
3030                            mMusicActiveMs = 0;
3031                        }
3032                        saveMusicActiveMs();
3033                    }
3034                }
3035            }
3036        }
3037    }
3038
3039    private void saveMusicActiveMs() {
3040        mAudioHandler.obtainMessage(MSG_PERSIST_MUSIC_ACTIVE_MS, mMusicActiveMs, 0).sendToTarget();
3041    }
3042
3043    private void onConfigureSafeVolume(boolean force) {
3044        synchronized (mSafeMediaVolumeState) {
3045            int mcc = mContext.getResources().getConfiguration().mcc;
3046            if ((mMcc != mcc) || ((mMcc == 0) && force)) {
3047                mSafeMediaVolumeIndex = mContext.getResources().getInteger(
3048                        com.android.internal.R.integer.config_safe_media_volume_index) * 10;
3049                boolean safeMediaVolumeEnabled =
3050                        SystemProperties.getBoolean("audio.safemedia.force", false)
3051                        || mContext.getResources().getBoolean(
3052                                com.android.internal.R.bool.config_safe_media_volume_enabled);
3053
3054                // The persisted state is either "disabled" or "active": this is the state applied
3055                // next time we boot and cannot be "inactive"
3056                int persistedState;
3057                if (safeMediaVolumeEnabled) {
3058                    persistedState = SAFE_MEDIA_VOLUME_ACTIVE;
3059                    // The state can already be "inactive" here if the user has forced it before
3060                    // the 30 seconds timeout for forced configuration. In this case we don't reset
3061                    // it to "active".
3062                    if (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_INACTIVE) {
3063                        if (mMusicActiveMs == 0) {
3064                            mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE;
3065                            enforceSafeMediaVolume();
3066                        } else {
3067                            // We have existing playback time recorded, already confirmed.
3068                            mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE;
3069                        }
3070                    }
3071                } else {
3072                    persistedState = SAFE_MEDIA_VOLUME_DISABLED;
3073                    mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_DISABLED;
3074                }
3075                mMcc = mcc;
3076                sendMsg(mAudioHandler,
3077                        MSG_PERSIST_SAFE_VOLUME_STATE,
3078                        SENDMSG_QUEUE,
3079                        persistedState,
3080                        0,
3081                        null,
3082                        0);
3083            }
3084        }
3085    }
3086
3087    ///////////////////////////////////////////////////////////////////////////
3088    // Internal methods
3089    ///////////////////////////////////////////////////////////////////////////
3090
3091    /**
3092     * Checks if the adjustment should change ringer mode instead of just
3093     * adjusting volume. If so, this will set the proper ringer mode and volume
3094     * indices on the stream states.
3095     */
3096    private int checkForRingerModeChange(int oldIndex, int direction,  int step) {
3097        int result = FLAG_ADJUST_VOLUME;
3098        int ringerMode = getRingerModeInternal();
3099
3100        switch (ringerMode) {
3101        case RINGER_MODE_NORMAL:
3102            if (direction == AudioManager.ADJUST_LOWER) {
3103                if (mHasVibrator) {
3104                    // "step" is the delta in internal index units corresponding to a
3105                    // change of 1 in UI index units.
3106                    // Because of rounding when rescaling from one stream index range to its alias
3107                    // index range, we cannot simply test oldIndex == step:
3108                    //   (step <= oldIndex < 2 * step) is equivalent to: (old UI index == 1)
3109                    if (step <= oldIndex && oldIndex < 2 * step) {
3110                        ringerMode = RINGER_MODE_VIBRATE;
3111                    }
3112                } else {
3113                    // (oldIndex < step) is equivalent to (old UI index == 0)
3114                    if ((oldIndex < step)
3115                            && VOLUME_SETS_RINGER_MODE_SILENT
3116                            && mPrevVolDirection != AudioManager.ADJUST_LOWER) {
3117                        ringerMode = RINGER_MODE_SILENT;
3118                    }
3119                }
3120            }
3121            break;
3122        case RINGER_MODE_VIBRATE:
3123            if (!mHasVibrator) {
3124                Log.e(TAG, "checkForRingerModeChange() current ringer mode is vibrate" +
3125                        "but no vibrator is present");
3126                break;
3127            }
3128            if ((direction == AudioManager.ADJUST_LOWER)) {
3129                if (mPrevVolDirection != AudioManager.ADJUST_LOWER) {
3130                    if (VOLUME_SETS_RINGER_MODE_SILENT) {
3131                        ringerMode = RINGER_MODE_SILENT;
3132                    } else {
3133                        result |= AudioManager.FLAG_SHOW_VIBRATE_HINT;
3134                    }
3135                }
3136            } else if (direction == AudioManager.ADJUST_RAISE) {
3137                ringerMode = RINGER_MODE_NORMAL;
3138            }
3139            result &= ~FLAG_ADJUST_VOLUME;
3140            break;
3141        case RINGER_MODE_SILENT:
3142            if (direction == AudioManager.ADJUST_RAISE) {
3143                if (PREVENT_VOLUME_ADJUSTMENT_IF_SILENT) {
3144                    result |= AudioManager.FLAG_SHOW_SILENT_HINT;
3145                } else {
3146                  if (mHasVibrator) {
3147                      ringerMode = RINGER_MODE_VIBRATE;
3148                  } else {
3149                      ringerMode = RINGER_MODE_NORMAL;
3150                  }
3151                }
3152            }
3153            result &= ~FLAG_ADJUST_VOLUME;
3154            break;
3155        default:
3156            Log.e(TAG, "checkForRingerModeChange() wrong ringer mode: "+ringerMode);
3157            break;
3158        }
3159
3160        setRingerMode(ringerMode, TAG + ".checkForRingerModeChange", false /*external*/);
3161
3162        mPrevVolDirection = direction;
3163
3164        return result;
3165    }
3166
3167    @Override
3168    public boolean isStreamAffectedByRingerMode(int streamType) {
3169        return (mRingerModeAffectedStreams & (1 << streamType)) != 0;
3170    }
3171
3172    private boolean isStreamMutedByRingerMode(int streamType) {
3173        return (mRingerModeMutedStreams & (1 << streamType)) != 0;
3174    }
3175
3176    boolean updateRingerModeAffectedStreams() {
3177        int ringerModeAffectedStreams;
3178        // make sure settings for ringer mode are consistent with device type: non voice capable
3179        // devices (tablets) include media stream in silent mode whereas phones don't.
3180        ringerModeAffectedStreams = Settings.System.getIntForUser(mContentResolver,
3181                Settings.System.MODE_RINGER_STREAMS_AFFECTED,
3182                ((1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_NOTIFICATION)|
3183                 (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)),
3184                 UserHandle.USER_CURRENT);
3185
3186        // ringtone, notification and system streams are always affected by ringer mode
3187        ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_RING)|
3188                                        (1 << AudioSystem.STREAM_NOTIFICATION)|
3189                                        (1 << AudioSystem.STREAM_SYSTEM);
3190
3191        switch (mPlatformType) {
3192            case PLATFORM_TELEVISION:
3193                ringerModeAffectedStreams = 0;
3194                break;
3195            default:
3196                ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_MUSIC);
3197                break;
3198        }
3199
3200        synchronized (mCameraSoundForced) {
3201            if (mCameraSoundForced) {
3202                ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
3203            } else {
3204                ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
3205            }
3206        }
3207        if (mStreamVolumeAlias[AudioSystem.STREAM_DTMF] == AudioSystem.STREAM_RING) {
3208            ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_DTMF);
3209        } else {
3210            ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_DTMF);
3211        }
3212
3213        if (ringerModeAffectedStreams != mRingerModeAffectedStreams) {
3214            Settings.System.putIntForUser(mContentResolver,
3215                    Settings.System.MODE_RINGER_STREAMS_AFFECTED,
3216                    ringerModeAffectedStreams,
3217                    UserHandle.USER_CURRENT);
3218            mRingerModeAffectedStreams = ringerModeAffectedStreams;
3219            return true;
3220        }
3221        return false;
3222    }
3223
3224    public boolean isStreamAffectedByMute(int streamType) {
3225        return (mMuteAffectedStreams & (1 << streamType)) != 0;
3226    }
3227
3228    private void ensureValidDirection(int direction) {
3229        if (direction < AudioManager.ADJUST_LOWER || direction > AudioManager.ADJUST_RAISE) {
3230            throw new IllegalArgumentException("Bad direction " + direction);
3231        }
3232    }
3233
3234    private void ensureValidSteps(int steps) {
3235        if (Math.abs(steps) > MAX_BATCH_VOLUME_ADJUST_STEPS) {
3236            throw new IllegalArgumentException("Bad volume adjust steps " + steps);
3237        }
3238    }
3239
3240    private void ensureValidStreamType(int streamType) {
3241        if (streamType < 0 || streamType >= mStreamStates.length) {
3242            throw new IllegalArgumentException("Bad stream type " + streamType);
3243        }
3244    }
3245
3246    private boolean isInCommunication() {
3247        boolean IsInCall = false;
3248
3249        TelecomManager telecomManager =
3250                (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
3251
3252        final long ident = Binder.clearCallingIdentity();
3253        IsInCall = telecomManager.isInCall();
3254        Binder.restoreCallingIdentity(ident);
3255
3256        return (IsInCall || getMode() == AudioManager.MODE_IN_COMMUNICATION);
3257    }
3258
3259    /**
3260     * For code clarity for getActiveStreamType(int)
3261     * @param delay_ms max time since last STREAM_MUSIC activity to consider
3262     * @return true if STREAM_MUSIC is active in streams handled by AudioFlinger now or
3263     *     in the last "delay_ms" ms.
3264     */
3265    private boolean isAfMusicActiveRecently(int delay_ms) {
3266        return AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, delay_ms)
3267                || AudioSystem.isStreamActiveRemotely(AudioSystem.STREAM_MUSIC, delay_ms);
3268    }
3269
3270    private int getActiveStreamType(int suggestedStreamType) {
3271        switch (mPlatformType) {
3272        case PLATFORM_VOICE:
3273            if (isInCommunication()) {
3274                if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION)
3275                        == AudioSystem.FORCE_BT_SCO) {
3276                    // Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO...");
3277                    return AudioSystem.STREAM_BLUETOOTH_SCO;
3278                } else {
3279                    // Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL...");
3280                    return AudioSystem.STREAM_VOICE_CALL;
3281                }
3282            } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
3283                if (isAfMusicActiveRecently(StreamOverride.sDelayMs)) {
3284                    if (DEBUG_VOL)
3285                        Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC stream active");
3286                    return AudioSystem.STREAM_MUSIC;
3287                    } else {
3288                        if (DEBUG_VOL)
3289                            Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING b/c default");
3290                        return AudioSystem.STREAM_RING;
3291                }
3292            } else if (isAfMusicActiveRecently(0)) {
3293                if (DEBUG_VOL)
3294                    Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC stream active");
3295                return AudioSystem.STREAM_MUSIC;
3296            }
3297            break;
3298        case PLATFORM_TELEVISION:
3299            if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
3300                    // TV always defaults to STREAM_MUSIC
3301                    return AudioSystem.STREAM_MUSIC;
3302            }
3303            break;
3304        default:
3305            if (isInCommunication()) {
3306                if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION)
3307                        == AudioSystem.FORCE_BT_SCO) {
3308                    if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO");
3309                    return AudioSystem.STREAM_BLUETOOTH_SCO;
3310                } else {
3311                    if (DEBUG_VOL)  Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL");
3312                    return AudioSystem.STREAM_VOICE_CALL;
3313                }
3314            } else if (AudioSystem.isStreamActive(AudioSystem.STREAM_NOTIFICATION,
3315                    StreamOverride.sDelayMs) ||
3316                    AudioSystem.isStreamActive(AudioSystem.STREAM_RING,
3317                            StreamOverride.sDelayMs)) {
3318                if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION");
3319                return AudioSystem.STREAM_NOTIFICATION;
3320            } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
3321                if (isAfMusicActiveRecently(StreamOverride.sDelayMs)) {
3322                    if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: forcing STREAM_MUSIC");
3323                    return AudioSystem.STREAM_MUSIC;
3324                } else {
3325                    if (DEBUG_VOL) Log.v(TAG,
3326                            "getActiveStreamType: using STREAM_NOTIFICATION as default");
3327                    return AudioSystem.STREAM_NOTIFICATION;
3328                }
3329            }
3330            break;
3331        }
3332        if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Returning suggested type "
3333                + suggestedStreamType);
3334        return suggestedStreamType;
3335    }
3336
3337    private void broadcastRingerMode(String action, int ringerMode) {
3338        // Send sticky broadcast
3339        Intent broadcast = new Intent(action);
3340        broadcast.putExtra(AudioManager.EXTRA_RINGER_MODE, ringerMode);
3341        broadcast.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
3342                | Intent.FLAG_RECEIVER_REPLACE_PENDING);
3343        sendStickyBroadcastToAll(broadcast);
3344    }
3345
3346    private void broadcastVibrateSetting(int vibrateType) {
3347        // Send broadcast
3348        if (ActivityManagerNative.isSystemReady()) {
3349            Intent broadcast = new Intent(AudioManager.VIBRATE_SETTING_CHANGED_ACTION);
3350            broadcast.putExtra(AudioManager.EXTRA_VIBRATE_TYPE, vibrateType);
3351            broadcast.putExtra(AudioManager.EXTRA_VIBRATE_SETTING, getVibrateSetting(vibrateType));
3352            sendBroadcastToAll(broadcast);
3353        }
3354    }
3355
3356    // Message helper methods
3357    /**
3358     * Queue a message on the given handler's message queue, after acquiring the service wake lock.
3359     * Note that the wake lock needs to be released after the message has been handled.
3360     */
3361    private void queueMsgUnderWakeLock(Handler handler, int msg,
3362            int arg1, int arg2, Object obj, int delay) {
3363        final long ident = Binder.clearCallingIdentity();
3364        // Always acquire the wake lock as AudioService because it is released by the
3365        // message handler.
3366        mAudioEventWakeLock.acquire();
3367        Binder.restoreCallingIdentity(ident);
3368        sendMsg(handler, msg, SENDMSG_QUEUE, arg1, arg2, obj, delay);
3369    }
3370
3371    private static void sendMsg(Handler handler, int msg,
3372            int existingMsgPolicy, int arg1, int arg2, Object obj, int delay) {
3373
3374        if (existingMsgPolicy == SENDMSG_REPLACE) {
3375            handler.removeMessages(msg);
3376        } else if (existingMsgPolicy == SENDMSG_NOOP && handler.hasMessages(msg)) {
3377            return;
3378        }
3379        synchronized (mLastDeviceConnectMsgTime) {
3380            long time = SystemClock.uptimeMillis() + delay;
3381            handler.sendMessageAtTime(handler.obtainMessage(msg, arg1, arg2, obj), time);
3382            if (msg == MSG_SET_WIRED_DEVICE_CONNECTION_STATE ||
3383                    msg == MSG_SET_A2DP_SRC_CONNECTION_STATE ||
3384                    msg == MSG_SET_A2DP_SINK_CONNECTION_STATE) {
3385                mLastDeviceConnectMsgTime = time;
3386            }
3387        }
3388    }
3389
3390    boolean checkAudioSettingsPermission(String method) {
3391        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS)
3392                == PackageManager.PERMISSION_GRANTED) {
3393            return true;
3394        }
3395        String msg = "Audio Settings Permission Denial: " + method + " from pid="
3396                + Binder.getCallingPid()
3397                + ", uid=" + Binder.getCallingUid();
3398        Log.w(TAG, msg);
3399        return false;
3400    }
3401
3402    private int getDeviceForStream(int stream) {
3403        int device = AudioSystem.getDevicesForStream(stream);
3404        if ((device & (device - 1)) != 0) {
3405            // Multiple device selection is either:
3406            //  - speaker + one other device: give priority to speaker in this case.
3407            //  - one A2DP device + another device: happens with duplicated output. In this case
3408            // retain the device on the A2DP output as the other must not correspond to an active
3409            // selection if not the speaker.
3410            //  - HDMI-CEC system audio mode only output: give priority to available item in order.
3411            if ((device & AudioSystem.DEVICE_OUT_SPEAKER) != 0) {
3412                device = AudioSystem.DEVICE_OUT_SPEAKER;
3413            } else if ((device & AudioSystem.DEVICE_OUT_HDMI_ARC) != 0) {
3414                device = AudioSystem.DEVICE_OUT_HDMI_ARC;
3415            } else if ((device & AudioSystem.DEVICE_OUT_SPDIF) != 0) {
3416                device = AudioSystem.DEVICE_OUT_SPDIF;
3417            } else if ((device & AudioSystem.DEVICE_OUT_AUX_LINE) != 0) {
3418                device = AudioSystem.DEVICE_OUT_AUX_LINE;
3419            } else {
3420                device &= AudioSystem.DEVICE_OUT_ALL_A2DP;
3421            }
3422        }
3423        return device;
3424    }
3425
3426    public void setWiredDeviceConnectionState(int device, int state, String name) {
3427        synchronized (mConnectedDevices) {
3428            int delay = checkSendBecomingNoisyIntent(device, state);
3429            queueMsgUnderWakeLock(mAudioHandler,
3430                    MSG_SET_WIRED_DEVICE_CONNECTION_STATE,
3431                    device,
3432                    state,
3433                    name,
3434                    delay);
3435        }
3436    }
3437
3438    public int setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state, int profile)
3439    {
3440        int delay;
3441        if (profile != BluetoothProfile.A2DP && profile != BluetoothProfile.A2DP_SINK) {
3442            throw new IllegalArgumentException("invalid profile " + profile);
3443        }
3444        synchronized (mConnectedDevices) {
3445            if (profile == BluetoothProfile.A2DP) {
3446                delay = checkSendBecomingNoisyIntent(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
3447                                                (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0);
3448            } else {
3449                delay = 0;
3450            }
3451            queueMsgUnderWakeLock(mAudioHandler,
3452                    (profile == BluetoothProfile.A2DP ?
3453                        MSG_SET_A2DP_SINK_CONNECTION_STATE : MSG_SET_A2DP_SRC_CONNECTION_STATE),
3454                    state,
3455                    0,
3456                    device,
3457                    delay);
3458        }
3459        return delay;
3460    }
3461
3462    ///////////////////////////////////////////////////////////////////////////
3463    // Inner classes
3464    ///////////////////////////////////////////////////////////////////////////
3465
3466    // NOTE: Locking order for synchronized objects related to volume or ringer mode management:
3467    //  1 mScoclient OR mSafeMediaVolumeState
3468    //  2   mSetModeDeathHandlers
3469    //  3     mSettingsLock
3470    //  4       VolumeStreamState.class
3471    //  5         mCameraSoundForced
3472    public class VolumeStreamState {
3473        private final int mStreamType;
3474
3475        private String mVolumeIndexSettingName;
3476        private int mIndexMax;
3477        private final ConcurrentHashMap<Integer, Integer> mIndex =
3478                                            new ConcurrentHashMap<Integer, Integer>(8, 0.75f, 4);
3479        private ArrayList<VolumeDeathHandler> mDeathHandlers; //handles mute/solo clients death
3480
3481        private VolumeStreamState(String settingName, int streamType) {
3482
3483            mVolumeIndexSettingName = settingName;
3484
3485            mStreamType = streamType;
3486            mIndexMax = MAX_STREAM_VOLUME[streamType];
3487            AudioSystem.initStreamVolume(streamType, 0, mIndexMax);
3488            mIndexMax *= 10;
3489
3490            // mDeathHandlers must be created before calling readSettings()
3491            mDeathHandlers = new ArrayList<VolumeDeathHandler>();
3492
3493            readSettings();
3494        }
3495
3496        public String getSettingNameForDevice(int device) {
3497            String name = mVolumeIndexSettingName;
3498            String suffix = AudioSystem.getOutputDeviceName(device);
3499            if (suffix.isEmpty()) {
3500                return name;
3501            }
3502            return name + "_" + suffix;
3503        }
3504
3505        public void readSettings() {
3506            synchronized (VolumeStreamState.class) {
3507                // force maximum volume on all streams if fixed volume property
3508                // or master volume property is set
3509                if (mUseFixedVolume || mUseMasterVolume) {
3510                    mIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, mIndexMax);
3511                    return;
3512                }
3513                // do not read system stream volume from settings: this stream is always aliased
3514                // to another stream type and its volume is never persisted. Values in settings can
3515                // only be stale values
3516                if ((mStreamType == AudioSystem.STREAM_SYSTEM) ||
3517                        (mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED)) {
3518                    int index = 10 * DEFAULT_STREAM_VOLUME[mStreamType];
3519                    synchronized (mCameraSoundForced) {
3520                        if (mCameraSoundForced) {
3521                            index = mIndexMax;
3522                        }
3523                    }
3524                    mIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, index);
3525                    return;
3526                }
3527
3528                int remainingDevices = AudioSystem.DEVICE_OUT_ALL;
3529
3530                for (int i = 0; remainingDevices != 0; i++) {
3531                    int device = (1 << i);
3532                    if ((device & remainingDevices) == 0) {
3533                        continue;
3534                    }
3535                    remainingDevices &= ~device;
3536
3537                    // retrieve current volume for device
3538                    String name = getSettingNameForDevice(device);
3539                    // if no volume stored for current stream and device, use default volume if default
3540                    // device, continue otherwise
3541                    int defaultIndex = (device == AudioSystem.DEVICE_OUT_DEFAULT) ?
3542                                            DEFAULT_STREAM_VOLUME[mStreamType] : -1;
3543                    int index = Settings.System.getIntForUser(
3544                            mContentResolver, name, defaultIndex, UserHandle.USER_CURRENT);
3545                    if (index == -1) {
3546                        continue;
3547                    }
3548
3549                    mIndex.put(device, getValidIndex(10 * index));
3550                }
3551            }
3552        }
3553
3554        // must be called while synchronized VolumeStreamState.class
3555        public void applyDeviceVolume_syncVSS(int device) {
3556            int index;
3557            if (isMuted_syncVSS()) {
3558                index = 0;
3559            } else if (((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && mAvrcpAbsVolSupported)
3560                    || ((device & mFullVolumeDevices) != 0)) {
3561                index = (mIndexMax + 5)/10;
3562            } else {
3563                index = (getIndex(device) + 5)/10;
3564            }
3565            AudioSystem.setStreamVolumeIndex(mStreamType, index, device);
3566        }
3567
3568        public void applyAllVolumes() {
3569            synchronized (VolumeStreamState.class) {
3570                // apply default volume first: by convention this will reset all
3571                // devices volumes in audio policy manager to the supplied value
3572                int index;
3573                if (isMuted_syncVSS()) {
3574                    index = 0;
3575                } else {
3576                    index = (getIndex(AudioSystem.DEVICE_OUT_DEFAULT) + 5)/10;
3577                }
3578                AudioSystem.setStreamVolumeIndex(mStreamType, index, AudioSystem.DEVICE_OUT_DEFAULT);
3579                // then apply device specific volumes
3580                Set set = mIndex.entrySet();
3581                Iterator i = set.iterator();
3582                while (i.hasNext()) {
3583                    Map.Entry entry = (Map.Entry)i.next();
3584                    int device = ((Integer)entry.getKey()).intValue();
3585                    if (device != AudioSystem.DEVICE_OUT_DEFAULT) {
3586                        if (isMuted_syncVSS()) {
3587                            index = 0;
3588                        } else if (((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
3589                                mAvrcpAbsVolSupported)
3590                                    || ((device & mFullVolumeDevices) != 0))
3591                        {
3592                            index = (mIndexMax + 5)/10;
3593                        } else {
3594                            index = ((Integer)entry.getValue() + 5)/10;
3595                        }
3596                        AudioSystem.setStreamVolumeIndex(mStreamType, index, device);
3597                    }
3598                }
3599            }
3600        }
3601
3602        public boolean adjustIndex(int deltaIndex, int device) {
3603            return setIndex(getIndex(device) + deltaIndex,
3604                            device);
3605        }
3606
3607        public boolean setIndex(int index, int device) {
3608            synchronized (VolumeStreamState.class) {
3609                int oldIndex = getIndex(device);
3610                index = getValidIndex(index);
3611                synchronized (mCameraSoundForced) {
3612                    if ((mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED) && mCameraSoundForced) {
3613                        index = mIndexMax;
3614                    }
3615                }
3616                mIndex.put(device, index);
3617
3618                if (oldIndex != index) {
3619                    // Apply change to all streams using this one as alias
3620                    // if changing volume of current device, also change volume of current
3621                    // device on aliased stream
3622                    boolean currentDevice = (device == getDeviceForStream(mStreamType));
3623                    int numStreamTypes = AudioSystem.getNumStreamTypes();
3624                    for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
3625                        if (streamType != mStreamType &&
3626                                mStreamVolumeAlias[streamType] == mStreamType) {
3627                            int scaledIndex = rescaleIndex(index, mStreamType, streamType);
3628                            mStreamStates[streamType].setIndex(scaledIndex,
3629                                                               device);
3630                            if (currentDevice) {
3631                                mStreamStates[streamType].setIndex(scaledIndex,
3632                                                                   getDeviceForStream(streamType));
3633                            }
3634                        }
3635                    }
3636                    return true;
3637                } else {
3638                    return false;
3639                }
3640            }
3641        }
3642
3643        public int getIndex(int device) {
3644            synchronized (VolumeStreamState.class) {
3645                Integer index = mIndex.get(device);
3646                if (index == null) {
3647                    // there is always an entry for AudioSystem.DEVICE_OUT_DEFAULT
3648                    index = mIndex.get(AudioSystem.DEVICE_OUT_DEFAULT);
3649                }
3650                return index.intValue();
3651            }
3652        }
3653
3654        public int getMaxIndex() {
3655            return mIndexMax;
3656        }
3657
3658        public void setAllIndexes(VolumeStreamState srcStream) {
3659            synchronized (VolumeStreamState.class) {
3660                int srcStreamType = srcStream.getStreamType();
3661                // apply default device volume from source stream to all devices first in case
3662                // some devices are present in this stream state but not in source stream state
3663                int index = srcStream.getIndex(AudioSystem.DEVICE_OUT_DEFAULT);
3664                index = rescaleIndex(index, srcStreamType, mStreamType);
3665                Set set = mIndex.entrySet();
3666                Iterator i = set.iterator();
3667                while (i.hasNext()) {
3668                    Map.Entry entry = (Map.Entry)i.next();
3669                    entry.setValue(index);
3670                }
3671                // Now apply actual volume for devices in source stream state
3672                set = srcStream.mIndex.entrySet();
3673                i = set.iterator();
3674                while (i.hasNext()) {
3675                    Map.Entry entry = (Map.Entry)i.next();
3676                    int device = ((Integer)entry.getKey()).intValue();
3677                    index = ((Integer)entry.getValue()).intValue();
3678                    index = rescaleIndex(index, srcStreamType, mStreamType);
3679
3680                    setIndex(index, device);
3681                }
3682            }
3683        }
3684
3685        public void setAllIndexesToMax() {
3686            synchronized (VolumeStreamState.class) {
3687                Set set = mIndex.entrySet();
3688                Iterator i = set.iterator();
3689                while (i.hasNext()) {
3690                    Map.Entry entry = (Map.Entry)i.next();
3691                    entry.setValue(mIndexMax);
3692                }
3693            }
3694        }
3695
3696        public void mute(IBinder cb, boolean state) {
3697            synchronized (VolumeStreamState.class) {
3698                VolumeDeathHandler handler = getDeathHandler_syncVSS(cb, state);
3699                if (handler == null) {
3700                    Log.e(TAG, "Could not get client death handler for stream: "+mStreamType);
3701                    return;
3702                }
3703                handler.mute_syncVSS(state);
3704            }
3705        }
3706
3707        public int getStreamType() {
3708            return mStreamType;
3709        }
3710
3711        public void checkFixedVolumeDevices() {
3712            synchronized (VolumeStreamState.class) {
3713                // ignore settings for fixed volume devices: volume should always be at max or 0
3714                if (mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_MUSIC) {
3715                    Set set = mIndex.entrySet();
3716                    Iterator i = set.iterator();
3717                    while (i.hasNext()) {
3718                        Map.Entry entry = (Map.Entry)i.next();
3719                        int device = ((Integer)entry.getKey()).intValue();
3720                        int index = ((Integer)entry.getValue()).intValue();
3721                        if (((device & mFullVolumeDevices) != 0)
3722                                || (((device & mFixedVolumeDevices) != 0) && index != 0)) {
3723                            entry.setValue(mIndexMax);
3724                        }
3725                        applyDeviceVolume_syncVSS(device);
3726                    }
3727                }
3728            }
3729        }
3730
3731        private int getValidIndex(int index) {
3732            if (index < 0) {
3733                return 0;
3734            } else if (mUseFixedVolume || mUseMasterVolume || index > mIndexMax) {
3735                return mIndexMax;
3736            }
3737
3738            return index;
3739        }
3740
3741        private class VolumeDeathHandler implements IBinder.DeathRecipient {
3742            private IBinder mICallback; // To be notified of client's death
3743            private int mMuteCount; // Number of active mutes for this client
3744
3745            VolumeDeathHandler(IBinder cb) {
3746                mICallback = cb;
3747            }
3748
3749            // must be called while synchronized VolumeStreamState.class
3750            public void mute_syncVSS(boolean state) {
3751                boolean updateVolume = false;
3752                if (state) {
3753                    if (mMuteCount == 0) {
3754                        // Register for client death notification
3755                        try {
3756                            // mICallback can be 0 if muted by AudioService
3757                            if (mICallback != null) {
3758                                mICallback.linkToDeath(this, 0);
3759                            }
3760                            VolumeStreamState.this.mDeathHandlers.add(this);
3761                            // If the stream is not yet muted by any client, set level to 0
3762                            if (!VolumeStreamState.this.isMuted_syncVSS()) {
3763                                updateVolume = true;
3764                            }
3765                        } catch (RemoteException e) {
3766                            // Client has died!
3767                            binderDied();
3768                            return;
3769                        }
3770                    } else {
3771                        Log.w(TAG, "stream: "+mStreamType+" was already muted by this client");
3772                    }
3773                    mMuteCount++;
3774                } else {
3775                    if (mMuteCount == 0) {
3776                        Log.e(TAG, "unexpected unmute for stream: "+mStreamType);
3777                    } else {
3778                        mMuteCount--;
3779                        if (mMuteCount == 0) {
3780                            // Unregister from client death notification
3781                            VolumeStreamState.this.mDeathHandlers.remove(this);
3782                            // mICallback can be 0 if muted by AudioService
3783                            if (mICallback != null) {
3784                                mICallback.unlinkToDeath(this, 0);
3785                            }
3786                            if (!VolumeStreamState.this.isMuted_syncVSS()) {
3787                                updateVolume = true;
3788                            }
3789                        }
3790                    }
3791                }
3792                if (updateVolume) {
3793                    sendMsg(mAudioHandler,
3794                            MSG_SET_ALL_VOLUMES,
3795                            SENDMSG_QUEUE,
3796                            0,
3797                            0,
3798                            VolumeStreamState.this, 0);
3799                }
3800            }
3801
3802            public void binderDied() {
3803                Log.w(TAG, "Volume service client died for stream: "+mStreamType);
3804                synchronized (VolumeStreamState.class) {
3805                    if (mMuteCount != 0) {
3806                        // Reset all active mute requests from this client.
3807                        mMuteCount = 1;
3808                        mute_syncVSS(false);
3809                    }
3810                }
3811            }
3812        }
3813
3814        private int muteCount() {
3815            int count = 0;
3816            int size = mDeathHandlers.size();
3817            for (int i = 0; i < size; i++) {
3818                count += mDeathHandlers.get(i).mMuteCount;
3819            }
3820            return count;
3821        }
3822
3823        // must be called while synchronized VolumeStreamState.class
3824        private boolean isMuted_syncVSS() {
3825            return muteCount() != 0;
3826        }
3827
3828        // must be called while synchronized VolumeStreamState.class
3829        private VolumeDeathHandler getDeathHandler_syncVSS(IBinder cb, boolean state) {
3830            VolumeDeathHandler handler;
3831            int size = mDeathHandlers.size();
3832            for (int i = 0; i < size; i++) {
3833                handler = mDeathHandlers.get(i);
3834                if (cb == handler.mICallback) {
3835                    return handler;
3836                }
3837            }
3838            // If this is the first mute request for this client, create a new
3839            // client death handler. Otherwise, it is an out of sequence unmute request.
3840            if (state) {
3841                handler = new VolumeDeathHandler(cb);
3842            } else {
3843                Log.w(TAG, "stream was not muted by this client");
3844                handler = null;
3845            }
3846            return handler;
3847        }
3848
3849        private void dump(PrintWriter pw) {
3850            pw.print("   Mute count: ");
3851            pw.println(muteCount());
3852            pw.print("   Max: ");
3853            pw.println((mIndexMax + 5) / 10);
3854            pw.print("   Current: ");
3855            Set set = mIndex.entrySet();
3856            Iterator i = set.iterator();
3857            while (i.hasNext()) {
3858                Map.Entry entry = (Map.Entry)i.next();
3859                final int device = (Integer) entry.getKey();
3860                pw.print(Integer.toHexString(device));
3861                final String deviceName = device == AudioSystem.DEVICE_OUT_DEFAULT ? "default"
3862                        : AudioSystem.getOutputDeviceName(device);
3863                if (!deviceName.isEmpty()) {
3864                    pw.print(" (");
3865                    pw.print(deviceName);
3866                    pw.print(")");
3867                }
3868                pw.print(": ");
3869                final int index = (((Integer) entry.getValue()) + 5) / 10;
3870                pw.print(index);
3871                if (i.hasNext()) {
3872                    pw.print(", ");
3873                }
3874            }
3875        }
3876    }
3877
3878    /** Thread that handles native AudioSystem control. */
3879    private class AudioSystemThread extends Thread {
3880        AudioSystemThread() {
3881            super("AudioService");
3882        }
3883
3884        @Override
3885        public void run() {
3886            // Set this thread up so the handler will work on it
3887            Looper.prepare();
3888
3889            synchronized(AudioService.this) {
3890                mAudioHandler = new AudioHandler();
3891
3892                // Notify that the handler has been created
3893                AudioService.this.notify();
3894            }
3895
3896            // Listen for volume change requests that are set by VolumePanel
3897            Looper.loop();
3898        }
3899    }
3900
3901    /** Handles internal volume messages in separate volume thread. */
3902    private class AudioHandler extends Handler {
3903
3904        private void setDeviceVolume(VolumeStreamState streamState, int device) {
3905
3906            synchronized (VolumeStreamState.class) {
3907                // Apply volume
3908                streamState.applyDeviceVolume_syncVSS(device);
3909
3910                // Apply change to all streams using this one as alias
3911                int numStreamTypes = AudioSystem.getNumStreamTypes();
3912                for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
3913                    if (streamType != streamState.mStreamType &&
3914                            mStreamVolumeAlias[streamType] == streamState.mStreamType) {
3915                        // Make sure volume is also maxed out on A2DP device for aliased stream
3916                        // that may have a different device selected
3917                        int streamDevice = getDeviceForStream(streamType);
3918                        if ((device != streamDevice) && mAvrcpAbsVolSupported &&
3919                                ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0)) {
3920                            mStreamStates[streamType].applyDeviceVolume_syncVSS(device);
3921                        }
3922                        mStreamStates[streamType].applyDeviceVolume_syncVSS(streamDevice);
3923                    }
3924                }
3925            }
3926            // Post a persist volume msg
3927            sendMsg(mAudioHandler,
3928                    MSG_PERSIST_VOLUME,
3929                    SENDMSG_QUEUE,
3930                    device,
3931                    0,
3932                    streamState,
3933                    PERSIST_DELAY);
3934
3935        }
3936
3937        private void setAllVolumes(VolumeStreamState streamState) {
3938
3939            // Apply volume
3940            streamState.applyAllVolumes();
3941
3942            // Apply change to all streams using this one as alias
3943            int numStreamTypes = AudioSystem.getNumStreamTypes();
3944            for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
3945                if (streamType != streamState.mStreamType &&
3946                        mStreamVolumeAlias[streamType] == streamState.mStreamType) {
3947                    mStreamStates[streamType].applyAllVolumes();
3948                }
3949            }
3950        }
3951
3952        private void persistVolume(VolumeStreamState streamState, int device) {
3953            if (mUseFixedVolume) {
3954                return;
3955            }
3956            if (isPlatformTelevision() && (streamState.mStreamType != AudioSystem.STREAM_MUSIC)) {
3957                return;
3958            }
3959            System.putIntForUser(mContentResolver,
3960                      streamState.getSettingNameForDevice(device),
3961                      (streamState.getIndex(device) + 5)/ 10,
3962                      UserHandle.USER_CURRENT);
3963        }
3964
3965        private void persistRingerMode(int ringerMode) {
3966            if (mUseFixedVolume) {
3967                return;
3968            }
3969            Settings.Global.putInt(mContentResolver, Settings.Global.MODE_RINGER, ringerMode);
3970        }
3971
3972        private boolean onLoadSoundEffects() {
3973            int status;
3974
3975            synchronized (mSoundEffectsLock) {
3976                if (!mSystemReady) {
3977                    Log.w(TAG, "onLoadSoundEffects() called before boot complete");
3978                    return false;
3979                }
3980
3981                if (mSoundPool != null) {
3982                    return true;
3983                }
3984
3985                loadTouchSoundAssets();
3986
3987                mSoundPool = new SoundPool.Builder()
3988                        .setMaxStreams(NUM_SOUNDPOOL_CHANNELS)
3989                        .setAudioAttributes(new AudioAttributes.Builder()
3990                            .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
3991                            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
3992                            .build())
3993                        .build();
3994                mSoundPoolCallBack = null;
3995                mSoundPoolListenerThread = new SoundPoolListenerThread();
3996                mSoundPoolListenerThread.start();
3997                int attempts = 3;
3998                while ((mSoundPoolCallBack == null) && (attempts-- > 0)) {
3999                    try {
4000                        // Wait for mSoundPoolCallBack to be set by the other thread
4001                        mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
4002                    } catch (InterruptedException e) {
4003                        Log.w(TAG, "Interrupted while waiting sound pool listener thread.");
4004                    }
4005                }
4006
4007                if (mSoundPoolCallBack == null) {
4008                    Log.w(TAG, "onLoadSoundEffects() SoundPool listener or thread creation error");
4009                    if (mSoundPoolLooper != null) {
4010                        mSoundPoolLooper.quit();
4011                        mSoundPoolLooper = null;
4012                    }
4013                    mSoundPoolListenerThread = null;
4014                    mSoundPool.release();
4015                    mSoundPool = null;
4016                    return false;
4017                }
4018                /*
4019                 * poolId table: The value -1 in this table indicates that corresponding
4020                 * file (same index in SOUND_EFFECT_FILES[] has not been loaded.
4021                 * Once loaded, the value in poolId is the sample ID and the same
4022                 * sample can be reused for another effect using the same file.
4023                 */
4024                int[] poolId = new int[SOUND_EFFECT_FILES.size()];
4025                for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) {
4026                    poolId[fileIdx] = -1;
4027                }
4028                /*
4029                 * Effects whose value in SOUND_EFFECT_FILES_MAP[effect][1] is -1 must be loaded.
4030                 * If load succeeds, value in SOUND_EFFECT_FILES_MAP[effect][1] is > 0:
4031                 * this indicates we have a valid sample loaded for this effect.
4032                 */
4033
4034                int numSamples = 0;
4035                for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
4036                    // Do not load sample if this effect uses the MediaPlayer
4037                    if (SOUND_EFFECT_FILES_MAP[effect][1] == 0) {
4038                        continue;
4039                    }
4040                    if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == -1) {
4041                        String filePath = Environment.getRootDirectory()
4042                                + SOUND_EFFECTS_PATH
4043                                + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effect][0]);
4044                        int sampleId = mSoundPool.load(filePath, 0);
4045                        if (sampleId <= 0) {
4046                            Log.w(TAG, "Soundpool could not load file: "+filePath);
4047                        } else {
4048                            SOUND_EFFECT_FILES_MAP[effect][1] = sampleId;
4049                            poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = sampleId;
4050                            numSamples++;
4051                        }
4052                    } else {
4053                        SOUND_EFFECT_FILES_MAP[effect][1] =
4054                                poolId[SOUND_EFFECT_FILES_MAP[effect][0]];
4055                    }
4056                }
4057                // wait for all samples to be loaded
4058                if (numSamples > 0) {
4059                    mSoundPoolCallBack.setSamples(poolId);
4060
4061                    attempts = 3;
4062                    status = 1;
4063                    while ((status == 1) && (attempts-- > 0)) {
4064                        try {
4065                            mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
4066                            status = mSoundPoolCallBack.status();
4067                        } catch (InterruptedException e) {
4068                            Log.w(TAG, "Interrupted while waiting sound pool callback.");
4069                        }
4070                    }
4071                } else {
4072                    status = -1;
4073                }
4074
4075                if (mSoundPoolLooper != null) {
4076                    mSoundPoolLooper.quit();
4077                    mSoundPoolLooper = null;
4078                }
4079                mSoundPoolListenerThread = null;
4080                if (status != 0) {
4081                    Log.w(TAG,
4082                            "onLoadSoundEffects(), Error "+status+ " while loading samples");
4083                    for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
4084                        if (SOUND_EFFECT_FILES_MAP[effect][1] > 0) {
4085                            SOUND_EFFECT_FILES_MAP[effect][1] = -1;
4086                        }
4087                    }
4088
4089                    mSoundPool.release();
4090                    mSoundPool = null;
4091                }
4092            }
4093            return (status == 0);
4094        }
4095
4096        /**
4097         *  Unloads samples from the sound pool.
4098         *  This method can be called to free some memory when
4099         *  sound effects are disabled.
4100         */
4101        private void onUnloadSoundEffects() {
4102            synchronized (mSoundEffectsLock) {
4103                if (mSoundPool == null) {
4104                    return;
4105                }
4106
4107                int[] poolId = new int[SOUND_EFFECT_FILES.size()];
4108                for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) {
4109                    poolId[fileIdx] = 0;
4110                }
4111
4112                for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
4113                    if (SOUND_EFFECT_FILES_MAP[effect][1] <= 0) {
4114                        continue;
4115                    }
4116                    if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == 0) {
4117                        mSoundPool.unload(SOUND_EFFECT_FILES_MAP[effect][1]);
4118                        SOUND_EFFECT_FILES_MAP[effect][1] = -1;
4119                        poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = -1;
4120                    }
4121                }
4122                mSoundPool.release();
4123                mSoundPool = null;
4124            }
4125        }
4126
4127        private void onPlaySoundEffect(int effectType, int volume) {
4128            synchronized (mSoundEffectsLock) {
4129
4130                onLoadSoundEffects();
4131
4132                if (mSoundPool == null) {
4133                    return;
4134                }
4135                float volFloat;
4136                // use default if volume is not specified by caller
4137                if (volume < 0) {
4138                    volFloat = (float)Math.pow(10, (float)sSoundEffectVolumeDb/20);
4139                } else {
4140                    volFloat = volume / 1000.0f;
4141                }
4142
4143                if (SOUND_EFFECT_FILES_MAP[effectType][1] > 0) {
4144                    mSoundPool.play(SOUND_EFFECT_FILES_MAP[effectType][1],
4145                                        volFloat, volFloat, 0, 0, 1.0f);
4146                } else {
4147                    MediaPlayer mediaPlayer = new MediaPlayer();
4148                    try {
4149                        String filePath = Environment.getRootDirectory() + SOUND_EFFECTS_PATH +
4150                                    SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]);
4151                        mediaPlayer.setDataSource(filePath);
4152                        mediaPlayer.setAudioStreamType(AudioSystem.STREAM_SYSTEM);
4153                        mediaPlayer.prepare();
4154                        mediaPlayer.setVolume(volFloat);
4155                        mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
4156                            public void onCompletion(MediaPlayer mp) {
4157                                cleanupPlayer(mp);
4158                            }
4159                        });
4160                        mediaPlayer.setOnErrorListener(new OnErrorListener() {
4161                            public boolean onError(MediaPlayer mp, int what, int extra) {
4162                                cleanupPlayer(mp);
4163                                return true;
4164                            }
4165                        });
4166                        mediaPlayer.start();
4167                    } catch (IOException ex) {
4168                        Log.w(TAG, "MediaPlayer IOException: "+ex);
4169                    } catch (IllegalArgumentException ex) {
4170                        Log.w(TAG, "MediaPlayer IllegalArgumentException: "+ex);
4171                    } catch (IllegalStateException ex) {
4172                        Log.w(TAG, "MediaPlayer IllegalStateException: "+ex);
4173                    }
4174                }
4175            }
4176        }
4177
4178        private void cleanupPlayer(MediaPlayer mp) {
4179            if (mp != null) {
4180                try {
4181                    mp.stop();
4182                    mp.release();
4183                } catch (IllegalStateException ex) {
4184                    Log.w(TAG, "MediaPlayer IllegalStateException: "+ex);
4185                }
4186            }
4187        }
4188
4189        private void setForceUse(int usage, int config) {
4190            AudioSystem.setForceUse(usage, config);
4191        }
4192
4193        private void onPersistSafeVolumeState(int state) {
4194            Settings.Global.putInt(mContentResolver,
4195                    Settings.Global.AUDIO_SAFE_VOLUME_STATE,
4196                    state);
4197        }
4198
4199        @Override
4200        public void handleMessage(Message msg) {
4201            switch (msg.what) {
4202
4203                case MSG_SET_DEVICE_VOLUME:
4204                    setDeviceVolume((VolumeStreamState) msg.obj, msg.arg1);
4205                    break;
4206
4207                case MSG_SET_ALL_VOLUMES:
4208                    setAllVolumes((VolumeStreamState) msg.obj);
4209                    break;
4210
4211                case MSG_PERSIST_VOLUME:
4212                    persistVolume((VolumeStreamState) msg.obj, msg.arg1);
4213                    break;
4214
4215                case MSG_PERSIST_MASTER_VOLUME:
4216                    if (mUseFixedVolume) {
4217                        return;
4218                    }
4219                    Settings.System.putFloatForUser(mContentResolver,
4220                                                    Settings.System.VOLUME_MASTER,
4221                                                    msg.arg1 / (float)1000.0,
4222                                                    UserHandle.USER_CURRENT);
4223                    break;
4224
4225                case MSG_PERSIST_MASTER_VOLUME_MUTE:
4226                    if (mUseFixedVolume) {
4227                        return;
4228                    }
4229                    Settings.System.putIntForUser(mContentResolver,
4230                                                 Settings.System.VOLUME_MASTER_MUTE,
4231                                                 msg.arg1,
4232                                                 msg.arg2);
4233                    break;
4234
4235                case MSG_PERSIST_RINGER_MODE:
4236                    // note that the value persisted is the current ringer mode, not the
4237                    // value of ringer mode as of the time the request was made to persist
4238                    persistRingerMode(getRingerModeInternal());
4239                    break;
4240
4241                case MSG_MEDIA_SERVER_DIED:
4242                    if (!mSystemReady ||
4243                            (AudioSystem.checkAudioFlinger() != AudioSystem.AUDIO_STATUS_OK)) {
4244                        Log.e(TAG, "Media server died.");
4245                        sendMsg(mAudioHandler, MSG_MEDIA_SERVER_DIED, SENDMSG_NOOP, 0, 0,
4246                                null, 500);
4247                        break;
4248                    }
4249                    Log.e(TAG, "Media server started.");
4250
4251                    // indicate to audio HAL that we start the reconfiguration phase after a media
4252                    // server crash
4253                    // Note that we only execute this when the media server
4254                    // process restarts after a crash, not the first time it is started.
4255                    AudioSystem.setParameters("restarting=true");
4256
4257                    readAndSetLowRamDevice();
4258
4259                    // Restore device connection states
4260                    synchronized (mConnectedDevices) {
4261                        Set set = mConnectedDevices.entrySet();
4262                        Iterator i = set.iterator();
4263                        while (i.hasNext()) {
4264                            Map.Entry device = (Map.Entry)i.next();
4265                            AudioSystem.setDeviceConnectionState(
4266                                                            ((Integer)device.getKey()).intValue(),
4267                                                            AudioSystem.DEVICE_STATE_AVAILABLE,
4268                                                            (String)device.getValue());
4269                        }
4270                    }
4271                    // Restore call state
4272                    AudioSystem.setPhoneState(mMode);
4273
4274                    // Restore forced usage for communcations and record
4275                    AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm);
4276                    AudioSystem.setForceUse(AudioSystem.FOR_RECORD, mForcedUseForComm);
4277                    AudioSystem.setForceUse(AudioSystem.FOR_SYSTEM, mCameraSoundForced ?
4278                                    AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE);
4279
4280                    // Restore stream volumes
4281                    int numStreamTypes = AudioSystem.getNumStreamTypes();
4282                    for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
4283                        VolumeStreamState streamState = mStreamStates[streamType];
4284                        AudioSystem.initStreamVolume(streamType, 0, (streamState.mIndexMax + 5) / 10);
4285
4286                        streamState.applyAllVolumes();
4287                    }
4288
4289                    // Restore ringer mode
4290                    setRingerModeInt(getRingerModeInternal(), false);
4291
4292                    // Restore master volume
4293                    restoreMasterVolume();
4294
4295                    // Reset device orientation (if monitored for this device)
4296                    if (mMonitorOrientation) {
4297                        setOrientationForAudioSystem();
4298                    }
4299                    if (mMonitorRotation) {
4300                        setRotationForAudioSystem();
4301                    }
4302
4303                    synchronized (mBluetoothA2dpEnabledLock) {
4304                        AudioSystem.setForceUse(AudioSystem.FOR_MEDIA,
4305                                mBluetoothA2dpEnabled ?
4306                                        AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP);
4307                    }
4308
4309                    synchronized (mSettingsLock) {
4310                        AudioSystem.setForceUse(AudioSystem.FOR_DOCK,
4311                                mDockAudioMediaEnabled ?
4312                                        AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE);
4313                    }
4314                    if (mHdmiManager != null) {
4315                        synchronized (mHdmiManager) {
4316                            if (mHdmiTvClient != null) {
4317                                setHdmiSystemAudioSupported(mHdmiSystemAudioSupported);
4318                            }
4319                        }
4320                    }
4321
4322                    synchronized (mAudioPolicies) {
4323                        for(AudioPolicyProxy policy : mAudioPolicies.values()) {
4324                            policy.connectMixes();
4325                        }
4326                    }
4327
4328                    // indicate the end of reconfiguration phase to audio HAL
4329                    AudioSystem.setParameters("restarting=false");
4330                    break;
4331
4332                case MSG_UNLOAD_SOUND_EFFECTS:
4333                    onUnloadSoundEffects();
4334                    break;
4335
4336                case MSG_LOAD_SOUND_EFFECTS:
4337                    //FIXME: onLoadSoundEffects() should be executed in a separate thread as it
4338                    // can take several dozens of milliseconds to complete
4339                    boolean loaded = onLoadSoundEffects();
4340                    if (msg.obj != null) {
4341                        LoadSoundEffectReply reply = (LoadSoundEffectReply)msg.obj;
4342                        synchronized (reply) {
4343                            reply.mStatus = loaded ? 0 : -1;
4344                            reply.notify();
4345                        }
4346                    }
4347                    break;
4348
4349                case MSG_PLAY_SOUND_EFFECT:
4350                    onPlaySoundEffect(msg.arg1, msg.arg2);
4351                    break;
4352
4353                case MSG_BTA2DP_DOCK_TIMEOUT:
4354                    // msg.obj  == address of BTA2DP device
4355                    synchronized (mConnectedDevices) {
4356                        makeA2dpDeviceUnavailableNow( (String) msg.obj );
4357                    }
4358                    break;
4359
4360                case MSG_SET_FORCE_USE:
4361                case MSG_SET_FORCE_BT_A2DP_USE:
4362                    setForceUse(msg.arg1, msg.arg2);
4363                    break;
4364
4365                case MSG_BT_HEADSET_CNCT_FAILED:
4366                    resetBluetoothSco();
4367                    break;
4368
4369                case MSG_SET_WIRED_DEVICE_CONNECTION_STATE:
4370                    onSetWiredDeviceConnectionState(msg.arg1, msg.arg2, (String)msg.obj);
4371                    mAudioEventWakeLock.release();
4372                    break;
4373
4374                case MSG_SET_A2DP_SRC_CONNECTION_STATE:
4375                    onSetA2dpSourceConnectionState((BluetoothDevice)msg.obj, msg.arg1);
4376                    mAudioEventWakeLock.release();
4377                    break;
4378
4379                case MSG_SET_A2DP_SINK_CONNECTION_STATE:
4380                    onSetA2dpSinkConnectionState((BluetoothDevice)msg.obj, msg.arg1);
4381                    mAudioEventWakeLock.release();
4382                    break;
4383
4384                case MSG_REPORT_NEW_ROUTES: {
4385                    int N = mRoutesObservers.beginBroadcast();
4386                    if (N > 0) {
4387                        AudioRoutesInfo routes;
4388                        synchronized (mCurAudioRoutes) {
4389                            routes = new AudioRoutesInfo(mCurAudioRoutes);
4390                        }
4391                        while (N > 0) {
4392                            N--;
4393                            IAudioRoutesObserver obs = mRoutesObservers.getBroadcastItem(N);
4394                            try {
4395                                obs.dispatchAudioRoutesChanged(routes);
4396                            } catch (RemoteException e) {
4397                            }
4398                        }
4399                    }
4400                    mRoutesObservers.finishBroadcast();
4401                    break;
4402                }
4403
4404                case MSG_CHECK_MUSIC_ACTIVE:
4405                    onCheckMusicActive();
4406                    break;
4407
4408                case MSG_BROADCAST_AUDIO_BECOMING_NOISY:
4409                    onSendBecomingNoisyIntent();
4410                    break;
4411
4412                case MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED:
4413                case MSG_CONFIGURE_SAFE_MEDIA_VOLUME:
4414                    onConfigureSafeVolume((msg.what == MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED));
4415                    break;
4416                case MSG_PERSIST_SAFE_VOLUME_STATE:
4417                    onPersistSafeVolumeState(msg.arg1);
4418                    break;
4419
4420                case MSG_BROADCAST_BT_CONNECTION_STATE:
4421                    onBroadcastScoConnectionState(msg.arg1);
4422                    break;
4423
4424                case MSG_SYSTEM_READY:
4425                    onSystemReady();
4426                    break;
4427
4428                case MSG_PERSIST_MUSIC_ACTIVE_MS:
4429                    final int musicActiveMs = msg.arg1;
4430                    Settings.Secure.putIntForUser(mContentResolver,
4431                            Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS, musicActiveMs,
4432                            UserHandle.USER_CURRENT);
4433                    break;
4434                case MSG_PERSIST_MICROPHONE_MUTE:
4435                    Settings.System.putIntForUser(mContentResolver,
4436                                                 Settings.System.MICROPHONE_MUTE,
4437                                                 msg.arg1,
4438                                                 msg.arg2);
4439                    break;
4440            }
4441        }
4442    }
4443
4444    private class SettingsObserver extends ContentObserver {
4445
4446        SettingsObserver() {
4447            super(new Handler());
4448            mContentResolver.registerContentObserver(Settings.System.getUriFor(
4449                Settings.System.MODE_RINGER_STREAMS_AFFECTED), false, this);
4450            mContentResolver.registerContentObserver(Settings.Global.getUriFor(
4451                Settings.Global.DOCK_AUDIO_MEDIA_ENABLED), false, this);
4452        }
4453
4454        @Override
4455        public void onChange(boolean selfChange) {
4456            super.onChange(selfChange);
4457            // FIXME This synchronized is not necessary if mSettingsLock only protects mRingerMode.
4458            //       However there appear to be some missing locks around mRingerModeMutedStreams
4459            //       and mRingerModeAffectedStreams, so will leave this synchronized for now.
4460            //       mRingerModeMutedStreams and mMuteAffectedStreams are safe (only accessed once).
4461            synchronized (mSettingsLock) {
4462                if (updateRingerModeAffectedStreams()) {
4463                    /*
4464                     * Ensure all stream types that should be affected by ringer mode
4465                     * are in the proper state.
4466                     */
4467                    setRingerModeInt(getRingerModeInternal(), false);
4468                }
4469                readDockAudioSettings(mContentResolver);
4470            }
4471        }
4472    }
4473
4474    // must be called synchronized on mConnectedDevices
4475    private void makeA2dpDeviceAvailable(String address) {
4476        // enable A2DP before notifying A2DP connection to avoid unecessary processing in
4477        // audio policy manager
4478        VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC];
4479        sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE,
4480                AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0, streamState, 0);
4481        setBluetoothA2dpOnInt(true);
4482        AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
4483                AudioSystem.DEVICE_STATE_AVAILABLE,
4484                address);
4485        // Reset A2DP suspend state each time a new sink is connected
4486        AudioSystem.setParameters("A2dpSuspended=false");
4487        mConnectedDevices.put( new Integer(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP),
4488                address);
4489    }
4490
4491    private void onSendBecomingNoisyIntent() {
4492        sendBroadcastToAll(new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY));
4493    }
4494
4495    // must be called synchronized on mConnectedDevices
4496    private void makeA2dpDeviceUnavailableNow(String address) {
4497        synchronized (mA2dpAvrcpLock) {
4498            mAvrcpAbsVolSupported = false;
4499        }
4500        AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
4501                AudioSystem.DEVICE_STATE_UNAVAILABLE,
4502                address);
4503        mConnectedDevices.remove(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
4504        synchronized (mCurAudioRoutes) {
4505            // Remove A2DP routes as well
4506            if (mCurAudioRoutes.mBluetoothName != null) {
4507                mCurAudioRoutes.mBluetoothName = null;
4508                sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES,
4509                        SENDMSG_NOOP, 0, 0, null, 0);
4510            }
4511        }
4512    }
4513
4514    // must be called synchronized on mConnectedDevices
4515    private void makeA2dpDeviceUnavailableLater(String address) {
4516        // prevent any activity on the A2DP audio output to avoid unwanted
4517        // reconnection of the sink.
4518        AudioSystem.setParameters("A2dpSuspended=true");
4519        // the device will be made unavailable later, so consider it disconnected right away
4520        mConnectedDevices.remove(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
4521        // send the delayed message to make the device unavailable later
4522        Message msg = mAudioHandler.obtainMessage(MSG_BTA2DP_DOCK_TIMEOUT, address);
4523        mAudioHandler.sendMessageDelayed(msg, BTA2DP_DOCK_TIMEOUT_MILLIS);
4524
4525    }
4526
4527    // must be called synchronized on mConnectedDevices
4528    private void makeA2dpSrcAvailable(String address) {
4529        AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP,
4530                AudioSystem.DEVICE_STATE_AVAILABLE,
4531                address);
4532        mConnectedDevices.put( new Integer(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP),
4533                address);
4534    }
4535
4536    // must be called synchronized on mConnectedDevices
4537    private void makeA2dpSrcUnavailable(String address) {
4538        AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP,
4539                AudioSystem.DEVICE_STATE_UNAVAILABLE,
4540                address);
4541        mConnectedDevices.remove(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP);
4542    }
4543
4544    // must be called synchronized on mConnectedDevices
4545    private void cancelA2dpDeviceTimeout() {
4546        mAudioHandler.removeMessages(MSG_BTA2DP_DOCK_TIMEOUT);
4547    }
4548
4549    // must be called synchronized on mConnectedDevices
4550    private boolean hasScheduledA2dpDockTimeout() {
4551        return mAudioHandler.hasMessages(MSG_BTA2DP_DOCK_TIMEOUT);
4552    }
4553
4554    private void onSetA2dpSinkConnectionState(BluetoothDevice btDevice, int state)
4555    {
4556        if (DEBUG_VOL) {
4557            Log.d(TAG, "onSetA2dpSinkConnectionState btDevice="+btDevice+"state="+state);
4558        }
4559        if (btDevice == null) {
4560            return;
4561        }
4562        String address = btDevice.getAddress();
4563        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
4564            address = "";
4565        }
4566
4567        synchronized (mConnectedDevices) {
4568            boolean isConnected =
4569                (mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) &&
4570                 mConnectedDevices.get(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP).equals(address));
4571
4572            if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
4573                if (btDevice.isBluetoothDock()) {
4574                    if (state == BluetoothProfile.STATE_DISCONNECTED) {
4575                        // introduction of a delay for transient disconnections of docks when
4576                        // power is rapidly turned off/on, this message will be canceled if
4577                        // we reconnect the dock under a preset delay
4578                        makeA2dpDeviceUnavailableLater(address);
4579                        // the next time isConnected is evaluated, it will be false for the dock
4580                    }
4581                } else {
4582                    makeA2dpDeviceUnavailableNow(address);
4583                }
4584                synchronized (mCurAudioRoutes) {
4585                    if (mCurAudioRoutes.mBluetoothName != null) {
4586                        mCurAudioRoutes.mBluetoothName = null;
4587                        sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES,
4588                                SENDMSG_NOOP, 0, 0, null, 0);
4589                    }
4590                }
4591            } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
4592                if (btDevice.isBluetoothDock()) {
4593                    // this could be a reconnection after a transient disconnection
4594                    cancelA2dpDeviceTimeout();
4595                    mDockAddress = address;
4596                } else {
4597                    // this could be a connection of another A2DP device before the timeout of
4598                    // a dock: cancel the dock timeout, and make the dock unavailable now
4599                    if(hasScheduledA2dpDockTimeout()) {
4600                        cancelA2dpDeviceTimeout();
4601                        makeA2dpDeviceUnavailableNow(mDockAddress);
4602                    }
4603                }
4604                makeA2dpDeviceAvailable(address);
4605                synchronized (mCurAudioRoutes) {
4606                    String name = btDevice.getAliasName();
4607                    if (!TextUtils.equals(mCurAudioRoutes.mBluetoothName, name)) {
4608                        mCurAudioRoutes.mBluetoothName = name;
4609                        sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES,
4610                                SENDMSG_NOOP, 0, 0, null, 0);
4611                    }
4612                }
4613            }
4614        }
4615    }
4616
4617    private void onSetA2dpSourceConnectionState(BluetoothDevice btDevice, int state)
4618    {
4619        if (DEBUG_VOL) {
4620            Log.d(TAG, "onSetA2dpSourceConnectionState btDevice="+btDevice+" state="+state);
4621        }
4622        if (btDevice == null) {
4623            return;
4624        }
4625        String address = btDevice.getAddress();
4626        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
4627            address = "";
4628        }
4629
4630        synchronized (mConnectedDevices) {
4631                boolean isConnected =
4632                (mConnectedDevices.containsKey(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP) &&
4633                 mConnectedDevices.get(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP).equals(address));
4634
4635            if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
4636                makeA2dpSrcUnavailable(address);
4637            } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
4638                makeA2dpSrcAvailable(address);
4639            }
4640        }
4641    }
4642
4643    public void avrcpSupportsAbsoluteVolume(String address, boolean support) {
4644        // address is not used for now, but may be used when multiple a2dp devices are supported
4645        synchronized (mA2dpAvrcpLock) {
4646            mAvrcpAbsVolSupported = support;
4647            sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE,
4648                    AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0,
4649                    mStreamStates[AudioSystem.STREAM_MUSIC], 0);
4650            sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE,
4651                    AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0,
4652                    mStreamStates[AudioSystem.STREAM_RING], 0);
4653        }
4654    }
4655
4656    private boolean handleDeviceConnection(boolean connected, int device, String params) {
4657        synchronized (mConnectedDevices) {
4658            boolean isConnected = (mConnectedDevices.containsKey(device) &&
4659                    (params.isEmpty() || mConnectedDevices.get(device).equals(params)));
4660
4661            if (isConnected && !connected) {
4662                AudioSystem.setDeviceConnectionState(device,
4663                                              AudioSystem.DEVICE_STATE_UNAVAILABLE,
4664                                              mConnectedDevices.get(device));
4665                 mConnectedDevices.remove(device);
4666                 return true;
4667            } else if (!isConnected && connected) {
4668                 AudioSystem.setDeviceConnectionState(device,
4669                                                      AudioSystem.DEVICE_STATE_AVAILABLE,
4670                                                      params);
4671                 mConnectedDevices.put(new Integer(device), params);
4672                 return true;
4673            }
4674        }
4675        return false;
4676    }
4677
4678    // Devices which removal triggers intent ACTION_AUDIO_BECOMING_NOISY. The intent is only
4679    // sent if none of these devices is connected.
4680    int mBecomingNoisyIntentDevices =
4681            AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE |
4682            AudioSystem.DEVICE_OUT_ALL_A2DP | AudioSystem.DEVICE_OUT_HDMI |
4683            AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET | AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET |
4684            AudioSystem.DEVICE_OUT_ALL_USB | AudioSystem.DEVICE_OUT_LINE;
4685
4686    // must be called before removing the device from mConnectedDevices
4687    private int checkSendBecomingNoisyIntent(int device, int state) {
4688        int delay = 0;
4689        if ((state == 0) && ((device & mBecomingNoisyIntentDevices) != 0)) {
4690            int devices = 0;
4691            for (int dev : mConnectedDevices.keySet()) {
4692                if (((dev & AudioSystem.DEVICE_BIT_IN) == 0) &&
4693                        ((dev & mBecomingNoisyIntentDevices) != 0)) {
4694                   devices |= dev;
4695                }
4696            }
4697            if (devices == device) {
4698                sendMsg(mAudioHandler,
4699                        MSG_BROADCAST_AUDIO_BECOMING_NOISY,
4700                        SENDMSG_REPLACE,
4701                        0,
4702                        0,
4703                        null,
4704                        0);
4705                delay = 1000;
4706            }
4707        }
4708
4709        if (mAudioHandler.hasMessages(MSG_SET_A2DP_SRC_CONNECTION_STATE) ||
4710                mAudioHandler.hasMessages(MSG_SET_A2DP_SINK_CONNECTION_STATE) ||
4711                mAudioHandler.hasMessages(MSG_SET_WIRED_DEVICE_CONNECTION_STATE)) {
4712            synchronized (mLastDeviceConnectMsgTime) {
4713                long time = SystemClock.uptimeMillis();
4714                if (mLastDeviceConnectMsgTime > time) {
4715                    delay = (int)(mLastDeviceConnectMsgTime - time);
4716                }
4717            }
4718        }
4719        return delay;
4720    }
4721
4722    private void sendDeviceConnectionIntent(int device, int state, String name)
4723    {
4724        Intent intent = new Intent();
4725
4726        intent.putExtra("state", state);
4727        intent.putExtra("name", name);
4728        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
4729
4730        int connType = 0;
4731
4732        if (device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) {
4733            connType = AudioRoutesInfo.MAIN_HEADSET;
4734            intent.setAction(Intent.ACTION_HEADSET_PLUG);
4735            intent.putExtra("microphone", 1);
4736        } else if (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE ||
4737                   device == AudioSystem.DEVICE_OUT_LINE) {
4738            /*do apps care about line-out vs headphones?*/
4739            connType = AudioRoutesInfo.MAIN_HEADPHONES;
4740            intent.setAction(Intent.ACTION_HEADSET_PLUG);
4741            intent.putExtra("microphone", 0);
4742        } else if (device == AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET) {
4743            connType = AudioRoutesInfo.MAIN_DOCK_SPEAKERS;
4744            intent.setAction(AudioManager.ACTION_ANALOG_AUDIO_DOCK_PLUG);
4745        } else if (device == AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET) {
4746            connType = AudioRoutesInfo.MAIN_DOCK_SPEAKERS;
4747            intent.setAction(AudioManager.ACTION_DIGITAL_AUDIO_DOCK_PLUG);
4748        } else if (device == AudioSystem.DEVICE_OUT_HDMI) {
4749            connType = AudioRoutesInfo.MAIN_HDMI;
4750            configureHdmiPlugIntent(intent, state);
4751        }
4752
4753        synchronized (mCurAudioRoutes) {
4754            if (connType != 0) {
4755                int newConn = mCurAudioRoutes.mMainType;
4756                if (state != 0) {
4757                    newConn |= connType;
4758                } else {
4759                    newConn &= ~connType;
4760                }
4761                if (newConn != mCurAudioRoutes.mMainType) {
4762                    mCurAudioRoutes.mMainType = newConn;
4763                    sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES,
4764                            SENDMSG_NOOP, 0, 0, null, 0);
4765                }
4766            }
4767        }
4768
4769        final long ident = Binder.clearCallingIdentity();
4770        try {
4771            ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.USER_ALL);
4772        } finally {
4773            Binder.restoreCallingIdentity(ident);
4774        }
4775    }
4776
4777    private void onSetWiredDeviceConnectionState(int device, int state, String name)
4778    {
4779        synchronized (mConnectedDevices) {
4780            if ((state == 0) && ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) ||
4781                    (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE) ||
4782                    (device == AudioSystem.DEVICE_OUT_LINE))) {
4783                setBluetoothA2dpOnInt(true);
4784            }
4785            boolean isUsb = ((device & ~AudioSystem.DEVICE_OUT_ALL_USB) == 0) ||
4786                            (((device & AudioSystem.DEVICE_BIT_IN) != 0) &&
4787                             ((device & ~AudioSystem.DEVICE_IN_ALL_USB) == 0));
4788            handleDeviceConnection((state == 1), device, (isUsb ? name : ""));
4789            if (state != 0) {
4790                if ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) ||
4791                    (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE) ||
4792                    (device == AudioSystem.DEVICE_OUT_LINE)) {
4793                    setBluetoothA2dpOnInt(false);
4794                }
4795                if ((device & mSafeMediaVolumeDevices) != 0) {
4796                    sendMsg(mAudioHandler,
4797                            MSG_CHECK_MUSIC_ACTIVE,
4798                            SENDMSG_REPLACE,
4799                            0,
4800                            0,
4801                            null,
4802                            MUSIC_ACTIVE_POLL_PERIOD_MS);
4803                }
4804                // Television devices without CEC service apply software volume on HDMI output
4805                if (isPlatformTelevision() && ((device & AudioSystem.DEVICE_OUT_HDMI) != 0)) {
4806                    mFixedVolumeDevices |= AudioSystem.DEVICE_OUT_HDMI;
4807                    checkAllFixedVolumeDevices();
4808                    if (mHdmiManager != null) {
4809                        synchronized (mHdmiManager) {
4810                            if (mHdmiPlaybackClient != null) {
4811                                mHdmiCecSink = false;
4812                                mHdmiPlaybackClient.queryDisplayStatus(mHdmiDisplayStatusCallback);
4813                            }
4814                        }
4815                    }
4816                }
4817            } else {
4818                if (isPlatformTelevision() && ((device & AudioSystem.DEVICE_OUT_HDMI) != 0)) {
4819                    if (mHdmiManager != null) {
4820                        synchronized (mHdmiManager) {
4821                            mHdmiCecSink = false;
4822                        }
4823                    }
4824                }
4825            }
4826            if (!isUsb && (device != AudioSystem.DEVICE_IN_WIRED_HEADSET)) {
4827                sendDeviceConnectionIntent(device, state, name);
4828            }
4829        }
4830    }
4831
4832    private void configureHdmiPlugIntent(Intent intent, int state) {
4833        intent.setAction(AudioManager.ACTION_HDMI_AUDIO_PLUG);
4834        intent.putExtra(AudioManager.EXTRA_AUDIO_PLUG_STATE, state);
4835        if (state == 1) {
4836            ArrayList<AudioPort> ports = new ArrayList<AudioPort>();
4837            int[] portGeneration = new int[1];
4838            int status = AudioSystem.listAudioPorts(ports, portGeneration);
4839            if (status == AudioManager.SUCCESS) {
4840                for (AudioPort port : ports) {
4841                    if (port instanceof AudioDevicePort) {
4842                        final AudioDevicePort devicePort = (AudioDevicePort) port;
4843                        if (devicePort.type() == AudioManager.DEVICE_OUT_HDMI) {
4844                            // format the list of supported encodings
4845                            int[] formats = devicePort.formats();
4846                            if (formats.length > 0) {
4847                                ArrayList<Integer> encodingList = new ArrayList(1);
4848                                for (int format : formats) {
4849                                    // a format in the list can be 0, skip it
4850                                    if (format != AudioFormat.ENCODING_INVALID) {
4851                                        encodingList.add(format);
4852                                    }
4853                                }
4854                                int[] encodingArray = new int[encodingList.size()];
4855                                for (int i = 0 ; i < encodingArray.length ; i++) {
4856                                    encodingArray[i] = encodingList.get(i);
4857                                }
4858                                intent.putExtra(AudioManager.EXTRA_ENCODINGS, encodingArray);
4859                            }
4860                            // find the maximum supported number of channels
4861                            int maxChannels = 0;
4862                            for (int mask : devicePort.channelMasks()) {
4863                                int channelCount = AudioFormat.channelCountFromOutChannelMask(mask);
4864                                if (channelCount > maxChannels) {
4865                                    maxChannels = channelCount;
4866                                }
4867                            }
4868                            intent.putExtra(AudioManager.EXTRA_MAX_CHANNEL_COUNT, maxChannels);
4869                        }
4870                    }
4871                }
4872            }
4873        }
4874    }
4875
4876    /* cache of the address of the last dock the device was connected to */
4877    private String mDockAddress;
4878
4879    /**
4880     * Receiver for misc intent broadcasts the Phone app cares about.
4881     */
4882    private class AudioServiceBroadcastReceiver extends BroadcastReceiver {
4883        @Override
4884        public void onReceive(Context context, Intent intent) {
4885            String action = intent.getAction();
4886            int outDevice;
4887            int inDevice;
4888            int state;
4889
4890            if (action.equals(Intent.ACTION_DOCK_EVENT)) {
4891                int dockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
4892                        Intent.EXTRA_DOCK_STATE_UNDOCKED);
4893                int config;
4894                switch (dockState) {
4895                    case Intent.EXTRA_DOCK_STATE_DESK:
4896                        config = AudioSystem.FORCE_BT_DESK_DOCK;
4897                        break;
4898                    case Intent.EXTRA_DOCK_STATE_CAR:
4899                        config = AudioSystem.FORCE_BT_CAR_DOCK;
4900                        break;
4901                    case Intent.EXTRA_DOCK_STATE_LE_DESK:
4902                        config = AudioSystem.FORCE_ANALOG_DOCK;
4903                        break;
4904                    case Intent.EXTRA_DOCK_STATE_HE_DESK:
4905                        config = AudioSystem.FORCE_DIGITAL_DOCK;
4906                        break;
4907                    case Intent.EXTRA_DOCK_STATE_UNDOCKED:
4908                    default:
4909                        config = AudioSystem.FORCE_NONE;
4910                }
4911                // Low end docks have a menu to enable or disable audio
4912                // (see mDockAudioMediaEnabled)
4913                if (!((dockState == Intent.EXTRA_DOCK_STATE_LE_DESK) ||
4914                      ((dockState == Intent.EXTRA_DOCK_STATE_UNDOCKED) &&
4915                       (mDockState == Intent.EXTRA_DOCK_STATE_LE_DESK)))) {
4916                    AudioSystem.setForceUse(AudioSystem.FOR_DOCK, config);
4917                }
4918                mDockState = dockState;
4919            } else if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) {
4920                state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE,
4921                                               BluetoothProfile.STATE_DISCONNECTED);
4922                outDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO;
4923                inDevice = AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET;
4924                String address = null;
4925
4926                BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
4927                if (btDevice == null) {
4928                    return;
4929                }
4930
4931                address = btDevice.getAddress();
4932                BluetoothClass btClass = btDevice.getBluetoothClass();
4933                if (btClass != null) {
4934                    switch (btClass.getDeviceClass()) {
4935                    case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET:
4936                    case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE:
4937                        outDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
4938                        break;
4939                    case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO:
4940                        outDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
4941                        break;
4942                    }
4943                }
4944
4945                if (!BluetoothAdapter.checkBluetoothAddress(address)) {
4946                    address = "";
4947                }
4948
4949                boolean connected = (state == BluetoothProfile.STATE_CONNECTED);
4950                boolean success = handleDeviceConnection(connected, outDevice, address) &&
4951                                      handleDeviceConnection(connected, inDevice, address);
4952                if (success) {
4953                    synchronized (mScoClients) {
4954                        if (connected) {
4955                            mBluetoothHeadsetDevice = btDevice;
4956                        } else {
4957                            mBluetoothHeadsetDevice = null;
4958                            resetBluetoothSco();
4959                        }
4960                    }
4961                }
4962            } else if (action.equals(AudioManager.ACTION_USB_AUDIO_ACCESSORY_PLUG)) {
4963                state = intent.getIntExtra("state", 0);
4964
4965                int alsaCard = intent.getIntExtra("card", -1);
4966                int alsaDevice = intent.getIntExtra("device", -1);
4967
4968                String params = (alsaCard == -1 && alsaDevice == -1 ? ""
4969                                    : "card=" + alsaCard + ";device=" + alsaDevice);
4970
4971                // Playback Device
4972                outDevice = AudioSystem.DEVICE_OUT_USB_ACCESSORY;
4973                setWiredDeviceConnectionState(outDevice, state, params);
4974            } else if (action.equals(AudioManager.ACTION_USB_AUDIO_DEVICE_PLUG)) {
4975                // FIXME Does not yet handle the case where the setting is changed
4976                // after device connection.  Ideally we should handle the settings change
4977                // in SettingsObserver. Here we should log that a USB device is connected
4978                // and disconnected with its address (card , device) and force the
4979                // connection or disconnection when the setting changes.
4980                int isDisabled = Settings.Secure.getInt(mContentResolver,
4981                        Settings.Secure.USB_AUDIO_AUTOMATIC_ROUTING_DISABLED, 0);
4982                if (isDisabled != 0) {
4983                    return;
4984                }
4985
4986                state = intent.getIntExtra("state", 0);
4987
4988                int alsaCard = intent.getIntExtra("card", -1);
4989                int alsaDevice = intent.getIntExtra("device", -1);
4990                boolean hasPlayback = intent.getBooleanExtra("hasPlayback", false);
4991                boolean hasCapture = intent.getBooleanExtra("hasCapture", false);
4992                boolean hasMIDI = intent.getBooleanExtra("hasMIDI", false);
4993
4994                String params = (alsaCard == -1 && alsaDevice == -1 ? ""
4995                                    : "card=" + alsaCard + ";device=" + alsaDevice);
4996
4997                // Playback Device
4998                if (hasPlayback) {
4999                    outDevice = AudioSystem.DEVICE_OUT_USB_DEVICE;
5000                    setWiredDeviceConnectionState(outDevice, state, params);
5001                }
5002
5003                // Capture Device
5004                if (hasCapture) {
5005                    inDevice = AudioSystem.DEVICE_IN_USB_DEVICE;
5006                    setWiredDeviceConnectionState(inDevice, state, params);
5007                }
5008            } else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
5009                boolean broadcast = false;
5010                int scoAudioState = AudioManager.SCO_AUDIO_STATE_ERROR;
5011                synchronized (mScoClients) {
5012                    int btState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
5013                    // broadcast intent if the connection was initated by AudioService
5014                    if (!mScoClients.isEmpty() &&
5015                            (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL ||
5016                             mScoAudioState == SCO_STATE_ACTIVATE_REQ ||
5017                             mScoAudioState == SCO_STATE_DEACTIVATE_REQ)) {
5018                        broadcast = true;
5019                    }
5020                    switch (btState) {
5021                    case BluetoothHeadset.STATE_AUDIO_CONNECTED:
5022                        scoAudioState = AudioManager.SCO_AUDIO_STATE_CONNECTED;
5023                        if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL &&
5024                            mScoAudioState != SCO_STATE_DEACTIVATE_REQ &&
5025                            mScoAudioState != SCO_STATE_DEACTIVATE_EXT_REQ) {
5026                            mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL;
5027                        }
5028                        break;
5029                    case BluetoothHeadset.STATE_AUDIO_DISCONNECTED:
5030                        scoAudioState = AudioManager.SCO_AUDIO_STATE_DISCONNECTED;
5031                        mScoAudioState = SCO_STATE_INACTIVE;
5032                        clearAllScoClients(0, false);
5033                        break;
5034                    case BluetoothHeadset.STATE_AUDIO_CONNECTING:
5035                        if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL &&
5036                            mScoAudioState != SCO_STATE_DEACTIVATE_REQ &&
5037                            mScoAudioState != SCO_STATE_DEACTIVATE_EXT_REQ) {
5038                            mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL;
5039                        }
5040                    default:
5041                        // do not broadcast CONNECTING or invalid state
5042                        broadcast = false;
5043                        break;
5044                    }
5045                }
5046                if (broadcast) {
5047                    broadcastScoConnectionState(scoAudioState);
5048                    //FIXME: this is to maintain compatibility with deprecated intent
5049                    // AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. Remove when appropriate.
5050                    Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED);
5051                    newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, scoAudioState);
5052                    sendStickyBroadcastToAll(newIntent);
5053                }
5054            } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
5055                if (mMonitorRotation) {
5056                    mOrientationListener.onOrientationChanged(0); //argument is ignored anyway
5057                    mOrientationListener.enable();
5058                }
5059                AudioSystem.setParameters("screen_state=on");
5060            } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
5061                if (mMonitorRotation) {
5062                    //reduce wakeups (save current) by only listening when display is on
5063                    mOrientationListener.disable();
5064                }
5065                AudioSystem.setParameters("screen_state=off");
5066            } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
5067                handleConfigurationChanged(context);
5068            } else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
5069                // attempt to stop music playback for background user
5070                sendMsg(mAudioHandler,
5071                        MSG_BROADCAST_AUDIO_BECOMING_NOISY,
5072                        SENDMSG_REPLACE,
5073                        0,
5074                        0,
5075                        null,
5076                        0);
5077                // the current audio focus owner is no longer valid
5078                mMediaFocusControl.discardAudioFocusOwner();
5079
5080                // load volume settings for new user
5081                readAudioSettings(true /*userSwitch*/);
5082                // preserve STREAM_MUSIC volume from one user to the next.
5083                sendMsg(mAudioHandler,
5084                        MSG_SET_ALL_VOLUMES,
5085                        SENDMSG_QUEUE,
5086                        0,
5087                        0,
5088                        mStreamStates[AudioSystem.STREAM_MUSIC], 0);
5089            }
5090        }
5091    } // end class AudioServiceBroadcastReceiver
5092
5093    //==========================================================================================
5094    // RemoteControlDisplay / RemoteControlClient / Remote info
5095    //==========================================================================================
5096    public boolean registerRemoteController(IRemoteControlDisplay rcd, int w, int h,
5097            ComponentName listenerComp) {
5098        return mMediaFocusControl.registerRemoteController(rcd, w, h, listenerComp);
5099    }
5100
5101    public boolean registerRemoteControlDisplay(IRemoteControlDisplay rcd, int w, int h) {
5102        return mMediaFocusControl.registerRemoteControlDisplay(rcd, w, h);
5103    }
5104
5105    public void unregisterRemoteControlDisplay(IRemoteControlDisplay rcd) {
5106        mMediaFocusControl.unregisterRemoteControlDisplay(rcd);
5107    }
5108
5109    public void remoteControlDisplayUsesBitmapSize(IRemoteControlDisplay rcd, int w, int h) {
5110        mMediaFocusControl.remoteControlDisplayUsesBitmapSize(rcd, w, h);
5111    }
5112
5113    public void remoteControlDisplayWantsPlaybackPositionSync(IRemoteControlDisplay rcd,
5114            boolean wantsSync) {
5115        mMediaFocusControl.remoteControlDisplayWantsPlaybackPositionSync(rcd, wantsSync);
5116    }
5117
5118    @Override
5119    public void setRemoteStreamVolume(int index) {
5120        enforceSelfOrSystemUI("set the remote stream volume");
5121        mMediaFocusControl.setRemoteStreamVolume(index);
5122    }
5123
5124    //==========================================================================================
5125    // Audio Focus
5126    //==========================================================================================
5127    public int requestAudioFocus(AudioAttributes aa, int durationHint, IBinder cb,
5128            IAudioFocusDispatcher fd, String clientId, String callingPackageName, int flags,
5129            IAudioPolicyCallback pcb) {
5130        // permission checks
5131        if ((flags & AudioManager.AUDIOFOCUS_FLAG_LOCK) == AudioManager.AUDIOFOCUS_FLAG_LOCK) {
5132            if (mMediaFocusControl.IN_VOICE_COMM_FOCUS_ID.equals(clientId)) {
5133                if (PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission(
5134                            android.Manifest.permission.MODIFY_PHONE_STATE)) {
5135                    Log.e(TAG, "Invalid permission to (un)lock audio focus", new Exception());
5136                    return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
5137                }
5138            } else {
5139                // only a registered audio policy can be used to lock focus
5140                synchronized (mAudioPolicies) {
5141                    if (!mAudioPolicies.containsKey(pcb.asBinder())) {
5142                        Log.e(TAG, "Invalid unregistered AudioPolicy to (un)lock audio focus");
5143                        return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
5144                    }
5145                }
5146            }
5147        }
5148
5149        return mMediaFocusControl.requestAudioFocus(aa, durationHint, cb, fd,
5150                clientId, callingPackageName, flags);
5151    }
5152
5153    public int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId, AudioAttributes aa) {
5154        return mMediaFocusControl.abandonAudioFocus(fd, clientId, aa);
5155    }
5156
5157    public void unregisterAudioFocusClient(String clientId) {
5158        mMediaFocusControl.unregisterAudioFocusClient(clientId);
5159    }
5160
5161    public int getCurrentAudioFocus() {
5162        return mMediaFocusControl.getCurrentAudioFocus();
5163    }
5164
5165    //==========================================================================================
5166    // Device orientation
5167    //==========================================================================================
5168    /**
5169     * Handles device configuration changes that may map to a change in the orientation
5170     * or orientation.
5171     * Monitoring orientation and rotation is optional, and is defined by the definition and value
5172     * of the "ro.audio.monitorOrientation" and "ro.audio.monitorRotation" system properties.
5173     */
5174    private void handleConfigurationChanged(Context context) {
5175        try {
5176            // reading new orientation "safely" (i.e. under try catch) in case anything
5177            // goes wrong when obtaining resources and configuration
5178            Configuration config = context.getResources().getConfiguration();
5179            // TODO merge rotation and orientation
5180            if (mMonitorOrientation) {
5181                int newOrientation = config.orientation;
5182                if (newOrientation != mDeviceOrientation) {
5183                    mDeviceOrientation = newOrientation;
5184                    setOrientationForAudioSystem();
5185                }
5186            }
5187            sendMsg(mAudioHandler,
5188                    MSG_CONFIGURE_SAFE_MEDIA_VOLUME,
5189                    SENDMSG_REPLACE,
5190                    0,
5191                    0,
5192                    null,
5193                    0);
5194
5195            boolean cameraSoundForced = mContext.getResources().getBoolean(
5196                    com.android.internal.R.bool.config_camera_sound_forced);
5197            synchronized (mSettingsLock) {
5198                boolean cameraSoundForcedChanged = false;
5199                synchronized (mCameraSoundForced) {
5200                    if (cameraSoundForced != mCameraSoundForced) {
5201                        mCameraSoundForced = cameraSoundForced;
5202                        cameraSoundForcedChanged = true;
5203                    }
5204                }
5205                if (cameraSoundForcedChanged) {
5206                    if (!isPlatformTelevision()) {
5207                        VolumeStreamState s = mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED];
5208                        if (cameraSoundForced) {
5209                            s.setAllIndexesToMax();
5210                            mRingerModeAffectedStreams &=
5211                                    ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
5212                        } else {
5213                            s.setAllIndexes(mStreamStates[AudioSystem.STREAM_SYSTEM]);
5214                            mRingerModeAffectedStreams |=
5215                                    (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
5216                        }
5217                        // take new state into account for streams muted by ringer mode
5218                        setRingerModeInt(getRingerModeInternal(), false);
5219                    }
5220
5221                    sendMsg(mAudioHandler,
5222                            MSG_SET_FORCE_USE,
5223                            SENDMSG_QUEUE,
5224                            AudioSystem.FOR_SYSTEM,
5225                            cameraSoundForced ?
5226                                    AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE,
5227                            null,
5228                            0);
5229
5230                    sendMsg(mAudioHandler,
5231                            MSG_SET_ALL_VOLUMES,
5232                            SENDMSG_QUEUE,
5233                            0,
5234                            0,
5235                            mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED], 0);
5236                }
5237            }
5238            mVolumeController.setLayoutDirection(config.getLayoutDirection());
5239        } catch (Exception e) {
5240            Log.e(TAG, "Error handling configuration change: ", e);
5241        }
5242    }
5243
5244    private void setOrientationForAudioSystem() {
5245        switch (mDeviceOrientation) {
5246            case Configuration.ORIENTATION_LANDSCAPE:
5247                //Log.i(TAG, "orientation is landscape");
5248                AudioSystem.setParameters("orientation=landscape");
5249                break;
5250            case Configuration.ORIENTATION_PORTRAIT:
5251                //Log.i(TAG, "orientation is portrait");
5252                AudioSystem.setParameters("orientation=portrait");
5253                break;
5254            case Configuration.ORIENTATION_SQUARE:
5255                //Log.i(TAG, "orientation is square");
5256                AudioSystem.setParameters("orientation=square");
5257                break;
5258            case Configuration.ORIENTATION_UNDEFINED:
5259                //Log.i(TAG, "orientation is undefined");
5260                AudioSystem.setParameters("orientation=undefined");
5261                break;
5262            default:
5263                Log.e(TAG, "Unknown orientation");
5264        }
5265    }
5266
5267    private void setRotationForAudioSystem() {
5268        switch (mDeviceRotation) {
5269            case Surface.ROTATION_0:
5270                AudioSystem.setParameters("rotation=0");
5271                break;
5272            case Surface.ROTATION_90:
5273                AudioSystem.setParameters("rotation=90");
5274                break;
5275            case Surface.ROTATION_180:
5276                AudioSystem.setParameters("rotation=180");
5277                break;
5278            case Surface.ROTATION_270:
5279                AudioSystem.setParameters("rotation=270");
5280                break;
5281            default:
5282                Log.e(TAG, "Unknown device rotation");
5283        }
5284    }
5285
5286
5287    // Handles request to override default use of A2DP for media.
5288    public void setBluetoothA2dpOnInt(boolean on) {
5289        synchronized (mBluetoothA2dpEnabledLock) {
5290            mBluetoothA2dpEnabled = on;
5291            mAudioHandler.removeMessages(MSG_SET_FORCE_BT_A2DP_USE);
5292            AudioSystem.setForceUse(AudioSystem.FOR_MEDIA,
5293                    mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP);
5294        }
5295    }
5296
5297    @Override
5298    public void setRingtonePlayer(IRingtonePlayer player) {
5299        mContext.enforceCallingOrSelfPermission(REMOTE_AUDIO_PLAYBACK, null);
5300        mRingtonePlayer = player;
5301    }
5302
5303    @Override
5304    public IRingtonePlayer getRingtonePlayer() {
5305        return mRingtonePlayer;
5306    }
5307
5308    @Override
5309    public AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) {
5310        synchronized (mCurAudioRoutes) {
5311            AudioRoutesInfo routes = new AudioRoutesInfo(mCurAudioRoutes);
5312            mRoutesObservers.register(observer);
5313            return routes;
5314        }
5315    }
5316
5317
5318    //==========================================================================================
5319    // Safe media volume management.
5320    // MUSIC stream volume level is limited when headphones are connected according to safety
5321    // regulation. When the user attempts to raise the volume above the limit, a warning is
5322    // displayed and the user has to acknowlegde before the volume is actually changed.
5323    // The volume index corresponding to the limit is stored in config_safe_media_volume_index
5324    // property. Platforms with a different limit must set this property accordingly in their
5325    // overlay.
5326    //==========================================================================================
5327
5328    // mSafeMediaVolumeState indicates whether the media volume is limited over headphones.
5329    // It is SAFE_MEDIA_VOLUME_NOT_CONFIGURED at boot time until a network service is connected
5330    // or the configure time is elapsed. It is then set to SAFE_MEDIA_VOLUME_ACTIVE or
5331    // SAFE_MEDIA_VOLUME_DISABLED according to country option. If not SAFE_MEDIA_VOLUME_DISABLED, it
5332    // can be set to SAFE_MEDIA_VOLUME_INACTIVE by calling AudioService.disableSafeMediaVolume()
5333    // (when user opts out).
5334    private static final int SAFE_MEDIA_VOLUME_NOT_CONFIGURED = 0;
5335    private static final int SAFE_MEDIA_VOLUME_DISABLED = 1;
5336    private static final int SAFE_MEDIA_VOLUME_INACTIVE = 2;  // confirmed
5337    private static final int SAFE_MEDIA_VOLUME_ACTIVE = 3;  // unconfirmed
5338    private Integer mSafeMediaVolumeState;
5339
5340    private int mMcc = 0;
5341    // mSafeMediaVolumeIndex is the cached value of config_safe_media_volume_index property
5342    private int mSafeMediaVolumeIndex;
5343    // mSafeMediaVolumeDevices lists the devices for which safe media volume is enforced,
5344    private final int mSafeMediaVolumeDevices = AudioSystem.DEVICE_OUT_WIRED_HEADSET |
5345                                                AudioSystem.DEVICE_OUT_WIRED_HEADPHONE;
5346    // mMusicActiveMs is the cumulative time of music activity since safe volume was disabled.
5347    // When this time reaches UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX, the safe media volume is re-enabled
5348    // automatically. mMusicActiveMs is rounded to a multiple of MUSIC_ACTIVE_POLL_PERIOD_MS.
5349    private int mMusicActiveMs;
5350    private static final int UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX = (20 * 3600 * 1000); // 20 hours
5351    private static final int MUSIC_ACTIVE_POLL_PERIOD_MS = 60000;  // 1 minute polling interval
5352    private static final int SAFE_VOLUME_CONFIGURE_TIMEOUT_MS = 30000;  // 30s after boot completed
5353
5354    private void setSafeMediaVolumeEnabled(boolean on) {
5355        synchronized (mSafeMediaVolumeState) {
5356            if ((mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_NOT_CONFIGURED) &&
5357                    (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_DISABLED)) {
5358                if (on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE)) {
5359                    mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE;
5360                    enforceSafeMediaVolume();
5361                } else if (!on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE)) {
5362                    mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE;
5363                    mMusicActiveMs = 1;  // nonzero = confirmed
5364                    saveMusicActiveMs();
5365                    sendMsg(mAudioHandler,
5366                            MSG_CHECK_MUSIC_ACTIVE,
5367                            SENDMSG_REPLACE,
5368                            0,
5369                            0,
5370                            null,
5371                            MUSIC_ACTIVE_POLL_PERIOD_MS);
5372                }
5373            }
5374        }
5375    }
5376
5377    private void enforceSafeMediaVolume() {
5378        VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC];
5379        int devices = mSafeMediaVolumeDevices;
5380        int i = 0;
5381
5382        while (devices != 0) {
5383            int device = 1 << i++;
5384            if ((device & devices) == 0) {
5385                continue;
5386            }
5387            int index = streamState.getIndex(device);
5388            if (index > mSafeMediaVolumeIndex) {
5389                streamState.setIndex(mSafeMediaVolumeIndex, device);
5390                sendMsg(mAudioHandler,
5391                        MSG_SET_DEVICE_VOLUME,
5392                        SENDMSG_QUEUE,
5393                        device,
5394                        0,
5395                        streamState,
5396                        0);
5397            }
5398            devices &= ~device;
5399        }
5400    }
5401
5402    private boolean checkSafeMediaVolume(int streamType, int index, int device) {
5403        synchronized (mSafeMediaVolumeState) {
5404            if ((mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) &&
5405                    (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
5406                    ((device & mSafeMediaVolumeDevices) != 0) &&
5407                    (index > mSafeMediaVolumeIndex)) {
5408                return false;
5409            }
5410            return true;
5411        }
5412    }
5413
5414    @Override
5415    public void disableSafeMediaVolume() {
5416        enforceSelfOrSystemUI("disable the safe media volume");
5417        synchronized (mSafeMediaVolumeState) {
5418            setSafeMediaVolumeEnabled(false);
5419            if (mPendingVolumeCommand != null) {
5420                onSetStreamVolume(mPendingVolumeCommand.mStreamType,
5421                                  mPendingVolumeCommand.mIndex,
5422                                  mPendingVolumeCommand.mFlags,
5423                                  mPendingVolumeCommand.mDevice);
5424                mPendingVolumeCommand = null;
5425            }
5426        }
5427    }
5428
5429    //==========================================================================================
5430    // Hdmi Cec system audio mode.
5431    // If Hdmi Cec's system audio mode is on, audio service should notify volume change
5432    // to HdmiControlService so that audio recevier can handle volume change.
5433    //==========================================================================================
5434
5435    private class MyDisplayStatusCallback implements HdmiPlaybackClient.DisplayStatusCallback {
5436        public void onComplete(int status) {
5437            if (mHdmiManager != null) {
5438                synchronized (mHdmiManager) {
5439                    mHdmiCecSink = (status != HdmiControlManager.POWER_STATUS_UNKNOWN);
5440                    // Television devices without CEC service apply software volume on HDMI output
5441                    if (isPlatformTelevision() && !mHdmiCecSink) {
5442                        mFixedVolumeDevices &= ~AudioSystem.DEVICE_OUT_HDMI;
5443                    }
5444                    checkAllFixedVolumeDevices();
5445                }
5446            }
5447        }
5448    };
5449
5450    // If HDMI-CEC system audio is supported
5451    private boolean mHdmiSystemAudioSupported = false;
5452    // Set only when device is tv.
5453    private HdmiTvClient mHdmiTvClient;
5454    // true if the device has system feature PackageManager.FEATURE_LEANBACK.
5455    // cached HdmiControlManager interface
5456    private HdmiControlManager mHdmiManager;
5457    // Set only when device is a set-top box.
5458    private HdmiPlaybackClient mHdmiPlaybackClient;
5459    // true if we are a set-top box, an HDMI sink is connected and it supports CEC.
5460    private boolean mHdmiCecSink;
5461
5462    private MyDisplayStatusCallback mHdmiDisplayStatusCallback = new MyDisplayStatusCallback();
5463
5464    @Override
5465    public int setHdmiSystemAudioSupported(boolean on) {
5466        int device = AudioSystem.DEVICE_NONE;
5467        if (mHdmiManager != null) {
5468            synchronized (mHdmiManager) {
5469                if (mHdmiTvClient == null) {
5470                    Log.w(TAG, "Only Hdmi-Cec enabled TV device supports system audio mode.");
5471                    return device;
5472                }
5473
5474                synchronized (mHdmiTvClient) {
5475                    if (mHdmiSystemAudioSupported != on) {
5476                        mHdmiSystemAudioSupported = on;
5477                        AudioSystem.setForceUse(AudioSystem.FOR_HDMI_SYSTEM_AUDIO,
5478                                on ? AudioSystem.FORCE_HDMI_SYSTEM_AUDIO_ENFORCED :
5479                                     AudioSystem.FORCE_NONE);
5480                    }
5481                    device = AudioSystem.getDevicesForStream(AudioSystem.STREAM_MUSIC);
5482                }
5483            }
5484        }
5485        return device;
5486    }
5487
5488    @Override
5489    public boolean isHdmiSystemAudioSupported() {
5490        return mHdmiSystemAudioSupported;
5491    }
5492
5493    //==========================================================================================
5494    // Accessibility: taking touch exploration into account for selecting the default
5495    //   stream override timeout when adjusting volume
5496    //==========================================================================================
5497    private static class StreamOverride
5498            implements AccessibilityManager.TouchExplorationStateChangeListener {
5499
5500        // AudioService.getActiveStreamType() will return:
5501        // - STREAM_NOTIFICATION on tablets during this period after a notification stopped
5502        // - STREAM_MUSIC on phones during this period after music or talkback/voice search prompt
5503        // stopped
5504        private static final int DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS = 5000;
5505        private static final int TOUCH_EXPLORE_STREAM_TYPE_OVERRIDE_DELAY_MS = 1000;
5506
5507        static int sDelayMs;
5508
5509        static void init(Context ctxt) {
5510            AccessibilityManager accessibilityManager =
5511                    (AccessibilityManager) ctxt.getSystemService(Context.ACCESSIBILITY_SERVICE);
5512            updateDefaultStreamOverrideDelay(
5513                    accessibilityManager.isTouchExplorationEnabled());
5514            accessibilityManager.addTouchExplorationStateChangeListener(
5515                    new StreamOverride());
5516        }
5517
5518        @Override
5519        public void onTouchExplorationStateChanged(boolean enabled) {
5520            updateDefaultStreamOverrideDelay(enabled);
5521        }
5522
5523        private static void updateDefaultStreamOverrideDelay(boolean touchExploreEnabled) {
5524            if (touchExploreEnabled) {
5525                sDelayMs = TOUCH_EXPLORE_STREAM_TYPE_OVERRIDE_DELAY_MS;
5526            } else {
5527                sDelayMs = DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS;
5528            }
5529            if (DEBUG_VOL) Log.d(TAG, "Touch exploration enabled=" + touchExploreEnabled
5530                    + " stream override delay is now " + sDelayMs + " ms");
5531        }
5532    }
5533
5534    //==========================================================================================
5535    // Camera shutter sound policy.
5536    // config_camera_sound_forced configuration option in config.xml defines if the camera shutter
5537    // sound is forced (sound even if the device is in silent mode) or not. This option is false by
5538    // default and can be overridden by country specific overlay in values-mccXXX/config.xml.
5539    //==========================================================================================
5540
5541    // cached value of com.android.internal.R.bool.config_camera_sound_forced
5542    private Boolean mCameraSoundForced;
5543
5544    // called by android.hardware.Camera to populate CameraInfo.canDisableShutterSound
5545    public boolean isCameraSoundForced() {
5546        synchronized (mCameraSoundForced) {
5547            return mCameraSoundForced;
5548        }
5549    }
5550
5551    private static final String[] RINGER_MODE_NAMES = new String[] {
5552            "SILENT",
5553            "VIBRATE",
5554            "NORMAL"
5555    };
5556
5557    private void dumpRingerMode(PrintWriter pw) {
5558        pw.println("\nRinger mode: ");
5559        pw.println("- mode (internal) = " + RINGER_MODE_NAMES[mRingerMode]);
5560        pw.println("- mode (external) = " + RINGER_MODE_NAMES[mRingerModeExternal]);
5561        pw.print("- ringer mode affected streams = 0x");
5562        pw.println(Integer.toHexString(mRingerModeAffectedStreams));
5563        pw.print("- ringer mode muted streams = 0x");
5564        pw.println(Integer.toHexString(mRingerModeMutedStreams));
5565        pw.print("- delegate = "); pw.println(mRingerModeDelegate);
5566    }
5567
5568    @Override
5569    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
5570        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
5571
5572        mMediaFocusControl.dump(pw);
5573        dumpStreamStates(pw);
5574        dumpRingerMode(pw);
5575        pw.println("\nAudio routes:");
5576        pw.print("  mMainType=0x"); pw.println(Integer.toHexString(mCurAudioRoutes.mMainType));
5577        pw.print("  mBluetoothName="); pw.println(mCurAudioRoutes.mBluetoothName);
5578
5579        pw.println("\nOther state:");
5580        pw.print("  mVolumeController="); pw.println(mVolumeController);
5581        pw.print("  mSafeMediaVolumeState=");
5582        pw.println(safeMediaVolumeStateToString(mSafeMediaVolumeState));
5583        pw.print("  mSafeMediaVolumeIndex="); pw.println(mSafeMediaVolumeIndex);
5584        pw.print("  mPendingVolumeCommand="); pw.println(mPendingVolumeCommand);
5585        pw.print("  mMusicActiveMs="); pw.println(mMusicActiveMs);
5586        pw.print("  mMcc="); pw.println(mMcc);
5587        pw.print("  mHasVibrator="); pw.println(mHasVibrator);
5588
5589        dumpAudioPolicies(pw);
5590    }
5591
5592    private static String safeMediaVolumeStateToString(Integer state) {
5593        switch(state) {
5594            case SAFE_MEDIA_VOLUME_NOT_CONFIGURED: return "SAFE_MEDIA_VOLUME_NOT_CONFIGURED";
5595            case SAFE_MEDIA_VOLUME_DISABLED: return "SAFE_MEDIA_VOLUME_DISABLED";
5596            case SAFE_MEDIA_VOLUME_INACTIVE: return "SAFE_MEDIA_VOLUME_INACTIVE";
5597            case SAFE_MEDIA_VOLUME_ACTIVE: return "SAFE_MEDIA_VOLUME_ACTIVE";
5598        }
5599        return null;
5600    }
5601
5602    // Inform AudioFlinger of our device's low RAM attribute
5603    private static void readAndSetLowRamDevice()
5604    {
5605        int status = AudioSystem.setLowRamDevice(ActivityManager.isLowRamDeviceStatic());
5606        if (status != 0) {
5607            Log.w(TAG, "AudioFlinger informed of device's low RAM attribute; status " + status);
5608        }
5609    }
5610
5611    private void enforceSelfOrSystemUI(String action) {
5612        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE,
5613                "Only SystemUI can " + action);
5614    }
5615
5616    @Override
5617    public void setVolumeController(final IVolumeController controller) {
5618        enforceSelfOrSystemUI("set the volume controller");
5619
5620        // return early if things are not actually changing
5621        if (mVolumeController.isSameBinder(controller)) {
5622            return;
5623        }
5624
5625        // dismiss the old volume controller
5626        mVolumeController.postDismiss();
5627        if (controller != null) {
5628            // we are about to register a new controller, listen for its death
5629            try {
5630                controller.asBinder().linkToDeath(new DeathRecipient() {
5631                    @Override
5632                    public void binderDied() {
5633                        if (mVolumeController.isSameBinder(controller)) {
5634                            Log.w(TAG, "Current remote volume controller died, unregistering");
5635                            setVolumeController(null);
5636                        }
5637                    }
5638                }, 0);
5639            } catch (RemoteException e) {
5640                // noop
5641            }
5642        }
5643        mVolumeController.setController(controller);
5644        if (DEBUG_VOL) Log.d(TAG, "Volume controller: " + mVolumeController);
5645    }
5646
5647    @Override
5648    public void notifyVolumeControllerVisible(final IVolumeController controller, boolean visible) {
5649        enforceSelfOrSystemUI("notify about volume controller visibility");
5650
5651        // return early if the controller is not current
5652        if (!mVolumeController.isSameBinder(controller)) {
5653            return;
5654        }
5655
5656        mVolumeController.setVisible(visible);
5657        if (DEBUG_VOL) Log.d(TAG, "Volume controller visible: " + visible);
5658    }
5659
5660    public static class VolumeController {
5661        private static final String TAG = "VolumeController";
5662
5663        private IVolumeController mController;
5664        private boolean mVisible;
5665        private long mNextLongPress;
5666        private int mLongPressTimeout;
5667
5668        public void setController(IVolumeController controller) {
5669            mController = controller;
5670            mVisible = false;
5671        }
5672
5673        public void loadSettings(ContentResolver cr) {
5674            mLongPressTimeout = Settings.Secure.getIntForUser(cr,
5675                    Settings.Secure.LONG_PRESS_TIMEOUT, 500, UserHandle.USER_CURRENT);
5676        }
5677
5678        public boolean suppressAdjustment(int resolvedStream, int flags) {
5679            boolean suppress = false;
5680            if (resolvedStream == AudioSystem.STREAM_RING && mController != null) {
5681                final long now = SystemClock.uptimeMillis();
5682                if ((flags & AudioManager.FLAG_SHOW_UI) != 0 && !mVisible) {
5683                    // ui will become visible
5684                    if (mNextLongPress < now) {
5685                        mNextLongPress = now + mLongPressTimeout;
5686                    }
5687                    suppress = true;
5688                } else if (mNextLongPress > 0) {  // in a long-press
5689                    if (now > mNextLongPress) {
5690                        // long press triggered, no more suppression
5691                        mNextLongPress = 0;
5692                    } else {
5693                        // keep suppressing until the long press triggers
5694                        suppress = true;
5695                    }
5696                }
5697            }
5698            return suppress;
5699        }
5700
5701        public void setVisible(boolean visible) {
5702            mVisible = visible;
5703        }
5704
5705        public boolean isSameBinder(IVolumeController controller) {
5706            return Objects.equals(asBinder(), binder(controller));
5707        }
5708
5709        public IBinder asBinder() {
5710            return binder(mController);
5711        }
5712
5713        private static IBinder binder(IVolumeController controller) {
5714            return controller == null ? null : controller.asBinder();
5715        }
5716
5717        @Override
5718        public String toString() {
5719            return "VolumeController(" + asBinder() + ",mVisible=" + mVisible + ")";
5720        }
5721
5722        public void postDisplaySafeVolumeWarning(int flags) {
5723            if (mController == null)
5724                return;
5725            try {
5726                mController.displaySafeVolumeWarning(flags);
5727            } catch (RemoteException e) {
5728                Log.w(TAG, "Error calling displaySafeVolumeWarning", e);
5729            }
5730        }
5731
5732        public void postVolumeChanged(int streamType, int flags) {
5733            if (mController == null)
5734                return;
5735            try {
5736                mController.volumeChanged(streamType, flags);
5737            } catch (RemoteException e) {
5738                Log.w(TAG, "Error calling volumeChanged", e);
5739            }
5740        }
5741
5742        public void postMasterVolumeChanged(int flags) {
5743            if (mController == null)
5744                return;
5745            try {
5746                mController.masterVolumeChanged(flags);
5747            } catch (RemoteException e) {
5748                Log.w(TAG, "Error calling masterVolumeChanged", e);
5749            }
5750        }
5751
5752        public void postMasterMuteChanged(int flags) {
5753            if (mController == null)
5754                return;
5755            try {
5756                mController.masterMuteChanged(flags);
5757            } catch (RemoteException e) {
5758                Log.w(TAG, "Error calling masterMuteChanged", e);
5759            }
5760        }
5761
5762        public void setLayoutDirection(int layoutDirection) {
5763            if (mController == null)
5764                return;
5765            try {
5766                mController.setLayoutDirection(layoutDirection);
5767            } catch (RemoteException e) {
5768                Log.w(TAG, "Error calling setLayoutDirection", e);
5769            }
5770        }
5771
5772        public void postDismiss() {
5773            if (mController == null)
5774                return;
5775            try {
5776                mController.dismiss();
5777            } catch (RemoteException e) {
5778                Log.w(TAG, "Error calling dismiss", e);
5779            }
5780        }
5781    }
5782
5783    /**
5784     * Interface for system components to get some extra functionality through
5785     * LocalServices.
5786     */
5787    final class AudioServiceInternal extends AudioManagerInternal {
5788        @Override
5789        public void setRingerModeDelegate(RingerModeDelegate delegate) {
5790            mRingerModeDelegate = delegate;
5791            if (mRingerModeDelegate != null) {
5792                setRingerModeInternal(getRingerModeInternal(), TAG + ".setRingerModeDelegate");
5793            }
5794        }
5795
5796        @Override
5797        public void adjustSuggestedStreamVolumeForUid(int streamType, int direction, int flags,
5798                String callingPackage, int uid) {
5799            // direction and stream type swap here because the public
5800            // adjustSuggested has a different order than the other methods.
5801            adjustSuggestedStreamVolume(direction, streamType, flags, callingPackage, uid);
5802        }
5803
5804        @Override
5805        public void adjustStreamVolumeForUid(int streamType, int direction, int flags,
5806                String callingPackage, int uid) {
5807            adjustStreamVolume(streamType, direction, flags, callingPackage, uid);
5808        }
5809
5810        @Override
5811        public void setStreamVolumeForUid(int streamType, int direction, int flags,
5812                String callingPackage, int uid) {
5813            setStreamVolume(streamType, direction, flags, callingPackage, uid);
5814        }
5815
5816        @Override
5817        public void adjustMasterVolumeForUid(int steps, int flags, String callingPackage,
5818                int uid) {
5819            adjustMasterVolume(steps, flags, callingPackage, uid);
5820        }
5821
5822        @Override
5823        public int getRingerModeInternal() {
5824            return AudioService.this.getRingerModeInternal();
5825        }
5826
5827        @Override
5828        public void setRingerModeInternal(int ringerMode, String caller) {
5829            AudioService.this.setRingerModeInternal(ringerMode, caller);
5830        }
5831
5832        @Override
5833        public void setMasterMuteForUid(boolean state, int flags, String callingPackage, IBinder cb,
5834                int uid) {
5835            setMasterMuteInternal(state, flags, callingPackage, cb, uid);
5836        }
5837    }
5838
5839    //==========================================================================================
5840    // Audio policy management
5841    //==========================================================================================
5842    public String registerAudioPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb,
5843            boolean hasFocusListener) {
5844        if (DEBUG_AP) Log.d(TAG, "registerAudioPolicy for " + pcb.asBinder()
5845                + " with config:" + policyConfig);
5846        String regId = null;
5847        // error handling
5848        boolean hasPermissionForPolicy =
5849                (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
5850                        android.Manifest.permission.MODIFY_AUDIO_ROUTING));
5851        if (!hasPermissionForPolicy) {
5852            Slog.w(TAG, "Can't register audio policy for pid " + Binder.getCallingPid() + " / uid "
5853                    + Binder.getCallingUid() + ", need MODIFY_AUDIO_ROUTING");
5854            return null;
5855        }
5856
5857        synchronized (mAudioPolicies) {
5858            try {
5859                if (mAudioPolicies.containsKey(pcb.asBinder())) {
5860                    Slog.e(TAG, "Cannot re-register policy");
5861                    return null;
5862                }
5863                AudioPolicyProxy app = new AudioPolicyProxy(policyConfig, pcb, hasFocusListener);
5864                pcb.asBinder().linkToDeath(app, 0/*flags*/);
5865                regId = app.getRegistrationId();
5866                mAudioPolicies.put(pcb.asBinder(), app);
5867            } catch (RemoteException e) {
5868                // audio policy owner has already died!
5869                Slog.w(TAG, "Audio policy registration failed, could not link to " + pcb +
5870                        " binder death", e);
5871                return null;
5872            }
5873        }
5874        return regId;
5875    }
5876
5877    public void unregisterAudioPolicyAsync(IAudioPolicyCallback pcb) {
5878        if (DEBUG_AP) Log.d(TAG, "unregisterAudioPolicyAsync for " + pcb.asBinder());
5879        synchronized (mAudioPolicies) {
5880            AudioPolicyProxy app = mAudioPolicies.remove(pcb.asBinder());
5881            if (app == null) {
5882                Slog.w(TAG, "Trying to unregister unknown audio policy for pid "
5883                        + Binder.getCallingPid() + " / uid " + Binder.getCallingUid());
5884                return;
5885            } else {
5886                pcb.asBinder().unlinkToDeath(app, 0/*flags*/);
5887            }
5888            app.release();
5889        }
5890        // TODO implement clearing mix attribute matching info in native audio policy
5891    }
5892
5893    public int setFocusPropertiesForPolicy(int duckingBehavior, IAudioPolicyCallback pcb) {
5894        if (DEBUG_AP) Log.d(TAG, "setFocusPropertiesForPolicy() duck behavior=" + duckingBehavior
5895                + " policy " +  pcb.asBinder());
5896        // error handling
5897        boolean hasPermissionForPolicy =
5898                (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
5899                        android.Manifest.permission.MODIFY_AUDIO_ROUTING));
5900        if (!hasPermissionForPolicy) {
5901            Slog.w(TAG, "Cannot change audio policy ducking handling for pid " +
5902                    + Binder.getCallingPid() + " / uid "
5903                    + Binder.getCallingUid() + ", need MODIFY_AUDIO_ROUTING");
5904            return AudioManager.ERROR;
5905        }
5906
5907        synchronized (mAudioPolicies) {
5908            if (!mAudioPolicies.containsKey(pcb.asBinder())) {
5909                Slog.e(TAG, "Cannot change audio policy focus properties, unregistered policy");
5910                return AudioManager.ERROR;
5911            }
5912            final AudioPolicyProxy app = mAudioPolicies.get(pcb.asBinder());
5913            if (duckingBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) {
5914                // is there already one policy managing ducking?
5915                for(AudioPolicyProxy policy : mAudioPolicies.values()) {
5916                    if (policy.mFocusDuckBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) {
5917                        Slog.e(TAG, "Cannot change audio policy ducking behavior, already handled");
5918                        return AudioManager.ERROR;
5919                    }
5920                }
5921            }
5922            app.mFocusDuckBehavior = duckingBehavior;
5923            mMediaFocusControl.setDuckingInExtPolicyAvailable(
5924                    duckingBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY);
5925        }
5926        return AudioManager.SUCCESS;
5927    }
5928
5929    private void dumpAudioPolicies(PrintWriter pw) {
5930        pw.println("\nAudio policies:");
5931        synchronized (mAudioPolicies) {
5932            for(AudioPolicyProxy policy : mAudioPolicies.values()) {
5933                pw.println(policy.toLogFriendlyString());
5934            }
5935        }
5936    }
5937
5938    //======================
5939    // Audio policy proxy
5940    //======================
5941    /**
5942     * This internal class inherits from AudioPolicyConfig, each instance contains all the
5943     * mixes of an AudioPolicy and their configurations.
5944     */
5945    public class AudioPolicyProxy extends AudioPolicyConfig implements IBinder.DeathRecipient {
5946        private static final String TAG = "AudioPolicyProxy";
5947        AudioPolicyConfig mConfig;
5948        IAudioPolicyCallback mPolicyToken;
5949        boolean mHasFocusListener;
5950        /**
5951         * Audio focus ducking behavior for an audio policy.
5952         * This variable reflects the value that was successfully set in
5953         * {@link AudioService#setFocusPropertiesForPolicy(int, IAudioPolicyCallback)}. This
5954         * implies that a value of FOCUS_POLICY_DUCKING_IN_POLICY means the corresponding policy
5955         * is handling ducking for audio focus.
5956         */
5957        int mFocusDuckBehavior = AudioPolicy.FOCUS_POLICY_DUCKING_DEFAULT;
5958
5959        AudioPolicyProxy(AudioPolicyConfig config, IAudioPolicyCallback token,
5960                boolean hasFocusListener) {
5961            super(config);
5962            setRegistration(new String(config.hashCode() + ":ap:" + mAudioPolicyCounter++));
5963            mPolicyToken = token;
5964            mHasFocusListener = hasFocusListener;
5965            if (mHasFocusListener) {
5966                mMediaFocusControl.addFocusFollower(mPolicyToken);
5967            }
5968            connectMixes();
5969        }
5970
5971        public void binderDied() {
5972            synchronized (mAudioPolicies) {
5973                Log.i(TAG, "audio policy " + mPolicyToken + " died");
5974                release();
5975                mAudioPolicies.remove(mPolicyToken.asBinder());
5976            }
5977        }
5978
5979        String getRegistrationId() {
5980            return getRegistration();
5981        }
5982
5983        void release() {
5984            if (mFocusDuckBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) {
5985                mMediaFocusControl.setDuckingInExtPolicyAvailable(false);
5986            }
5987            if (mHasFocusListener) {
5988                mMediaFocusControl.removeFocusFollower(mPolicyToken);
5989            }
5990            AudioSystem.registerPolicyMixes(mMixes, false);
5991        }
5992
5993        void connectMixes() {
5994            AudioSystem.registerPolicyMixes(mMixes, true);
5995        }
5996    };
5997
5998    private HashMap<IBinder, AudioPolicyProxy> mAudioPolicies =
5999            new HashMap<IBinder, AudioPolicyProxy>();
6000    private int mAudioPolicyCounter = 0; // always accessed synchronized on mAudioPolicies
6001}
6002