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