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