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