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