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