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