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