1 /*
2  * Copyright (C) 2007 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 android.Manifest;
20 import android.annotation.NonNull;
21 import android.annotation.SdkConstant;
22 import android.annotation.SdkConstant.SdkConstantType;
23 import android.annotation.SystemApi;
24 import android.app.PendingIntent;
25 import android.bluetooth.BluetoothDevice;
26 import android.content.ComponentName;
27 import android.content.Context;
28 import android.content.Intent;
29 import android.media.RemoteController.OnClientUpdateListener;
30 import android.media.audiopolicy.AudioPolicy;
31 import android.media.audiopolicy.AudioPolicyConfig;
32 import android.media.session.MediaController;
33 import android.media.session.MediaSession;
34 import android.media.session.MediaSessionLegacyHelper;
35 import android.media.session.MediaSessionManager;
36 import android.os.Binder;
37 import android.os.Handler;
38 import android.os.IBinder;
39 import android.os.Looper;
40 import android.os.Message;
41 import android.os.Process;
42 import android.os.RemoteException;
43 import android.os.SystemClock;
44 import android.os.ServiceManager;
45 import android.provider.Settings;
46 import android.util.Log;
47 import android.view.KeyEvent;
48 
49 import java.util.ArrayList;
50 import java.util.HashMap;
51 import java.util.Iterator;
52 
53 /**
54  * AudioManager provides access to volume and ringer mode control.
55  * <p>
56  * Use <code>Context.getSystemService(Context.AUDIO_SERVICE)</code> to get
57  * an instance of this class.
58  */
59 public class AudioManager {
60 
61     private final Context mContext;
62     private long mVolumeKeyUpTime;
63     private final boolean mUseMasterVolume;
64     private final boolean mUseVolumeKeySounds;
65     private final boolean mUseFixedVolume;
66     private final Binder mToken = new Binder();
67     private static String TAG = "AudioManager";
68     private static final AudioPortEventHandler sAudioPortEventHandler = new AudioPortEventHandler();
69 
70     /**
71      * Broadcast intent, a hint for applications that audio is about to become
72      * 'noisy' due to a change in audio outputs. For example, this intent may
73      * be sent when a wired headset is unplugged, or when an A2DP audio
74      * sink is disconnected, and the audio system is about to automatically
75      * switch audio route to the speaker. Applications that are controlling
76      * audio streams may consider pausing, reducing volume or some other action
77      * on receipt of this intent so as not to surprise the user with audio
78      * from the speaker.
79      */
80     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
81     public static final String ACTION_AUDIO_BECOMING_NOISY = "android.media.AUDIO_BECOMING_NOISY";
82 
83     /**
84      * Sticky broadcast intent action indicating that the ringer mode has
85      * changed. Includes the new ringer mode.
86      *
87      * @see #EXTRA_RINGER_MODE
88      */
89     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
90     public static final String RINGER_MODE_CHANGED_ACTION = "android.media.RINGER_MODE_CHANGED";
91 
92     /**
93      * @hide
94      * Sticky broadcast intent action indicating that the internal ringer mode has
95      * changed. Includes the new ringer mode.
96      *
97      * @see #EXTRA_RINGER_MODE
98      */
99     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
100     public static final String INTERNAL_RINGER_MODE_CHANGED_ACTION =
101             "android.media.INTERNAL_RINGER_MODE_CHANGED_ACTION";
102 
103     /**
104      * The new ringer mode.
105      *
106      * @see #RINGER_MODE_CHANGED_ACTION
107      * @see #RINGER_MODE_NORMAL
108      * @see #RINGER_MODE_SILENT
109      * @see #RINGER_MODE_VIBRATE
110      */
111     public static final String EXTRA_RINGER_MODE = "android.media.EXTRA_RINGER_MODE";
112 
113     /**
114      * Broadcast intent action indicating that the vibrate setting has
115      * changed. Includes the vibrate type and its new setting.
116      *
117      * @see #EXTRA_VIBRATE_TYPE
118      * @see #EXTRA_VIBRATE_SETTING
119      * @deprecated Applications should maintain their own vibrate policy based on
120      * current ringer mode and listen to {@link #RINGER_MODE_CHANGED_ACTION} instead.
121      */
122     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
123     public static final String VIBRATE_SETTING_CHANGED_ACTION =
124         "android.media.VIBRATE_SETTING_CHANGED";
125 
126     /**
127      * @hide Broadcast intent when the volume for a particular stream type changes.
128      * Includes the stream, the new volume and previous volumes.
129      * Notes:
130      *  - for internal platform use only, do not make public,
131      *  - never used for "remote" volume changes
132      *
133      * @see #EXTRA_VOLUME_STREAM_TYPE
134      * @see #EXTRA_VOLUME_STREAM_VALUE
135      * @see #EXTRA_PREV_VOLUME_STREAM_VALUE
136      */
137     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
138     public static final String VOLUME_CHANGED_ACTION = "android.media.VOLUME_CHANGED_ACTION";
139 
140     /**
141      * @hide Broadcast intent when a stream mute state changes.
142      * Includes the stream that changed and the new mute state
143      *
144      * @see #EXTRA_VOLUME_STREAM_TYPE
145      * @see #EXTRA_STREAM_VOLUME_MUTED
146      */
147     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
148     public static final String STREAM_MUTE_CHANGED_ACTION =
149         "android.media.STREAM_MUTE_CHANGED_ACTION";
150 
151     /**
152      * @hide Broadcast intent when the master volume changes.
153      * Includes the new volume
154      *
155      * @see #EXTRA_MASTER_VOLUME_VALUE
156      * @see #EXTRA_PREV_MASTER_VOLUME_VALUE
157      */
158     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
159     public static final String MASTER_VOLUME_CHANGED_ACTION =
160         "android.media.MASTER_VOLUME_CHANGED_ACTION";
161 
162     /**
163      * @hide Broadcast intent when the master mute state changes.
164      * Includes the the new volume
165      *
166      * @see #EXTRA_MASTER_VOLUME_MUTED
167      */
168     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
169     public static final String MASTER_MUTE_CHANGED_ACTION =
170         "android.media.MASTER_MUTE_CHANGED_ACTION";
171 
172     /**
173      * The new vibrate setting for a particular type.
174      *
175      * @see #VIBRATE_SETTING_CHANGED_ACTION
176      * @see #EXTRA_VIBRATE_TYPE
177      * @see #VIBRATE_SETTING_ON
178      * @see #VIBRATE_SETTING_OFF
179      * @see #VIBRATE_SETTING_ONLY_SILENT
180      * @deprecated Applications should maintain their own vibrate policy based on
181      * current ringer mode and listen to {@link #RINGER_MODE_CHANGED_ACTION} instead.
182      */
183     public static final String EXTRA_VIBRATE_SETTING = "android.media.EXTRA_VIBRATE_SETTING";
184 
185     /**
186      * The vibrate type whose setting has changed.
187      *
188      * @see #VIBRATE_SETTING_CHANGED_ACTION
189      * @see #VIBRATE_TYPE_NOTIFICATION
190      * @see #VIBRATE_TYPE_RINGER
191      * @deprecated Applications should maintain their own vibrate policy based on
192      * current ringer mode and listen to {@link #RINGER_MODE_CHANGED_ACTION} instead.
193      */
194     public static final String EXTRA_VIBRATE_TYPE = "android.media.EXTRA_VIBRATE_TYPE";
195 
196     /**
197      * @hide The stream type for the volume changed intent.
198      */
199     public static final String EXTRA_VOLUME_STREAM_TYPE = "android.media.EXTRA_VOLUME_STREAM_TYPE";
200 
201     /**
202      * @hide The volume associated with the stream for the volume changed intent.
203      */
204     public static final String EXTRA_VOLUME_STREAM_VALUE =
205         "android.media.EXTRA_VOLUME_STREAM_VALUE";
206 
207     /**
208      * @hide The previous volume associated with the stream for the volume changed intent.
209      */
210     public static final String EXTRA_PREV_VOLUME_STREAM_VALUE =
211         "android.media.EXTRA_PREV_VOLUME_STREAM_VALUE";
212 
213     /**
214      * @hide The new master volume value for the master volume changed intent.
215      * Value is integer between 0 and 100 inclusive.
216      */
217     public static final String EXTRA_MASTER_VOLUME_VALUE =
218         "android.media.EXTRA_MASTER_VOLUME_VALUE";
219 
220     /**
221      * @hide The previous master volume value for the master volume changed intent.
222      * Value is integer between 0 and 100 inclusive.
223      */
224     public static final String EXTRA_PREV_MASTER_VOLUME_VALUE =
225         "android.media.EXTRA_PREV_MASTER_VOLUME_VALUE";
226 
227     /**
228      * @hide The new master volume mute state for the master mute changed intent.
229      * Value is boolean
230      */
231     public static final String EXTRA_MASTER_VOLUME_MUTED =
232         "android.media.EXTRA_MASTER_VOLUME_MUTED";
233 
234     /**
235      * @hide The new stream volume mute state for the stream mute changed intent.
236      * Value is boolean
237      */
238     public static final String EXTRA_STREAM_VOLUME_MUTED =
239         "android.media.EXTRA_STREAM_VOLUME_MUTED";
240 
241     /**
242      * Broadcast Action: Wired Headset plugged in or unplugged.
243      *
244      * You <em>cannot</em> receive this through components declared
245      * in manifests, only by explicitly registering for it with
246      * {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)
247      * Context.registerReceiver()}.
248      *
249      * <p>The intent will have the following extra values:
250      * <ul>
251      *   <li><em>state</em> - 0 for unplugged, 1 for plugged. </li>
252      *   <li><em>name</em> - Headset type, human readable string </li>
253      *   <li><em>microphone</em> - 1 if headset has a microphone, 0 otherwise </li>
254      * </ul>
255      * </ul>
256      */
257     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
258     public static final String ACTION_HEADSET_PLUG =
259             "android.intent.action.HEADSET_PLUG";
260 
261     /**
262      * Broadcast Action: A sticky broadcast indicating an HMDI cable was plugged or unplugged
263      *
264      * The intent will have the following extra values: {@link #EXTRA_AUDIO_PLUG_STATE},
265      * {@link #EXTRA_MAX_CHANNEL_COUNT}, {@link #EXTRA_ENCODINGS}.
266      * <p>It can only be received by explicitly registering for it with
267      * {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)}.
268      */
269     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
270     public static final String ACTION_HDMI_AUDIO_PLUG =
271             "android.media.action.HDMI_AUDIO_PLUG";
272 
273     /**
274      * Extra used in {@link #ACTION_HDMI_AUDIO_PLUG} to communicate whether HDMI is plugged in
275      * or unplugged.
276      * An integer value of 1 indicates a plugged-in state, 0 is unplugged.
277      */
278     public static final String EXTRA_AUDIO_PLUG_STATE = "android.media.extra.AUDIO_PLUG_STATE";
279 
280     /**
281      * Extra used in {@link #ACTION_HDMI_AUDIO_PLUG} to define the maximum number of channels
282      * supported by the HDMI device.
283      * The corresponding integer value is only available when the device is plugged in (as expressed
284      * by {@link #EXTRA_AUDIO_PLUG_STATE}).
285      */
286     public static final String EXTRA_MAX_CHANNEL_COUNT = "android.media.extra.MAX_CHANNEL_COUNT";
287 
288     /**
289      * Extra used in {@link #ACTION_HDMI_AUDIO_PLUG} to define the audio encodings supported by
290      * the connected HDMI device.
291      * The corresponding array of encoding values is only available when the device is plugged in
292      * (as expressed by {@link #EXTRA_AUDIO_PLUG_STATE}). Encoding values are defined in
293      * {@link AudioFormat} (for instance see {@link AudioFormat#ENCODING_PCM_16BIT}). Use
294      * {@link android.content.Intent#getIntArrayExtra(String)} to retrieve the encoding values.
295      */
296     public static final String EXTRA_ENCODINGS = "android.media.extra.ENCODINGS";
297 
298     /**
299      * Broadcast Action: An analog audio speaker/headset plugged in or unplugged.
300      *
301      * <p>The intent will have the following extra values:
302      * <ul>
303      *   <li><em>state</em> - 0 for unplugged, 1 for plugged. </li>
304      *   <li><em>name</em> - Headset type, human readable string </li>
305      * </ul>
306      * </ul>
307      * @hide
308      */
309     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
310     public static final String ACTION_ANALOG_AUDIO_DOCK_PLUG =
311             "android.media.action.ANALOG_AUDIO_DOCK_PLUG";
312 
313     /**
314      * Broadcast Action: A digital audio speaker/headset plugged in or unplugged.
315      *
316      * <p>The intent will have the following extra values:
317      * <ul>
318      *   <li><em>state</em> - 0 for unplugged, 1 for plugged. </li>
319      *   <li><em>name</em> - Headset type, human readable string </li>
320      * </ul>
321      * </ul>
322      * @hide
323      */
324     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
325     public static final String ACTION_DIGITAL_AUDIO_DOCK_PLUG =
326             "android.media.action.DIGITAL_AUDIO_DOCK_PLUG";
327 
328     /**
329      * Broadcast Action: A USB audio accessory was plugged in or unplugged.
330      *
331      * <p>The intent will have the following extra values:
332      * <ul>
333      *   <li><em>state</em> - 0 for unplugged, 1 for plugged. </li>
334      *   <li><em>card</em> - ALSA card number (integer) </li>
335      *   <li><em>device</em> - ALSA device number (integer) </li>
336      * </ul>
337      * </ul>
338      * @hide
339      */
340     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
341     public static final String ACTION_USB_AUDIO_ACCESSORY_PLUG =
342             "android.media.action.USB_AUDIO_ACCESSORY_PLUG";
343 
344     /**
345      * Broadcast Action: A USB audio device was plugged in or unplugged.
346      *
347      * <p>The intent will have the following extra values:
348      * <ul>
349      *   <li><em>state</em> - 0 for unplugged, 1 for plugged. </li>
350      *   <li><em>card</em> - ALSA card number (integer) </li>
351      *   <li><em>device</em> - ALSA device number (integer) </li>
352      * </ul>
353      * </ul>
354      * @hide
355      */
356     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
357     public static final String ACTION_USB_AUDIO_DEVICE_PLUG =
358             "android.media.action.USB_AUDIO_DEVICE_PLUG";
359 
360     /** The audio stream for phone calls */
361     public static final int STREAM_VOICE_CALL = AudioSystem.STREAM_VOICE_CALL;
362     /** The audio stream for system sounds */
363     public static final int STREAM_SYSTEM = AudioSystem.STREAM_SYSTEM;
364     /** The audio stream for the phone ring */
365     public static final int STREAM_RING = AudioSystem.STREAM_RING;
366     /** The audio stream for music playback */
367     public static final int STREAM_MUSIC = AudioSystem.STREAM_MUSIC;
368     /** The audio stream for alarms */
369     public static final int STREAM_ALARM = AudioSystem.STREAM_ALARM;
370     /** The audio stream for notifications */
371     public static final int STREAM_NOTIFICATION = AudioSystem.STREAM_NOTIFICATION;
372     /** @hide The audio stream for phone calls when connected to bluetooth */
373     public static final int STREAM_BLUETOOTH_SCO = AudioSystem.STREAM_BLUETOOTH_SCO;
374     /** @hide The audio stream for enforced system sounds in certain countries (e.g camera in Japan) */
375     public static final int STREAM_SYSTEM_ENFORCED = AudioSystem.STREAM_SYSTEM_ENFORCED;
376     /** The audio stream for DTMF Tones */
377     public static final int STREAM_DTMF = AudioSystem.STREAM_DTMF;
378     /** @hide The audio stream for text to speech (TTS) */
379     public static final int STREAM_TTS = AudioSystem.STREAM_TTS;
380     /** Number of audio streams */
381     /**
382      * @deprecated Use AudioSystem.getNumStreamTypes() instead
383      */
384     @Deprecated public static final int NUM_STREAMS = AudioSystem.NUM_STREAMS;
385 
386     /**
387      * Increase the ringer volume.
388      *
389      * @see #adjustVolume(int, int)
390      * @see #adjustStreamVolume(int, int, int)
391      */
392     public static final int ADJUST_RAISE = 1;
393 
394     /**
395      * Decrease the ringer volume.
396      *
397      * @see #adjustVolume(int, int)
398      * @see #adjustStreamVolume(int, int, int)
399      */
400     public static final int ADJUST_LOWER = -1;
401 
402     /**
403      * Maintain the previous ringer volume. This may be useful when needing to
404      * show the volume toast without actually modifying the volume.
405      *
406      * @see #adjustVolume(int, int)
407      * @see #adjustStreamVolume(int, int, int)
408      */
409     public static final int ADJUST_SAME = 0;
410 
411     // Flags should be powers of 2!
412 
413     /**
414      * Show a toast containing the current volume.
415      *
416      * @see #adjustStreamVolume(int, int, int)
417      * @see #adjustVolume(int, int)
418      * @see #setStreamVolume(int, int, int)
419      * @see #setRingerMode(int)
420      */
421     public static final int FLAG_SHOW_UI = 1 << 0;
422 
423     /**
424      * Whether to include ringer modes as possible options when changing volume.
425      * For example, if true and volume level is 0 and the volume is adjusted
426      * with {@link #ADJUST_LOWER}, then the ringer mode may switch the silent or
427      * vibrate mode.
428      * <p>
429      * By default this is on for the ring stream. If this flag is included,
430      * this behavior will be present regardless of the stream type being
431      * affected by the ringer mode.
432      *
433      * @see #adjustVolume(int, int)
434      * @see #adjustStreamVolume(int, int, int)
435      */
436     public static final int FLAG_ALLOW_RINGER_MODES = 1 << 1;
437 
438     /**
439      * Whether to play a sound when changing the volume.
440      * <p>
441      * If this is given to {@link #adjustVolume(int, int)} or
442      * {@link #adjustSuggestedStreamVolume(int, int, int)}, it may be ignored
443      * in some cases (for example, the decided stream type is not
444      * {@link AudioManager#STREAM_RING}, or the volume is being adjusted
445      * downward).
446      *
447      * @see #adjustStreamVolume(int, int, int)
448      * @see #adjustVolume(int, int)
449      * @see #setStreamVolume(int, int, int)
450      */
451     public static final int FLAG_PLAY_SOUND = 1 << 2;
452 
453     /**
454      * Removes any sounds/vibrate that may be in the queue, or are playing (related to
455      * changing volume).
456      */
457     public static final int FLAG_REMOVE_SOUND_AND_VIBRATE = 1 << 3;
458 
459     /**
460      * Whether to vibrate if going into the vibrate ringer mode.
461      */
462     public static final int FLAG_VIBRATE = 1 << 4;
463 
464     /**
465      * Indicates to VolumePanel that the volume slider should be disabled as user
466      * cannot change the stream volume
467      * @hide
468      */
469     public static final int FLAG_FIXED_VOLUME = 1 << 5;
470 
471     /**
472      * Indicates the volume set/adjust call is for Bluetooth absolute volume
473      * @hide
474      */
475     public static final int FLAG_BLUETOOTH_ABS_VOLUME = 1 << 6;
476 
477     /**
478      * Adjusting the volume was prevented due to silent mode, display a hint in the UI.
479      * @hide
480      */
481     public static final int FLAG_SHOW_SILENT_HINT = 1 << 7;
482 
483     /**
484      * Indicates the volume call is for Hdmi Cec system audio volume
485      * @hide
486      */
487     public static final int FLAG_HDMI_SYSTEM_AUDIO_VOLUME = 1 << 8;
488 
489     /**
490      * Indicates that this should only be handled if media is actively playing.
491      * @hide
492      */
493     public static final int FLAG_ACTIVE_MEDIA_ONLY = 1 << 9;
494 
495     /**
496      * Like FLAG_SHOW_UI, but only dialog warnings and confirmations, no sliders.
497      * @hide
498      */
499     public static final int FLAG_SHOW_UI_WARNINGS = 1 << 10;
500 
501     /**
502      * Adjusting the volume down from vibrated was prevented, display a hint in the UI.
503      * @hide
504      */
505     public static final int FLAG_SHOW_VIBRATE_HINT = 1 << 11;
506 
507     private static final String[] FLAG_NAMES = {
508         "FLAG_SHOW_UI",
509         "FLAG_ALLOW_RINGER_MODES",
510         "FLAG_PLAY_SOUND",
511         "FLAG_REMOVE_SOUND_AND_VIBRATE",
512         "FLAG_VIBRATE",
513         "FLAG_FIXED_VOLUME",
514         "FLAG_BLUETOOTH_ABS_VOLUME",
515         "FLAG_SHOW_SILENT_HINT",
516         "FLAG_HDMI_SYSTEM_AUDIO_VOLUME",
517         "FLAG_ACTIVE_MEDIA_ONLY",
518         "FLAG_SHOW_UI_WARNINGS",
519         "FLAG_SHOW_VIBRATE_HINT",
520     };
521 
522     /** @hide */
flagsToString(int flags)523     public static String flagsToString(int flags) {
524         final StringBuilder sb = new StringBuilder();
525         for (int i = 0; i < FLAG_NAMES.length; i++) {
526             final int flag = 1 << i;
527             if ((flags & flag) != 0) {
528                 if (sb.length() > 0) {
529                     sb.append(',');
530                 }
531                 sb.append(FLAG_NAMES[i]);
532                 flags &= ~flag;
533             }
534         }
535         if (flags != 0) {
536             if (sb.length() > 0) {
537                 sb.append(',');
538             }
539             sb.append(flags);
540         }
541         return sb.toString();
542     }
543 
544     /**
545      * Ringer mode that will be silent and will not vibrate. (This overrides the
546      * vibrate setting.)
547      *
548      * @see #setRingerMode(int)
549      * @see #getRingerMode()
550      */
551     public static final int RINGER_MODE_SILENT = 0;
552 
553     /**
554      * Ringer mode that will be silent and will vibrate. (This will cause the
555      * phone ringer to always vibrate, but the notification vibrate to only
556      * vibrate if set.)
557      *
558      * @see #setRingerMode(int)
559      * @see #getRingerMode()
560      */
561     public static final int RINGER_MODE_VIBRATE = 1;
562 
563     /**
564      * Ringer mode that may be audible and may vibrate. It will be audible if
565      * the volume before changing out of this mode was audible. It will vibrate
566      * if the vibrate setting is on.
567      *
568      * @see #setRingerMode(int)
569      * @see #getRingerMode()
570      */
571     public static final int RINGER_MODE_NORMAL = 2;
572 
573     /**
574      * Maximum valid ringer mode value. Values must start from 0 and be contiguous.
575      * @hide
576      */
577     public static final int RINGER_MODE_MAX = RINGER_MODE_NORMAL;
578 
579     /**
580      * Vibrate type that corresponds to the ringer.
581      *
582      * @see #setVibrateSetting(int, int)
583      * @see #getVibrateSetting(int)
584      * @see #shouldVibrate(int)
585      * @deprecated Applications should maintain their own vibrate policy based on
586      * current ringer mode that can be queried via {@link #getRingerMode()}.
587      */
588     public static final int VIBRATE_TYPE_RINGER = 0;
589 
590     /**
591      * Vibrate type that corresponds to notifications.
592      *
593      * @see #setVibrateSetting(int, int)
594      * @see #getVibrateSetting(int)
595      * @see #shouldVibrate(int)
596      * @deprecated Applications should maintain their own vibrate policy based on
597      * current ringer mode that can be queried via {@link #getRingerMode()}.
598      */
599     public static final int VIBRATE_TYPE_NOTIFICATION = 1;
600 
601     /**
602      * Vibrate setting that suggests to never vibrate.
603      *
604      * @see #setVibrateSetting(int, int)
605      * @see #getVibrateSetting(int)
606      * @deprecated Applications should maintain their own vibrate policy based on
607      * current ringer mode that can be queried via {@link #getRingerMode()}.
608      */
609     public static final int VIBRATE_SETTING_OFF = 0;
610 
611     /**
612      * Vibrate setting that suggests to vibrate when possible.
613      *
614      * @see #setVibrateSetting(int, int)
615      * @see #getVibrateSetting(int)
616      * @deprecated Applications should maintain their own vibrate policy based on
617      * current ringer mode that can be queried via {@link #getRingerMode()}.
618      */
619     public static final int VIBRATE_SETTING_ON = 1;
620 
621     /**
622      * Vibrate setting that suggests to only vibrate when in the vibrate ringer
623      * mode.
624      *
625      * @see #setVibrateSetting(int, int)
626      * @see #getVibrateSetting(int)
627      * @deprecated Applications should maintain their own vibrate policy based on
628      * current ringer mode that can be queried via {@link #getRingerMode()}.
629      */
630     public static final int VIBRATE_SETTING_ONLY_SILENT = 2;
631 
632     /**
633      * Suggests using the default stream type. This may not be used in all
634      * places a stream type is needed.
635      */
636     public static final int USE_DEFAULT_STREAM_TYPE = Integer.MIN_VALUE;
637 
638     private static IAudioService sService;
639 
640     /**
641      * @hide
642      */
AudioManager(Context context)643     public AudioManager(Context context) {
644         mContext = context;
645         mUseMasterVolume = mContext.getResources().getBoolean(
646                 com.android.internal.R.bool.config_useMasterVolume);
647         mUseVolumeKeySounds = mContext.getResources().getBoolean(
648                 com.android.internal.R.bool.config_useVolumeKeySounds);
649         mUseFixedVolume = mContext.getResources().getBoolean(
650                 com.android.internal.R.bool.config_useFixedVolume);
651         sAudioPortEventHandler.init();
652     }
653 
getService()654     private static IAudioService getService()
655     {
656         if (sService != null) {
657             return sService;
658         }
659         IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
660         sService = IAudioService.Stub.asInterface(b);
661         return sService;
662     }
663 
664     /**
665      * Sends a simulated key event for a media button.
666      * To simulate a key press, you must first send a KeyEvent built with a
667      * {@link KeyEvent#ACTION_DOWN} action, then another event with the {@link KeyEvent#ACTION_UP}
668      * action.
669      * <p>The key event will be sent to the current media key event consumer which registered with
670      * {@link AudioManager#registerMediaButtonEventReceiver(PendingIntent)}.
671      * @param keyEvent a {@link KeyEvent} instance whose key code is one of
672      *     {@link KeyEvent#KEYCODE_MUTE},
673      *     {@link KeyEvent#KEYCODE_HEADSETHOOK},
674      *     {@link KeyEvent#KEYCODE_MEDIA_PLAY},
675      *     {@link KeyEvent#KEYCODE_MEDIA_PAUSE},
676      *     {@link KeyEvent#KEYCODE_MEDIA_PLAY_PAUSE},
677      *     {@link KeyEvent#KEYCODE_MEDIA_STOP},
678      *     {@link KeyEvent#KEYCODE_MEDIA_NEXT},
679      *     {@link KeyEvent#KEYCODE_MEDIA_PREVIOUS},
680      *     {@link KeyEvent#KEYCODE_MEDIA_REWIND},
681      *     {@link KeyEvent#KEYCODE_MEDIA_RECORD},
682      *     {@link KeyEvent#KEYCODE_MEDIA_FAST_FORWARD},
683      *     {@link KeyEvent#KEYCODE_MEDIA_CLOSE},
684      *     {@link KeyEvent#KEYCODE_MEDIA_EJECT},
685      *     or {@link KeyEvent#KEYCODE_MEDIA_AUDIO_TRACK}.
686      */
dispatchMediaKeyEvent(KeyEvent keyEvent)687     public void dispatchMediaKeyEvent(KeyEvent keyEvent) {
688         MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mContext);
689         helper.sendMediaButtonEvent(keyEvent, false);
690     }
691 
692     /**
693      * @hide
694      */
preDispatchKeyEvent(KeyEvent event, int stream)695     public void preDispatchKeyEvent(KeyEvent event, int stream) {
696         /*
697          * If the user hits another key within the play sound delay, then
698          * cancel the sound
699          */
700         int keyCode = event.getKeyCode();
701         if (keyCode != KeyEvent.KEYCODE_VOLUME_DOWN && keyCode != KeyEvent.KEYCODE_VOLUME_UP
702                 && keyCode != KeyEvent.KEYCODE_VOLUME_MUTE
703                 && mVolumeKeyUpTime + AudioService.PLAY_SOUND_DELAY
704                         > SystemClock.uptimeMillis()) {
705             /*
706              * The user has hit another key during the delay (e.g., 300ms)
707              * since the last volume key up, so cancel any sounds.
708              */
709             if (mUseMasterVolume) {
710                 adjustMasterVolume(ADJUST_SAME, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
711             } else {
712                 adjustSuggestedStreamVolume(ADJUST_SAME,
713                         stream, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
714             }
715         }
716     }
717 
718     /**
719      * @hide
720      */
handleKeyDown(KeyEvent event, int stream)721     public void handleKeyDown(KeyEvent event, int stream) {
722         int keyCode = event.getKeyCode();
723         switch (keyCode) {
724             case KeyEvent.KEYCODE_VOLUME_UP:
725             case KeyEvent.KEYCODE_VOLUME_DOWN:
726                 /*
727                  * Adjust the volume in on key down since it is more
728                  * responsive to the user.
729                  */
730                 int flags = FLAG_SHOW_UI | FLAG_VIBRATE;
731 
732                 if (mUseMasterVolume) {
733                     adjustMasterVolume(
734                             keyCode == KeyEvent.KEYCODE_VOLUME_UP
735                                     ? ADJUST_RAISE
736                                     : ADJUST_LOWER,
737                             flags);
738                 } else {
739                     adjustSuggestedStreamVolume(
740                             keyCode == KeyEvent.KEYCODE_VOLUME_UP
741                                     ? ADJUST_RAISE
742                                     : ADJUST_LOWER,
743                             stream,
744                             flags);
745                 }
746                 break;
747             case KeyEvent.KEYCODE_VOLUME_MUTE:
748                 if (event.getRepeatCount() == 0) {
749                     MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(event, false);
750                 }
751                 break;
752         }
753     }
754 
755     /**
756      * @hide
757      */
handleKeyUp(KeyEvent event, int stream)758     public void handleKeyUp(KeyEvent event, int stream) {
759         int keyCode = event.getKeyCode();
760         switch (keyCode) {
761             case KeyEvent.KEYCODE_VOLUME_UP:
762             case KeyEvent.KEYCODE_VOLUME_DOWN:
763                 /*
764                  * Play a sound. This is done on key up since we don't want the
765                  * sound to play when a user holds down volume down to mute.
766                  */
767                 if (mUseVolumeKeySounds) {
768                     if (mUseMasterVolume) {
769                         adjustMasterVolume(ADJUST_SAME, FLAG_PLAY_SOUND);
770                     } else {
771                         int flags = FLAG_PLAY_SOUND;
772                         adjustSuggestedStreamVolume(
773                                 ADJUST_SAME,
774                                 stream,
775                                 flags);
776                     }
777                 }
778                 mVolumeKeyUpTime = SystemClock.uptimeMillis();
779                 break;
780             case KeyEvent.KEYCODE_VOLUME_MUTE:
781                 MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(event, false);
782                 break;
783         }
784     }
785 
786     /**
787      * Indicates if the device implements a fixed volume policy.
788      * <p>Some devices may not have volume control and may operate at a fixed volume,
789      * and may not enable muting or changing the volume of audio streams.
790      * This method will return true on such devices.
791      * <p>The following APIs have no effect when volume is fixed:
792      * <ul>
793      *   <li> {@link #adjustVolume(int, int)}
794      *   <li> {@link #adjustSuggestedStreamVolume(int, int, int)}
795      *   <li> {@link #adjustStreamVolume(int, int, int)}
796      *   <li> {@link #setStreamVolume(int, int, int)}
797      *   <li> {@link #setRingerMode(int)}
798      *   <li> {@link #setStreamSolo(int, boolean)}
799      *   <li> {@link #setStreamMute(int, boolean)}
800      * </ul>
801      */
isVolumeFixed()802     public boolean isVolumeFixed() {
803         return mUseFixedVolume;
804     }
805 
806     /**
807      * Adjusts the volume of a particular stream by one step in a direction.
808      * <p>
809      * This method should only be used by applications that replace the platform-wide
810      * management of audio settings or the main telephony application.
811      *
812      * @param streamType The stream type to adjust. One of {@link #STREAM_VOICE_CALL},
813      * {@link #STREAM_SYSTEM}, {@link #STREAM_RING}, {@link #STREAM_MUSIC} or
814      * {@link #STREAM_ALARM}
815      * @param direction The direction to adjust the volume. One of
816      *            {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, or
817      *            {@link #ADJUST_SAME}.
818      * @param flags One or more flags.
819      * @see #adjustVolume(int, int)
820      * @see #setStreamVolume(int, int, int)
821      */
adjustStreamVolume(int streamType, int direction, int flags)822     public void adjustStreamVolume(int streamType, int direction, int flags) {
823         IAudioService service = getService();
824         try {
825             if (mUseMasterVolume) {
826                 service.adjustMasterVolume(direction, flags, mContext.getOpPackageName());
827             } else {
828                 service.adjustStreamVolume(streamType, direction, flags,
829                         mContext.getOpPackageName());
830             }
831         } catch (RemoteException e) {
832             Log.e(TAG, "Dead object in adjustStreamVolume", e);
833         }
834     }
835 
836     /**
837      * Adjusts the volume of the most relevant stream. For example, if a call is
838      * active, it will have the highest priority regardless of if the in-call
839      * screen is showing. Another example, if music is playing in the background
840      * and a call is not active, the music stream will be adjusted.
841      * <p>
842      * This method should only be used by applications that replace the platform-wide
843      * management of audio settings or the main telephony application.
844      * <p>This method has no effect if the device implements a fixed volume policy
845      * as indicated by {@link #isVolumeFixed()}.
846      * @param direction The direction to adjust the volume. One of
847      *            {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, or
848      *            {@link #ADJUST_SAME}.
849      * @param flags One or more flags.
850      * @see #adjustSuggestedStreamVolume(int, int, int)
851      * @see #adjustStreamVolume(int, int, int)
852      * @see #setStreamVolume(int, int, int)
853      * @see #isVolumeFixed()
854      */
adjustVolume(int direction, int flags)855     public void adjustVolume(int direction, int flags) {
856         IAudioService service = getService();
857         try {
858             if (mUseMasterVolume) {
859                 service.adjustMasterVolume(direction, flags, mContext.getOpPackageName());
860             } else {
861                 MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mContext);
862                 helper.sendAdjustVolumeBy(USE_DEFAULT_STREAM_TYPE, direction, flags);
863             }
864         } catch (RemoteException e) {
865             Log.e(TAG, "Dead object in adjustVolume", e);
866         }
867     }
868 
869     /**
870      * Adjusts the volume of the most relevant stream, or the given fallback
871      * stream.
872      * <p>
873      * This method should only be used by applications that replace the platform-wide
874      * management of audio settings or the main telephony application.
875      *
876      * <p>This method has no effect if the device implements a fixed volume policy
877      * as indicated by {@link #isVolumeFixed()}.
878      * @param direction The direction to adjust the volume. One of
879      *            {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, or
880      *            {@link #ADJUST_SAME}.
881      * @param suggestedStreamType The stream type that will be used if there
882      *            isn't a relevant stream. {@link #USE_DEFAULT_STREAM_TYPE} is valid here.
883      * @param flags One or more flags.
884      * @see #adjustVolume(int, int)
885      * @see #adjustStreamVolume(int, int, int)
886      * @see #setStreamVolume(int, int, int)
887      * @see #isVolumeFixed()
888      */
adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags)889     public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags) {
890         IAudioService service = getService();
891         try {
892             if (mUseMasterVolume) {
893                 service.adjustMasterVolume(direction, flags, mContext.getOpPackageName());
894             } else {
895                 MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mContext);
896                 helper.sendAdjustVolumeBy(suggestedStreamType, direction, flags);
897             }
898         } catch (RemoteException e) {
899             Log.e(TAG, "Dead object in adjustSuggestedStreamVolume", e);
900         }
901     }
902 
903     /**
904      * Adjusts the master volume for the device's audio amplifier.
905      * <p>
906      *
907      * @param steps The number of volume steps to adjust. A positive
908      *            value will raise the volume.
909      * @param flags One or more flags.
910      * @hide
911      */
adjustMasterVolume(int steps, int flags)912     public void adjustMasterVolume(int steps, int flags) {
913         IAudioService service = getService();
914         try {
915             service.adjustMasterVolume(steps, flags, mContext.getOpPackageName());
916         } catch (RemoteException e) {
917             Log.e(TAG, "Dead object in adjustMasterVolume", e);
918         }
919     }
920 
921     /**
922      * Returns the current ringtone mode.
923      *
924      * @return The current ringtone mode, one of {@link #RINGER_MODE_NORMAL},
925      *         {@link #RINGER_MODE_SILENT}, or {@link #RINGER_MODE_VIBRATE}.
926      * @see #setRingerMode(int)
927      */
getRingerMode()928     public int getRingerMode() {
929         IAudioService service = getService();
930         try {
931             return service.getRingerModeExternal();
932         } catch (RemoteException e) {
933             Log.e(TAG, "Dead object in getRingerMode", e);
934             return RINGER_MODE_NORMAL;
935         }
936     }
937 
938     /**
939      * Checks valid ringer mode values.
940      *
941      * @return true if the ringer mode indicated is valid, false otherwise.
942      *
943      * @see #setRingerMode(int)
944      * @hide
945      */
isValidRingerMode(int ringerMode)946     public static boolean isValidRingerMode(int ringerMode) {
947         if (ringerMode < 0 || ringerMode > RINGER_MODE_MAX) {
948             return false;
949         }
950         IAudioService service = getService();
951         try {
952             return service.isValidRingerMode(ringerMode);
953         } catch (RemoteException e) {
954             Log.e(TAG, "Dead object in isValidRingerMode", e);
955             return false;
956         }
957     }
958 
959     /**
960      * Returns the maximum volume index for a particular stream.
961      *
962      * @param streamType The stream type whose maximum volume index is returned.
963      * @return The maximum valid volume index for the stream.
964      * @see #getStreamVolume(int)
965      */
getStreamMaxVolume(int streamType)966     public int getStreamMaxVolume(int streamType) {
967         IAudioService service = getService();
968         try {
969             if (mUseMasterVolume) {
970                 return service.getMasterMaxVolume();
971             } else {
972                 return service.getStreamMaxVolume(streamType);
973             }
974         } catch (RemoteException e) {
975             Log.e(TAG, "Dead object in getStreamMaxVolume", e);
976             return 0;
977         }
978     }
979 
980     /**
981      * Returns the current volume index for a particular stream.
982      *
983      * @param streamType The stream type whose volume index is returned.
984      * @return The current volume index for the stream.
985      * @see #getStreamMaxVolume(int)
986      * @see #setStreamVolume(int, int, int)
987      */
getStreamVolume(int streamType)988     public int getStreamVolume(int streamType) {
989         IAudioService service = getService();
990         try {
991             if (mUseMasterVolume) {
992                 return service.getMasterVolume();
993             } else {
994                 return service.getStreamVolume(streamType);
995             }
996         } catch (RemoteException e) {
997             Log.e(TAG, "Dead object in getStreamVolume", e);
998             return 0;
999         }
1000     }
1001 
1002     /**
1003      * Get last audible volume before stream was muted.
1004      *
1005      * @hide
1006      */
getLastAudibleStreamVolume(int streamType)1007     public int getLastAudibleStreamVolume(int streamType) {
1008         IAudioService service = getService();
1009         try {
1010             if (mUseMasterVolume) {
1011                 return service.getLastAudibleMasterVolume();
1012             } else {
1013                 return service.getLastAudibleStreamVolume(streamType);
1014             }
1015         } catch (RemoteException e) {
1016             Log.e(TAG, "Dead object in getLastAudibleStreamVolume", e);
1017             return 0;
1018         }
1019     }
1020 
1021     /**
1022      * Get the stream type whose volume is driving the UI sounds volume.
1023      * UI sounds are screen lock/unlock, camera shutter, key clicks...
1024      * It is assumed that this stream type is also tied to ringer mode changes.
1025      * @hide
1026      */
getMasterStreamType()1027     public int getMasterStreamType() {
1028         IAudioService service = getService();
1029         try {
1030             return service.getMasterStreamType();
1031         } catch (RemoteException e) {
1032             Log.e(TAG, "Dead object in getMasterStreamType", e);
1033             return STREAM_RING;
1034         }
1035     }
1036 
1037     /**
1038      * Sets the ringer mode.
1039      * <p>
1040      * Silent mode will mute the volume and will not vibrate. Vibrate mode will
1041      * mute the volume and vibrate. Normal mode will be audible and may vibrate
1042      * according to user settings.
1043      * <p>This method has no effect if the device implements a fixed volume policy
1044      * as indicated by {@link #isVolumeFixed()}.
1045      * @param ringerMode The ringer mode, one of {@link #RINGER_MODE_NORMAL},
1046      *            {@link #RINGER_MODE_SILENT}, or {@link #RINGER_MODE_VIBRATE}.
1047      * @see #getRingerMode()
1048      * @see #isVolumeFixed()
1049      */
setRingerMode(int ringerMode)1050     public void setRingerMode(int ringerMode) {
1051         if (!isValidRingerMode(ringerMode)) {
1052             return;
1053         }
1054         IAudioService service = getService();
1055         try {
1056             service.setRingerModeExternal(ringerMode, mContext.getOpPackageName());
1057         } catch (RemoteException e) {
1058             Log.e(TAG, "Dead object in setRingerMode", e);
1059         }
1060     }
1061 
1062     /**
1063      * Sets the volume index for a particular stream.
1064      * <p>This method has no effect if the device implements a fixed volume policy
1065      * as indicated by {@link #isVolumeFixed()}.
1066      * @param streamType The stream whose volume index should be set.
1067      * @param index The volume index to set. See
1068      *            {@link #getStreamMaxVolume(int)} for the largest valid value.
1069      * @param flags One or more flags.
1070      * @see #getStreamMaxVolume(int)
1071      * @see #getStreamVolume(int)
1072      * @see #isVolumeFixed()
1073      */
setStreamVolume(int streamType, int index, int flags)1074     public void setStreamVolume(int streamType, int index, int flags) {
1075         IAudioService service = getService();
1076         try {
1077             if (mUseMasterVolume) {
1078                 service.setMasterVolume(index, flags, mContext.getOpPackageName());
1079             } else {
1080                 service.setStreamVolume(streamType, index, flags, mContext.getOpPackageName());
1081             }
1082         } catch (RemoteException e) {
1083             Log.e(TAG, "Dead object in setStreamVolume", e);
1084         }
1085     }
1086 
1087     /**
1088      * Returns the maximum volume index for master volume.
1089      *
1090      * @hide
1091      */
getMasterMaxVolume()1092     public int getMasterMaxVolume() {
1093         IAudioService service = getService();
1094         try {
1095             return service.getMasterMaxVolume();
1096         } catch (RemoteException e) {
1097             Log.e(TAG, "Dead object in getMasterMaxVolume", e);
1098             return 0;
1099         }
1100     }
1101 
1102     /**
1103      * Returns the current volume index for master volume.
1104      *
1105      * @return The current volume index for master volume.
1106      * @hide
1107      */
getMasterVolume()1108     public int getMasterVolume() {
1109         IAudioService service = getService();
1110         try {
1111             return service.getMasterVolume();
1112         } catch (RemoteException e) {
1113             Log.e(TAG, "Dead object in getMasterVolume", e);
1114             return 0;
1115         }
1116     }
1117 
1118     /**
1119      * Get last audible volume before master volume was muted.
1120      *
1121      * @hide
1122      */
getLastAudibleMasterVolume()1123     public int getLastAudibleMasterVolume() {
1124         IAudioService service = getService();
1125         try {
1126             return service.getLastAudibleMasterVolume();
1127         } catch (RemoteException e) {
1128             Log.e(TAG, "Dead object in getLastAudibleMasterVolume", e);
1129             return 0;
1130         }
1131     }
1132 
1133     /**
1134      * Sets the volume index for master volume.
1135      *
1136      * @param index The volume index to set. See
1137      *            {@link #getMasterMaxVolume()} for the largest valid value.
1138      * @param flags One or more flags.
1139      * @see #getMasterMaxVolume()
1140      * @see #getMasterVolume()
1141      * @hide
1142      */
setMasterVolume(int index, int flags)1143     public void setMasterVolume(int index, int flags) {
1144         IAudioService service = getService();
1145         try {
1146             service.setMasterVolume(index, flags, mContext.getOpPackageName());
1147         } catch (RemoteException e) {
1148             Log.e(TAG, "Dead object in setMasterVolume", e);
1149         }
1150     }
1151 
1152     /**
1153      * Solo or unsolo a particular stream. All other streams are muted.
1154      * <p>
1155      * The solo command is protected against client process death: if a process
1156      * with an active solo request on a stream dies, all streams that were muted
1157      * because of this request will be unmuted automatically.
1158      * <p>
1159      * The solo requests for a given stream are cumulative: the AudioManager
1160      * can receive several solo requests from one or more clients and the stream
1161      * will be unsoloed only when the same number of unsolo requests are received.
1162      * <p>
1163      * For a better user experience, applications MUST unsolo a soloed stream
1164      * in onPause() and solo is again in onResume() if appropriate.
1165      * <p>This method has no effect if the device implements a fixed volume policy
1166      * as indicated by {@link #isVolumeFixed()}.
1167      *
1168      * @param streamType The stream to be soloed/unsoloed.
1169      * @param state The required solo state: true for solo ON, false for solo OFF
1170      *
1171      * @see #isVolumeFixed()
1172      */
setStreamSolo(int streamType, boolean state)1173     public void setStreamSolo(int streamType, boolean state) {
1174         IAudioService service = getService();
1175         try {
1176             service.setStreamSolo(streamType, state, mICallBack);
1177         } catch (RemoteException e) {
1178             Log.e(TAG, "Dead object in setStreamSolo", e);
1179         }
1180     }
1181 
1182     /**
1183      * Mute or unmute an audio stream.
1184      * <p>
1185      * The mute command is protected against client process death: if a process
1186      * with an active mute request on a stream dies, this stream will be unmuted
1187      * automatically.
1188      * <p>
1189      * The mute requests for a given stream are cumulative: the AudioManager
1190      * can receive several mute requests from one or more clients and the stream
1191      * will be unmuted only when the same number of unmute requests are received.
1192      * <p>
1193      * For a better user experience, applications MUST unmute a muted stream
1194      * in onPause() and mute is again in onResume() if appropriate.
1195      * <p>
1196      * This method should only be used by applications that replace the platform-wide
1197      * management of audio settings or the main telephony application.
1198      * <p>This method has no effect if the device implements a fixed volume policy
1199      * as indicated by {@link #isVolumeFixed()}.
1200      *
1201      * @param streamType The stream to be muted/unmuted.
1202      * @param state The required mute state: true for mute ON, false for mute OFF
1203      *
1204      * @see #isVolumeFixed()
1205      */
setStreamMute(int streamType, boolean state)1206     public void setStreamMute(int streamType, boolean state) {
1207         IAudioService service = getService();
1208         try {
1209             service.setStreamMute(streamType, state, mICallBack);
1210         } catch (RemoteException e) {
1211             Log.e(TAG, "Dead object in setStreamMute", e);
1212         }
1213     }
1214 
1215     /**
1216      * get stream mute state.
1217      *
1218      * @hide
1219      */
isStreamMute(int streamType)1220     public boolean isStreamMute(int streamType) {
1221         IAudioService service = getService();
1222         try {
1223             return service.isStreamMute(streamType);
1224         } catch (RemoteException e) {
1225             Log.e(TAG, "Dead object in isStreamMute", e);
1226             return false;
1227         }
1228     }
1229 
1230     /**
1231      * set master mute state.
1232      *
1233      * @hide
1234      */
setMasterMute(boolean state)1235     public void setMasterMute(boolean state) {
1236         setMasterMute(state, FLAG_SHOW_UI);
1237     }
1238 
1239     /**
1240      * set master mute state with optional flags.
1241      *
1242      * @hide
1243      */
setMasterMute(boolean state, int flags)1244     public void setMasterMute(boolean state, int flags) {
1245         IAudioService service = getService();
1246         try {
1247             service.setMasterMute(state, flags, mContext.getOpPackageName(), mICallBack);
1248         } catch (RemoteException e) {
1249             Log.e(TAG, "Dead object in setMasterMute", e);
1250         }
1251     }
1252 
1253     /**
1254      * get master mute state.
1255      *
1256      * @hide
1257      */
isMasterMute()1258     public boolean isMasterMute() {
1259         IAudioService service = getService();
1260         try {
1261             return service.isMasterMute();
1262         } catch (RemoteException e) {
1263             Log.e(TAG, "Dead object in isMasterMute", e);
1264             return false;
1265         }
1266     }
1267 
1268     /**
1269      * forces the stream controlled by hard volume keys
1270      * specifying streamType == -1 releases control to the
1271      * logic.
1272      *
1273      * @hide
1274      */
forceVolumeControlStream(int streamType)1275     public void forceVolumeControlStream(int streamType) {
1276         if (mUseMasterVolume) {
1277             return;
1278         }
1279         IAudioService service = getService();
1280         try {
1281             service.forceVolumeControlStream(streamType, mICallBack);
1282         } catch (RemoteException e) {
1283             Log.e(TAG, "Dead object in forceVolumeControlStream", e);
1284         }
1285     }
1286 
1287     /**
1288      * Returns whether a particular type should vibrate according to user
1289      * settings and the current ringer mode.
1290      * <p>
1291      * This shouldn't be needed by most clients that use notifications to
1292      * vibrate. The notification manager will not vibrate if the policy doesn't
1293      * allow it, so the client should always set a vibrate pattern and let the
1294      * notification manager control whether or not to actually vibrate.
1295      *
1296      * @param vibrateType The type of vibrate. One of
1297      *            {@link #VIBRATE_TYPE_NOTIFICATION} or
1298      *            {@link #VIBRATE_TYPE_RINGER}.
1299      * @return Whether the type should vibrate at the instant this method is
1300      *         called.
1301      * @see #setVibrateSetting(int, int)
1302      * @see #getVibrateSetting(int)
1303      * @deprecated Applications should maintain their own vibrate policy based on
1304      * current ringer mode that can be queried via {@link #getRingerMode()}.
1305      */
shouldVibrate(int vibrateType)1306     public boolean shouldVibrate(int vibrateType) {
1307         IAudioService service = getService();
1308         try {
1309             return service.shouldVibrate(vibrateType);
1310         } catch (RemoteException e) {
1311             Log.e(TAG, "Dead object in shouldVibrate", e);
1312             return false;
1313         }
1314     }
1315 
1316     /**
1317      * Returns whether the user's vibrate setting for a vibrate type.
1318      * <p>
1319      * This shouldn't be needed by most clients that want to vibrate, instead
1320      * see {@link #shouldVibrate(int)}.
1321      *
1322      * @param vibrateType The type of vibrate. One of
1323      *            {@link #VIBRATE_TYPE_NOTIFICATION} or
1324      *            {@link #VIBRATE_TYPE_RINGER}.
1325      * @return The vibrate setting, one of {@link #VIBRATE_SETTING_ON},
1326      *         {@link #VIBRATE_SETTING_OFF}, or
1327      *         {@link #VIBRATE_SETTING_ONLY_SILENT}.
1328      * @see #setVibrateSetting(int, int)
1329      * @see #shouldVibrate(int)
1330      * @deprecated Applications should maintain their own vibrate policy based on
1331      * current ringer mode that can be queried via {@link #getRingerMode()}.
1332      */
getVibrateSetting(int vibrateType)1333     public int getVibrateSetting(int vibrateType) {
1334         IAudioService service = getService();
1335         try {
1336             return service.getVibrateSetting(vibrateType);
1337         } catch (RemoteException e) {
1338             Log.e(TAG, "Dead object in getVibrateSetting", e);
1339             return VIBRATE_SETTING_OFF;
1340         }
1341     }
1342 
1343     /**
1344      * Sets the setting for when the vibrate type should vibrate.
1345      * <p>
1346      * This method should only be used by applications that replace the platform-wide
1347      * management of audio settings or the main telephony application.
1348      *
1349      * @param vibrateType The type of vibrate. One of
1350      *            {@link #VIBRATE_TYPE_NOTIFICATION} or
1351      *            {@link #VIBRATE_TYPE_RINGER}.
1352      * @param vibrateSetting The vibrate setting, one of
1353      *            {@link #VIBRATE_SETTING_ON},
1354      *            {@link #VIBRATE_SETTING_OFF}, or
1355      *            {@link #VIBRATE_SETTING_ONLY_SILENT}.
1356      * @see #getVibrateSetting(int)
1357      * @see #shouldVibrate(int)
1358      * @deprecated Applications should maintain their own vibrate policy based on
1359      * current ringer mode that can be queried via {@link #getRingerMode()}.
1360      */
setVibrateSetting(int vibrateType, int vibrateSetting)1361     public void setVibrateSetting(int vibrateType, int vibrateSetting) {
1362         IAudioService service = getService();
1363         try {
1364             service.setVibrateSetting(vibrateType, vibrateSetting);
1365         } catch (RemoteException e) {
1366             Log.e(TAG, "Dead object in setVibrateSetting", e);
1367         }
1368     }
1369 
1370     /**
1371      * Sets the speakerphone on or off.
1372      * <p>
1373      * This method should only be used by applications that replace the platform-wide
1374      * management of audio settings or the main telephony application.
1375      *
1376      * @param on set <var>true</var> to turn on speakerphone;
1377      *           <var>false</var> to turn it off
1378      */
setSpeakerphoneOn(boolean on)1379     public void setSpeakerphoneOn(boolean on){
1380         IAudioService service = getService();
1381         try {
1382             service.setSpeakerphoneOn(on);
1383         } catch (RemoteException e) {
1384             Log.e(TAG, "Dead object in setSpeakerphoneOn", e);
1385         }
1386     }
1387 
1388     /**
1389      * Checks whether the speakerphone is on or off.
1390      *
1391      * @return true if speakerphone is on, false if it's off
1392      */
isSpeakerphoneOn()1393     public boolean isSpeakerphoneOn() {
1394         IAudioService service = getService();
1395         try {
1396             return service.isSpeakerphoneOn();
1397         } catch (RemoteException e) {
1398             Log.e(TAG, "Dead object in isSpeakerphoneOn", e);
1399             return false;
1400         }
1401      }
1402 
1403     //====================================================================
1404     // Bluetooth SCO control
1405     /**
1406      * Sticky broadcast intent action indicating that the bluetoooth SCO audio
1407      * connection state has changed. The intent contains on extra {@link #EXTRA_SCO_AUDIO_STATE}
1408      * indicating the new state which is either {@link #SCO_AUDIO_STATE_DISCONNECTED}
1409      * or {@link #SCO_AUDIO_STATE_CONNECTED}
1410      *
1411      * @see #startBluetoothSco()
1412      * @deprecated Use  {@link #ACTION_SCO_AUDIO_STATE_UPDATED} instead
1413      */
1414     @Deprecated
1415     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
1416     public static final String ACTION_SCO_AUDIO_STATE_CHANGED =
1417             "android.media.SCO_AUDIO_STATE_CHANGED";
1418 
1419      /**
1420      * Sticky broadcast intent action indicating that the bluetoooth SCO audio
1421      * connection state has been updated.
1422      * <p>This intent has two extras:
1423      * <ul>
1424      *   <li> {@link #EXTRA_SCO_AUDIO_STATE} - The new SCO audio state. </li>
1425      *   <li> {@link #EXTRA_SCO_AUDIO_PREVIOUS_STATE}- The previous SCO audio state. </li>
1426      * </ul>
1427      * <p> EXTRA_SCO_AUDIO_STATE or EXTRA_SCO_AUDIO_PREVIOUS_STATE can be any of:
1428      * <ul>
1429      *   <li> {@link #SCO_AUDIO_STATE_DISCONNECTED}, </li>
1430      *   <li> {@link #SCO_AUDIO_STATE_CONNECTING} or </li>
1431      *   <li> {@link #SCO_AUDIO_STATE_CONNECTED}, </li>
1432      * </ul>
1433      * @see #startBluetoothSco()
1434      */
1435     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
1436     public static final String ACTION_SCO_AUDIO_STATE_UPDATED =
1437             "android.media.ACTION_SCO_AUDIO_STATE_UPDATED";
1438 
1439     /**
1440      * Extra for intent {@link #ACTION_SCO_AUDIO_STATE_CHANGED} or
1441      * {@link #ACTION_SCO_AUDIO_STATE_UPDATED} containing the new bluetooth SCO connection state.
1442      */
1443     public static final String EXTRA_SCO_AUDIO_STATE =
1444             "android.media.extra.SCO_AUDIO_STATE";
1445 
1446     /**
1447      * Extra for intent {@link #ACTION_SCO_AUDIO_STATE_UPDATED} containing the previous
1448      * bluetooth SCO connection state.
1449      */
1450     public static final String EXTRA_SCO_AUDIO_PREVIOUS_STATE =
1451             "android.media.extra.SCO_AUDIO_PREVIOUS_STATE";
1452 
1453     /**
1454      * Value for extra EXTRA_SCO_AUDIO_STATE or EXTRA_SCO_AUDIO_PREVIOUS_STATE
1455      * indicating that the SCO audio channel is not established
1456      */
1457     public static final int SCO_AUDIO_STATE_DISCONNECTED = 0;
1458     /**
1459      * Value for extra {@link #EXTRA_SCO_AUDIO_STATE} or {@link #EXTRA_SCO_AUDIO_PREVIOUS_STATE}
1460      * indicating that the SCO audio channel is established
1461      */
1462     public static final int SCO_AUDIO_STATE_CONNECTED = 1;
1463     /**
1464      * Value for extra EXTRA_SCO_AUDIO_STATE or EXTRA_SCO_AUDIO_PREVIOUS_STATE
1465      * indicating that the SCO audio channel is being established
1466      */
1467     public static final int SCO_AUDIO_STATE_CONNECTING = 2;
1468     /**
1469      * Value for extra EXTRA_SCO_AUDIO_STATE indicating that
1470      * there was an error trying to obtain the state
1471      */
1472     public static final int SCO_AUDIO_STATE_ERROR = -1;
1473 
1474 
1475     /**
1476      * Indicates if current platform supports use of SCO for off call use cases.
1477      * Application wanted to use bluetooth SCO audio when the phone is not in call
1478      * must first call this method to make sure that the platform supports this
1479      * feature.
1480      * @return true if bluetooth SCO can be used for audio when not in call
1481      *         false otherwise
1482      * @see #startBluetoothSco()
1483     */
isBluetoothScoAvailableOffCall()1484     public boolean isBluetoothScoAvailableOffCall() {
1485         return mContext.getResources().getBoolean(
1486                com.android.internal.R.bool.config_bluetooth_sco_off_call);
1487     }
1488 
1489     /**
1490      * Start bluetooth SCO audio connection.
1491      * <p>Requires Permission:
1492      *   {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}.
1493      * <p>This method can be used by applications wanting to send and received audio
1494      * to/from a bluetooth SCO headset while the phone is not in call.
1495      * <p>As the SCO connection establishment can take several seconds,
1496      * applications should not rely on the connection to be available when the method
1497      * returns but instead register to receive the intent {@link #ACTION_SCO_AUDIO_STATE_UPDATED}
1498      * and wait for the state to be {@link #SCO_AUDIO_STATE_CONNECTED}.
1499      * <p>As the ACTION_SCO_AUDIO_STATE_UPDATED intent is sticky, the application can check the SCO
1500      * audio state before calling startBluetoothSco() by reading the intent returned by the receiver
1501      * registration. If the state is already CONNECTED, no state change will be received via the
1502      * intent after calling startBluetoothSco(). It is however useful to call startBluetoothSco()
1503      * so that the connection stays active in case the current initiator stops the connection.
1504      * <p>Unless the connection is already active as described above, the state will always
1505      * transition from DISCONNECTED to CONNECTING and then either to CONNECTED if the connection
1506      * succeeds or back to DISCONNECTED if the connection fails (e.g no headset is connected).
1507      * <p>When finished with the SCO connection or if the establishment fails, the application must
1508      * call {@link #stopBluetoothSco()} to clear the request and turn down the bluetooth connection.
1509      * <p>Even if a SCO connection is established, the following restrictions apply on audio
1510      * output streams so that they can be routed to SCO headset:
1511      * <ul>
1512      *   <li> the stream type must be {@link #STREAM_VOICE_CALL} </li>
1513      *   <li> the format must be mono </li>
1514      *   <li> the sampling must be 16kHz or 8kHz </li>
1515      * </ul>
1516      * <p>The following restrictions apply on input streams:
1517      * <ul>
1518      *   <li> the format must be mono </li>
1519      *   <li> the sampling must be 8kHz </li>
1520      * </ul>
1521      * <p>Note that the phone application always has the priority on the usage of the SCO
1522      * connection for telephony. If this method is called while the phone is in call
1523      * it will be ignored. Similarly, if a call is received or sent while an application
1524      * is using the SCO connection, the connection will be lost for the application and NOT
1525      * returned automatically when the call ends.
1526      * <p>NOTE: up to and including API version
1527      * {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}, this method initiates a virtual
1528      * voice call to the bluetooth headset.
1529      * After API version {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2} only a raw SCO audio
1530      * connection is established.
1531      * @see #stopBluetoothSco()
1532      * @see #ACTION_SCO_AUDIO_STATE_UPDATED
1533      */
startBluetoothSco()1534     public void startBluetoothSco(){
1535         IAudioService service = getService();
1536         try {
1537             service.startBluetoothSco(mICallBack, mContext.getApplicationInfo().targetSdkVersion);
1538         } catch (RemoteException e) {
1539             Log.e(TAG, "Dead object in startBluetoothSco", e);
1540         }
1541     }
1542 
1543     /**
1544      * @hide
1545      * Start bluetooth SCO audio connection in virtual call mode.
1546      * <p>Requires Permission:
1547      *   {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}.
1548      * <p>Similar to {@link #startBluetoothSco()} with explicit selection of virtual call mode.
1549      * Telephony and communication applications (VoIP, Video Chat) should preferably select
1550      * virtual call mode.
1551      * Applications using voice input for search or commands should first try raw audio connection
1552      * with {@link #startBluetoothSco()} and fall back to startBluetoothScoVirtualCall() in case of
1553      * failure.
1554      * @see #startBluetoothSco()
1555      * @see #stopBluetoothSco()
1556      * @see #ACTION_SCO_AUDIO_STATE_UPDATED
1557      */
startBluetoothScoVirtualCall()1558     public void startBluetoothScoVirtualCall() {
1559         IAudioService service = getService();
1560         try {
1561             service.startBluetoothScoVirtualCall(mICallBack);
1562         } catch (RemoteException e) {
1563             Log.e(TAG, "Dead object in startBluetoothScoVirtualCall", e);
1564         }
1565     }
1566 
1567     /**
1568      * Stop bluetooth SCO audio connection.
1569      * <p>Requires Permission:
1570      *   {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}.
1571      * <p>This method must be called by applications having requested the use of
1572      * bluetooth SCO audio with {@link #startBluetoothSco()} when finished with the SCO
1573      * connection or if connection fails.
1574      * @see #startBluetoothSco()
1575      */
1576     // Also used for connections started with {@link #startBluetoothScoVirtualCall()}
stopBluetoothSco()1577     public void stopBluetoothSco(){
1578         IAudioService service = getService();
1579         try {
1580             service.stopBluetoothSco(mICallBack);
1581         } catch (RemoteException e) {
1582             Log.e(TAG, "Dead object in stopBluetoothSco", e);
1583         }
1584     }
1585 
1586     /**
1587      * Request use of Bluetooth SCO headset for communications.
1588      * <p>
1589      * This method should only be used by applications that replace the platform-wide
1590      * management of audio settings or the main telephony application.
1591      *
1592      * @param on set <var>true</var> to use bluetooth SCO for communications;
1593      *               <var>false</var> to not use bluetooth SCO for communications
1594      */
setBluetoothScoOn(boolean on)1595     public void setBluetoothScoOn(boolean on){
1596         IAudioService service = getService();
1597         try {
1598             service.setBluetoothScoOn(on);
1599         } catch (RemoteException e) {
1600             Log.e(TAG, "Dead object in setBluetoothScoOn", e);
1601         }
1602     }
1603 
1604     /**
1605      * Checks whether communications use Bluetooth SCO.
1606      *
1607      * @return true if SCO is used for communications;
1608      *         false if otherwise
1609      */
isBluetoothScoOn()1610     public boolean isBluetoothScoOn() {
1611         IAudioService service = getService();
1612         try {
1613             return service.isBluetoothScoOn();
1614         } catch (RemoteException e) {
1615             Log.e(TAG, "Dead object in isBluetoothScoOn", e);
1616             return false;
1617         }
1618     }
1619 
1620     /**
1621      * @param on set <var>true</var> to route A2DP audio to/from Bluetooth
1622      *           headset; <var>false</var> disable A2DP audio
1623      * @deprecated Do not use.
1624      */
setBluetoothA2dpOn(boolean on)1625     @Deprecated public void setBluetoothA2dpOn(boolean on){
1626     }
1627 
1628     /**
1629      * Checks whether A2DP audio routing to the Bluetooth headset is on or off.
1630      *
1631      * @return true if A2DP audio is being routed to/from Bluetooth headset;
1632      *         false if otherwise
1633      */
isBluetoothA2dpOn()1634     public boolean isBluetoothA2dpOn() {
1635         if (AudioSystem.getDeviceConnectionState(DEVICE_OUT_BLUETOOTH_A2DP,"")
1636             == AudioSystem.DEVICE_STATE_UNAVAILABLE) {
1637             return false;
1638         } else {
1639             return true;
1640         }
1641     }
1642 
1643     /**
1644      * Sets audio routing to the wired headset on or off.
1645      *
1646      * @param on set <var>true</var> to route audio to/from wired
1647      *           headset; <var>false</var> disable wired headset audio
1648      * @deprecated Do not use.
1649      */
setWiredHeadsetOn(boolean on)1650     @Deprecated public void setWiredHeadsetOn(boolean on){
1651     }
1652 
1653     /**
1654      * Checks whether a wired headset is connected or not.
1655      * <p>This is not a valid indication that audio playback is
1656      * actually over the wired headset as audio routing depends on other conditions.
1657      *
1658      * @return true if a wired headset is connected.
1659      *         false if otherwise
1660      * @deprecated Use only to check is a headset is connected or not.
1661      */
isWiredHeadsetOn()1662     public boolean isWiredHeadsetOn() {
1663         if (AudioSystem.getDeviceConnectionState(DEVICE_OUT_WIRED_HEADSET,"")
1664                 == AudioSystem.DEVICE_STATE_UNAVAILABLE &&
1665             AudioSystem.getDeviceConnectionState(DEVICE_OUT_WIRED_HEADPHONE,"")
1666                 == AudioSystem.DEVICE_STATE_UNAVAILABLE) {
1667             return false;
1668         } else {
1669             return true;
1670         }
1671     }
1672 
1673     /**
1674      * Sets the microphone mute on or off.
1675      * <p>
1676      * This method should only be used by applications that replace the platform-wide
1677      * management of audio settings or the main telephony application.
1678      *
1679      * @param on set <var>true</var> to mute the microphone;
1680      *           <var>false</var> to turn mute off
1681      */
setMicrophoneMute(boolean on)1682     public void setMicrophoneMute(boolean on){
1683         IAudioService service = getService();
1684         try {
1685             service.setMicrophoneMute(on, mContext.getOpPackageName());
1686         } catch (RemoteException e) {
1687             Log.e(TAG, "Dead object in setMicrophoneMute", e);
1688         }
1689     }
1690 
1691     /**
1692      * Checks whether the microphone mute is on or off.
1693      *
1694      * @return true if microphone is muted, false if it's not
1695      */
isMicrophoneMute()1696     public boolean isMicrophoneMute() {
1697         return AudioSystem.isMicrophoneMuted();
1698     }
1699 
1700     /**
1701      * Sets the audio mode.
1702      * <p>
1703      * The audio mode encompasses audio routing AND the behavior of
1704      * the telephony layer. Therefore this method should only be used by applications that
1705      * replace the platform-wide management of audio settings or the main telephony application.
1706      * In particular, the {@link #MODE_IN_CALL} mode should only be used by the telephony
1707      * application when it places a phone call, as it will cause signals from the radio layer
1708      * to feed the platform mixer.
1709      *
1710      * @param mode  the requested audio mode ({@link #MODE_NORMAL}, {@link #MODE_RINGTONE},
1711      *              {@link #MODE_IN_CALL} or {@link #MODE_IN_COMMUNICATION}).
1712      *              Informs the HAL about the current audio state so that
1713      *              it can route the audio appropriately.
1714      */
setMode(int mode)1715     public void setMode(int mode) {
1716         IAudioService service = getService();
1717         try {
1718             service.setMode(mode, mICallBack);
1719         } catch (RemoteException e) {
1720             Log.e(TAG, "Dead object in setMode", e);
1721         }
1722     }
1723 
1724     /**
1725      * Returns the current audio mode.
1726      *
1727      * @return      the current audio mode ({@link #MODE_NORMAL}, {@link #MODE_RINGTONE},
1728      *              {@link #MODE_IN_CALL} or {@link #MODE_IN_COMMUNICATION}).
1729      *              Returns the current current audio state from the HAL.
1730      */
getMode()1731     public int getMode() {
1732         IAudioService service = getService();
1733         try {
1734             return service.getMode();
1735         } catch (RemoteException e) {
1736             Log.e(TAG, "Dead object in getMode", e);
1737             return MODE_INVALID;
1738         }
1739     }
1740 
1741     /* modes for setMode/getMode/setRoute/getRoute */
1742     /**
1743      * Audio harware modes.
1744      */
1745     /**
1746      * Invalid audio mode.
1747      */
1748     public static final int MODE_INVALID            = AudioSystem.MODE_INVALID;
1749     /**
1750      * Current audio mode. Used to apply audio routing to current mode.
1751      */
1752     public static final int MODE_CURRENT            = AudioSystem.MODE_CURRENT;
1753     /**
1754      * Normal audio mode: not ringing and no call established.
1755      */
1756     public static final int MODE_NORMAL             = AudioSystem.MODE_NORMAL;
1757     /**
1758      * Ringing audio mode. An incoming is being signaled.
1759      */
1760     public static final int MODE_RINGTONE           = AudioSystem.MODE_RINGTONE;
1761     /**
1762      * In call audio mode. A telephony call is established.
1763      */
1764     public static final int MODE_IN_CALL            = AudioSystem.MODE_IN_CALL;
1765     /**
1766      * In communication audio mode. An audio/video chat or VoIP call is established.
1767      */
1768     public static final int MODE_IN_COMMUNICATION   = AudioSystem.MODE_IN_COMMUNICATION;
1769 
1770     /* Routing bits for setRouting/getRouting API */
1771     /**
1772      * Routing audio output to earpiece
1773      * @deprecated   Do not set audio routing directly, use setSpeakerphoneOn(),
1774      * setBluetoothScoOn() methods instead.
1775      */
1776     @Deprecated public static final int ROUTE_EARPIECE          = AudioSystem.ROUTE_EARPIECE;
1777     /**
1778      * Routing audio output to speaker
1779      * @deprecated   Do not set audio routing directly, use setSpeakerphoneOn(),
1780      * setBluetoothScoOn() methods instead.
1781      */
1782     @Deprecated public static final int ROUTE_SPEAKER           = AudioSystem.ROUTE_SPEAKER;
1783     /**
1784      * @deprecated use {@link #ROUTE_BLUETOOTH_SCO}
1785      * @deprecated   Do not set audio routing directly, use setSpeakerphoneOn(),
1786      * setBluetoothScoOn() methods instead.
1787      */
1788     @Deprecated public static final int ROUTE_BLUETOOTH = AudioSystem.ROUTE_BLUETOOTH_SCO;
1789     /**
1790      * Routing audio output to bluetooth SCO
1791      * @deprecated   Do not set audio routing directly, use setSpeakerphoneOn(),
1792      * setBluetoothScoOn() methods instead.
1793      */
1794     @Deprecated public static final int ROUTE_BLUETOOTH_SCO     = AudioSystem.ROUTE_BLUETOOTH_SCO;
1795     /**
1796      * Routing audio output to headset
1797      * @deprecated   Do not set audio routing directly, use setSpeakerphoneOn(),
1798      * setBluetoothScoOn() methods instead.
1799      */
1800     @Deprecated public static final int ROUTE_HEADSET           = AudioSystem.ROUTE_HEADSET;
1801     /**
1802      * Routing audio output to bluetooth A2DP
1803      * @deprecated   Do not set audio routing directly, use setSpeakerphoneOn(),
1804      * setBluetoothScoOn() methods instead.
1805      */
1806     @Deprecated public static final int ROUTE_BLUETOOTH_A2DP    = AudioSystem.ROUTE_BLUETOOTH_A2DP;
1807     /**
1808      * Used for mask parameter of {@link #setRouting(int,int,int)}.
1809      * @deprecated   Do not set audio routing directly, use setSpeakerphoneOn(),
1810      * setBluetoothScoOn() methods instead.
1811      */
1812     @Deprecated public static final int ROUTE_ALL               = AudioSystem.ROUTE_ALL;
1813 
1814     /**
1815      * Sets the audio routing for a specified mode
1816      *
1817      * @param mode   audio mode to change route. E.g., MODE_RINGTONE.
1818      * @param routes bit vector of routes requested, created from one or
1819      *               more of ROUTE_xxx types. Set bits indicate that route should be on
1820      * @param mask   bit vector of routes to change, created from one or more of
1821      * ROUTE_xxx types. Unset bits indicate the route should be left unchanged
1822      *
1823      * @deprecated   Do not set audio routing directly, use setSpeakerphoneOn(),
1824      * setBluetoothScoOn() methods instead.
1825      */
1826     @Deprecated
setRouting(int mode, int routes, int mask)1827     public void setRouting(int mode, int routes, int mask) {
1828     }
1829 
1830     /**
1831      * Returns the current audio routing bit vector for a specified mode.
1832      *
1833      * @param mode audio mode to get route (e.g., MODE_RINGTONE)
1834      * @return an audio route bit vector that can be compared with ROUTE_xxx
1835      * bits
1836      * @deprecated   Do not query audio routing directly, use isSpeakerphoneOn(),
1837      * isBluetoothScoOn(), isBluetoothA2dpOn() and isWiredHeadsetOn() methods instead.
1838      */
1839     @Deprecated
getRouting(int mode)1840     public int getRouting(int mode) {
1841         return -1;
1842     }
1843 
1844     /**
1845      * Checks whether any music is active.
1846      *
1847      * @return true if any music tracks are active.
1848      */
isMusicActive()1849     public boolean isMusicActive() {
1850         return AudioSystem.isStreamActive(STREAM_MUSIC, 0);
1851     }
1852 
1853     /**
1854      * @hide
1855      * Checks whether any music or media is actively playing on a remote device (e.g. wireless
1856      *   display). Note that BT audio sinks are not considered remote devices.
1857      * @return true if {@link AudioManager#STREAM_MUSIC} is active on a remote device
1858      */
isMusicActiveRemotely()1859     public boolean isMusicActiveRemotely() {
1860         return AudioSystem.isStreamActiveRemotely(STREAM_MUSIC, 0);
1861     }
1862 
1863     /**
1864      * @hide
1865      * Checks whether the current audio focus is exclusive.
1866      * @return true if the top of the audio focus stack requested focus
1867      *     with {@link #AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE}
1868      */
isAudioFocusExclusive()1869     public boolean isAudioFocusExclusive() {
1870         IAudioService service = getService();
1871         try {
1872             return service.getCurrentAudioFocus() == AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE;
1873         } catch (RemoteException e) {
1874             Log.e(TAG, "Dead object in isAudioFocusExclusive()", e);
1875             return false;
1876         }
1877     }
1878 
1879     /**
1880      * Return a new audio session identifier not associated with any player or effect.
1881      * An audio session identifier is a system wide unique identifier for a set of audio streams
1882      * (one or more mixed together).
1883      * <p>The primary use of the audio session ID is to associate audio effects to audio players,
1884      * such as {@link MediaPlayer} or {@link AudioTrack}: all audio effects sharing the same audio
1885      * session ID will be applied to the mixed audio content of the players that share the same
1886      * audio session.
1887      * <p>This method can for instance be used when creating one of the
1888      * {@link android.media.audiofx.AudioEffect} objects to define the audio session of the effect,
1889      * or to specify a session for a speech synthesis utterance
1890      * in {@link android.speech.tts.TextToSpeech.Engine}.
1891      * @return a new unclaimed and unused audio session identifier, or {@link #ERROR} when the
1892      *   system failed to generate a new session, a condition in which audio playback or recording
1893      *   will subsequently fail as well.
1894      */
generateAudioSessionId()1895     public int generateAudioSessionId() {
1896         int session = AudioSystem.newAudioSessionId();
1897         if (session > 0) {
1898             return session;
1899         } else {
1900             Log.e(TAG, "Failure to generate a new audio session ID");
1901             return ERROR;
1902         }
1903     }
1904 
1905     /**
1906      * A special audio session ID to indicate that the audio session ID isn't known and the
1907      * framework should generate a new value. This can be used when building a new
1908      * {@link AudioTrack} instance with
1909      * {@link AudioTrack#AudioTrack(AudioAttributes, AudioFormat, int, int, int)}.
1910      */
1911     public static final int AUDIO_SESSION_ID_GENERATE = AudioSystem.AUDIO_SESSION_ALLOCATE;
1912 
1913 
1914     /*
1915      * Sets a generic audio configuration parameter. The use of these parameters
1916      * are platform dependant, see libaudio
1917      *
1918      * ** Temporary interface - DO NOT USE
1919      *
1920      * TODO: Replace with a more generic key:value get/set mechanism
1921      *
1922      * param key   name of parameter to set. Must not be null.
1923      * param value value of parameter. Must not be null.
1924      */
1925     /**
1926      * @hide
1927      * @deprecated Use {@link #setParameters(String)} instead
1928      */
setParameter(String key, String value)1929     @Deprecated public void setParameter(String key, String value) {
1930         setParameters(key+"="+value);
1931     }
1932 
1933     /**
1934      * Sets a variable number of parameter values to audio hardware.
1935      *
1936      * @param keyValuePairs list of parameters key value pairs in the form:
1937      *    key1=value1;key2=value2;...
1938      *
1939      */
setParameters(String keyValuePairs)1940     public void setParameters(String keyValuePairs) {
1941         AudioSystem.setParameters(keyValuePairs);
1942     }
1943 
1944     /**
1945      * Gets a variable number of parameter values from audio hardware.
1946      *
1947      * @param keys list of parameters
1948      * @return list of parameters key value pairs in the form:
1949      *    key1=value1;key2=value2;...
1950      */
getParameters(String keys)1951     public String getParameters(String keys) {
1952         return AudioSystem.getParameters(keys);
1953     }
1954 
1955     /* Sound effect identifiers */
1956     /**
1957      * Keyboard and direction pad click sound
1958      * @see #playSoundEffect(int)
1959      */
1960     public static final int FX_KEY_CLICK = 0;
1961     /**
1962      * Focus has moved up
1963      * @see #playSoundEffect(int)
1964      */
1965     public static final int FX_FOCUS_NAVIGATION_UP = 1;
1966     /**
1967      * Focus has moved down
1968      * @see #playSoundEffect(int)
1969      */
1970     public static final int FX_FOCUS_NAVIGATION_DOWN = 2;
1971     /**
1972      * Focus has moved left
1973      * @see #playSoundEffect(int)
1974      */
1975     public static final int FX_FOCUS_NAVIGATION_LEFT = 3;
1976     /**
1977      * Focus has moved right
1978      * @see #playSoundEffect(int)
1979      */
1980     public static final int FX_FOCUS_NAVIGATION_RIGHT = 4;
1981     /**
1982      * IME standard keypress sound
1983      * @see #playSoundEffect(int)
1984      */
1985     public static final int FX_KEYPRESS_STANDARD = 5;
1986     /**
1987      * IME spacebar keypress sound
1988      * @see #playSoundEffect(int)
1989      */
1990     public static final int FX_KEYPRESS_SPACEBAR = 6;
1991     /**
1992      * IME delete keypress sound
1993      * @see #playSoundEffect(int)
1994      */
1995     public static final int FX_KEYPRESS_DELETE = 7;
1996     /**
1997      * IME return_keypress sound
1998      * @see #playSoundEffect(int)
1999      */
2000     public static final int FX_KEYPRESS_RETURN = 8;
2001 
2002     /**
2003      * Invalid keypress sound
2004      * @see #playSoundEffect(int)
2005      */
2006     public static final int FX_KEYPRESS_INVALID = 9;
2007     /**
2008      * @hide Number of sound effects
2009      */
2010     public static final int NUM_SOUND_EFFECTS = 10;
2011 
2012     /**
2013      * Plays a sound effect (Key clicks, lid open/close...)
2014      * @param effectType The type of sound effect. One of
2015      *            {@link #FX_KEY_CLICK},
2016      *            {@link #FX_FOCUS_NAVIGATION_UP},
2017      *            {@link #FX_FOCUS_NAVIGATION_DOWN},
2018      *            {@link #FX_FOCUS_NAVIGATION_LEFT},
2019      *            {@link #FX_FOCUS_NAVIGATION_RIGHT},
2020      *            {@link #FX_KEYPRESS_STANDARD},
2021      *            {@link #FX_KEYPRESS_SPACEBAR},
2022      *            {@link #FX_KEYPRESS_DELETE},
2023      *            {@link #FX_KEYPRESS_RETURN},
2024      *            {@link #FX_KEYPRESS_INVALID},
2025      * NOTE: This version uses the UI settings to determine
2026      * whether sounds are heard or not.
2027      */
playSoundEffect(int effectType)2028     public void  playSoundEffect(int effectType) {
2029         if (effectType < 0 || effectType >= NUM_SOUND_EFFECTS) {
2030             return;
2031         }
2032 
2033         if (!querySoundEffectsEnabled(Process.myUserHandle().getIdentifier())) {
2034             return;
2035         }
2036 
2037         IAudioService service = getService();
2038         try {
2039             service.playSoundEffect(effectType);
2040         } catch (RemoteException e) {
2041             Log.e(TAG, "Dead object in playSoundEffect"+e);
2042         }
2043     }
2044 
2045     /**
2046      * Plays a sound effect (Key clicks, lid open/close...)
2047      * @param effectType The type of sound effect. One of
2048      *            {@link #FX_KEY_CLICK},
2049      *            {@link #FX_FOCUS_NAVIGATION_UP},
2050      *            {@link #FX_FOCUS_NAVIGATION_DOWN},
2051      *            {@link #FX_FOCUS_NAVIGATION_LEFT},
2052      *            {@link #FX_FOCUS_NAVIGATION_RIGHT},
2053      *            {@link #FX_KEYPRESS_STANDARD},
2054      *            {@link #FX_KEYPRESS_SPACEBAR},
2055      *            {@link #FX_KEYPRESS_DELETE},
2056      *            {@link #FX_KEYPRESS_RETURN},
2057      *            {@link #FX_KEYPRESS_INVALID},
2058      * @param userId The current user to pull sound settings from
2059      * NOTE: This version uses the UI settings to determine
2060      * whether sounds are heard or not.
2061      * @hide
2062      */
playSoundEffect(int effectType, int userId)2063     public void  playSoundEffect(int effectType, int userId) {
2064         if (effectType < 0 || effectType >= NUM_SOUND_EFFECTS) {
2065             return;
2066         }
2067 
2068         if (!querySoundEffectsEnabled(userId)) {
2069             return;
2070         }
2071 
2072         IAudioService service = getService();
2073         try {
2074             service.playSoundEffect(effectType);
2075         } catch (RemoteException e) {
2076             Log.e(TAG, "Dead object in playSoundEffect"+e);
2077         }
2078     }
2079 
2080     /**
2081      * Plays a sound effect (Key clicks, lid open/close...)
2082      * @param effectType The type of sound effect. One of
2083      *            {@link #FX_KEY_CLICK},
2084      *            {@link #FX_FOCUS_NAVIGATION_UP},
2085      *            {@link #FX_FOCUS_NAVIGATION_DOWN},
2086      *            {@link #FX_FOCUS_NAVIGATION_LEFT},
2087      *            {@link #FX_FOCUS_NAVIGATION_RIGHT},
2088      *            {@link #FX_KEYPRESS_STANDARD},
2089      *            {@link #FX_KEYPRESS_SPACEBAR},
2090      *            {@link #FX_KEYPRESS_DELETE},
2091      *            {@link #FX_KEYPRESS_RETURN},
2092      *            {@link #FX_KEYPRESS_INVALID},
2093      * @param volume Sound effect volume.
2094      * The volume value is a raw scalar so UI controls should be scaled logarithmically.
2095      * If a volume of -1 is specified, the AudioManager.STREAM_MUSIC stream volume minus 3dB will be used.
2096      * NOTE: This version is for applications that have their own
2097      * settings panel for enabling and controlling volume.
2098      */
playSoundEffect(int effectType, float volume)2099     public void  playSoundEffect(int effectType, float volume) {
2100         if (effectType < 0 || effectType >= NUM_SOUND_EFFECTS) {
2101             return;
2102         }
2103 
2104         IAudioService service = getService();
2105         try {
2106             service.playSoundEffectVolume(effectType, volume);
2107         } catch (RemoteException e) {
2108             Log.e(TAG, "Dead object in playSoundEffect"+e);
2109         }
2110     }
2111 
2112     /**
2113      * Settings has an in memory cache, so this is fast.
2114      */
querySoundEffectsEnabled(int user)2115     private boolean querySoundEffectsEnabled(int user) {
2116         return Settings.System.getIntForUser(mContext.getContentResolver(),
2117                 Settings.System.SOUND_EFFECTS_ENABLED, 0, user) != 0;
2118     }
2119 
2120 
2121     /**
2122      *  Load Sound effects.
2123      *  This method must be called when sound effects are enabled.
2124      */
loadSoundEffects()2125     public void loadSoundEffects() {
2126         IAudioService service = getService();
2127         try {
2128             service.loadSoundEffects();
2129         } catch (RemoteException e) {
2130             Log.e(TAG, "Dead object in loadSoundEffects"+e);
2131         }
2132     }
2133 
2134     /**
2135      *  Unload Sound effects.
2136      *  This method can be called to free some memory when
2137      *  sound effects are disabled.
2138      */
unloadSoundEffects()2139     public void unloadSoundEffects() {
2140         IAudioService service = getService();
2141         try {
2142             service.unloadSoundEffects();
2143         } catch (RemoteException e) {
2144             Log.e(TAG, "Dead object in unloadSoundEffects"+e);
2145         }
2146     }
2147 
2148     /**
2149      * @hide
2150      * Used to indicate no audio focus has been gained or lost.
2151      */
2152     public static final int AUDIOFOCUS_NONE = 0;
2153 
2154     /**
2155      * Used to indicate a gain of audio focus, or a request of audio focus, of unknown duration.
2156      * @see OnAudioFocusChangeListener#onAudioFocusChange(int)
2157      * @see #requestAudioFocus(OnAudioFocusChangeListener, int, int)
2158      */
2159     public static final int AUDIOFOCUS_GAIN = 1;
2160     /**
2161      * Used to indicate a temporary gain or request of audio focus, anticipated to last a short
2162      * amount of time. Examples of temporary changes are the playback of driving directions, or an
2163      * event notification.
2164      * @see OnAudioFocusChangeListener#onAudioFocusChange(int)
2165      * @see #requestAudioFocus(OnAudioFocusChangeListener, int, int)
2166      */
2167     public static final int AUDIOFOCUS_GAIN_TRANSIENT = 2;
2168     /**
2169      * Used to indicate a temporary request of audio focus, anticipated to last a short
2170      * amount of time, and where it is acceptable for other audio applications to keep playing
2171      * after having lowered their output level (also referred to as "ducking").
2172      * Examples of temporary changes are the playback of driving directions where playback of music
2173      * in the background is acceptable.
2174      * @see OnAudioFocusChangeListener#onAudioFocusChange(int)
2175      * @see #requestAudioFocus(OnAudioFocusChangeListener, int, int)
2176      */
2177     public static final int AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK = 3;
2178     /**
2179      * Used to indicate a temporary request of audio focus, anticipated to last a short
2180      * amount of time, during which no other applications, or system components, should play
2181      * anything. Examples of exclusive and transient audio focus requests are voice
2182      * memo recording and speech recognition, during which the system shouldn't play any
2183      * notifications, and media playback should have paused.
2184      * @see #requestAudioFocus(OnAudioFocusChangeListener, int, int)
2185      */
2186     public static final int AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE = 4;
2187     /**
2188      * Used to indicate a loss of audio focus of unknown duration.
2189      * @see OnAudioFocusChangeListener#onAudioFocusChange(int)
2190      */
2191     public static final int AUDIOFOCUS_LOSS = -1 * AUDIOFOCUS_GAIN;
2192     /**
2193      * Used to indicate a transient loss of audio focus.
2194      * @see OnAudioFocusChangeListener#onAudioFocusChange(int)
2195      */
2196     public static final int AUDIOFOCUS_LOSS_TRANSIENT = -1 * AUDIOFOCUS_GAIN_TRANSIENT;
2197     /**
2198      * Used to indicate a transient loss of audio focus where the loser of the audio focus can
2199      * lower its output volume if it wants to continue playing (also referred to as "ducking"), as
2200      * the new focus owner doesn't require others to be silent.
2201      * @see OnAudioFocusChangeListener#onAudioFocusChange(int)
2202      */
2203     public static final int AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK =
2204             -1 * AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK;
2205 
2206     /**
2207      * Interface definition for a callback to be invoked when the audio focus of the system is
2208      * updated.
2209      */
2210     public interface OnAudioFocusChangeListener {
2211         /**
2212          * Called on the listener to notify it the audio focus for this listener has been changed.
2213          * The focusChange value indicates whether the focus was gained,
2214          * whether the focus was lost, and whether that loss is transient, or whether the new focus
2215          * holder will hold it for an unknown amount of time.
2216          * When losing focus, listeners can use the focus change information to decide what
2217          * behavior to adopt when losing focus. A music player could for instance elect to lower
2218          * the volume of its music stream (duck) for transient focus losses, and pause otherwise.
2219          * @param focusChange the type of focus change, one of {@link AudioManager#AUDIOFOCUS_GAIN},
2220          *   {@link AudioManager#AUDIOFOCUS_LOSS}, {@link AudioManager#AUDIOFOCUS_LOSS_TRANSIENT}
2221          *   and {@link AudioManager#AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK}.
2222          */
onAudioFocusChange(int focusChange)2223         public void onAudioFocusChange(int focusChange);
2224     }
2225 
2226     /**
2227      * Map to convert focus event listener IDs, as used in the AudioService audio focus stack,
2228      * to actual listener objects.
2229      */
2230     private final HashMap<String, OnAudioFocusChangeListener> mAudioFocusIdListenerMap =
2231             new HashMap<String, OnAudioFocusChangeListener>();
2232     /**
2233      * Lock to prevent concurrent changes to the list of focus listeners for this AudioManager
2234      * instance.
2235      */
2236     private final Object mFocusListenerLock = new Object();
2237 
findFocusListener(String id)2238     private OnAudioFocusChangeListener findFocusListener(String id) {
2239         return mAudioFocusIdListenerMap.get(id);
2240     }
2241 
2242     /**
2243      * Handler for audio focus events coming from the audio service.
2244      */
2245     private final FocusEventHandlerDelegate mAudioFocusEventHandlerDelegate =
2246             new FocusEventHandlerDelegate();
2247 
2248     /**
2249      * Helper class to handle the forwarding of audio focus events to the appropriate listener
2250      */
2251     private class FocusEventHandlerDelegate {
2252         private final Handler mHandler;
2253 
FocusEventHandlerDelegate()2254         FocusEventHandlerDelegate() {
2255             Looper looper;
2256             if ((looper = Looper.myLooper()) == null) {
2257                 looper = Looper.getMainLooper();
2258             }
2259 
2260             if (looper != null) {
2261                 // implement the event handler delegate to receive audio focus events
2262                 mHandler = new Handler(looper) {
2263                     @Override
2264                     public void handleMessage(Message msg) {
2265                         OnAudioFocusChangeListener listener = null;
2266                         synchronized(mFocusListenerLock) {
2267                             listener = findFocusListener((String)msg.obj);
2268                         }
2269                         if (listener != null) {
2270                             Log.d(TAG, "AudioManager dispatching onAudioFocusChange("
2271                                     + msg.what + ") for " + msg.obj);
2272                             listener.onAudioFocusChange(msg.what);
2273                         }
2274                     }
2275                 };
2276             } else {
2277                 mHandler = null;
2278             }
2279         }
2280 
getHandler()2281         Handler getHandler() {
2282             return mHandler;
2283         }
2284     }
2285 
2286     private final IAudioFocusDispatcher mAudioFocusDispatcher = new IAudioFocusDispatcher.Stub() {
2287 
2288         public void dispatchAudioFocusChange(int focusChange, String id) {
2289             Message m = mAudioFocusEventHandlerDelegate.getHandler().obtainMessage(focusChange, id);
2290             mAudioFocusEventHandlerDelegate.getHandler().sendMessage(m);
2291         }
2292 
2293     };
2294 
getIdForAudioFocusListener(OnAudioFocusChangeListener l)2295     private String getIdForAudioFocusListener(OnAudioFocusChangeListener l) {
2296         if (l == null) {
2297             return new String(this.toString());
2298         } else {
2299             return new String(this.toString() + l.toString());
2300         }
2301     }
2302 
2303     /**
2304      * @hide
2305      * Registers a listener to be called when audio focus changes. Calling this method is optional
2306      * before calling {@link #requestAudioFocus(OnAudioFocusChangeListener, int, int)}, as it
2307      * will register the listener as well if it wasn't registered already.
2308      * @param l the listener to be notified of audio focus changes.
2309      */
registerAudioFocusListener(OnAudioFocusChangeListener l)2310     public void registerAudioFocusListener(OnAudioFocusChangeListener l) {
2311         synchronized(mFocusListenerLock) {
2312             if (mAudioFocusIdListenerMap.containsKey(getIdForAudioFocusListener(l))) {
2313                 return;
2314             }
2315             mAudioFocusIdListenerMap.put(getIdForAudioFocusListener(l), l);
2316         }
2317     }
2318 
2319     /**
2320      * @hide
2321      * Causes the specified listener to not be called anymore when focus is gained or lost.
2322      * @param l the listener to unregister.
2323      */
unregisterAudioFocusListener(OnAudioFocusChangeListener l)2324     public void unregisterAudioFocusListener(OnAudioFocusChangeListener l) {
2325 
2326         // remove locally
2327         synchronized(mFocusListenerLock) {
2328             mAudioFocusIdListenerMap.remove(getIdForAudioFocusListener(l));
2329         }
2330     }
2331 
2332 
2333     /**
2334      * A failed focus change request.
2335      */
2336     public static final int AUDIOFOCUS_REQUEST_FAILED = 0;
2337     /**
2338      * A successful focus change request.
2339      */
2340     public static final int AUDIOFOCUS_REQUEST_GRANTED = 1;
2341      /**
2342       * @hide
2343       * A focus change request whose granting is delayed: the request was successful, but the
2344       * requester will only be granted audio focus once the condition that prevented immediate
2345       * granting has ended.
2346       * See {@link #requestAudioFocus(OnAudioFocusChangeListener, AudioAttributes, int, int)}
2347       */
2348     public static final int AUDIOFOCUS_REQUEST_DELAYED = 2;
2349 
2350 
2351     /**
2352      *  Request audio focus.
2353      *  Send a request to obtain the audio focus
2354      *  @param l the listener to be notified of audio focus changes
2355      *  @param streamType the main audio stream type affected by the focus request
2356      *  @param durationHint use {@link #AUDIOFOCUS_GAIN_TRANSIENT} to indicate this focus request
2357      *      is temporary, and focus will be abandonned shortly. Examples of transient requests are
2358      *      for the playback of driving directions, or notifications sounds.
2359      *      Use {@link #AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK} to indicate also that it's ok for
2360      *      the previous focus owner to keep playing if it ducks its audio output.
2361      *      Alternatively use {@link #AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE} for a temporary request
2362      *      that benefits from the system not playing disruptive sounds like notifications, for
2363      *      usecases such as voice memo recording, or speech recognition.
2364      *      Use {@link #AUDIOFOCUS_GAIN} for a focus request of unknown duration such
2365      *      as the playback of a song or a video.
2366      *  @return {@link #AUDIOFOCUS_REQUEST_FAILED} or {@link #AUDIOFOCUS_REQUEST_GRANTED}
2367      */
requestAudioFocus(OnAudioFocusChangeListener l, int streamType, int durationHint)2368     public int requestAudioFocus(OnAudioFocusChangeListener l, int streamType, int durationHint) {
2369         int status = AUDIOFOCUS_REQUEST_FAILED;
2370 
2371         try {
2372             // status is guaranteed to be either AUDIOFOCUS_REQUEST_FAILED or
2373             // AUDIOFOCUS_REQUEST_GRANTED as focus is requested without the
2374             // AUDIOFOCUS_FLAG_DELAY_OK flag
2375             status = requestAudioFocus(l,
2376                     new AudioAttributes.Builder()
2377                             .setInternalLegacyStreamType(streamType).build(),
2378                     durationHint,
2379                     0 /* flags, legacy behavior */);
2380         } catch (IllegalArgumentException e) {
2381             Log.e(TAG, "Audio focus request denied due to ", e);
2382         }
2383 
2384         return status;
2385     }
2386 
2387     // when adding new flags, add them to the relevant AUDIOFOCUS_FLAGS_APPS or SYSTEM masks
2388     /**
2389      * @hide
2390      * Use this flag when requesting audio focus to indicate it is ok for the requester to not be
2391      * granted audio focus immediately (as indicated by {@link #AUDIOFOCUS_REQUEST_DELAYED}) when
2392      * the system is in a state where focus cannot change, but be granted focus later when
2393      * this condition ends.
2394      */
2395     @SystemApi
2396     public static final int AUDIOFOCUS_FLAG_DELAY_OK = 0x1 << 0;
2397     /**
2398      * @hide
2399      * Use this flag when requesting audio focus to indicate that the requester
2400      * will pause its media playback (if applicable) when losing audio focus with
2401      * {@link #AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK}, rather than ducking.
2402      * <br>On some platforms, the ducking may be handled without the application being aware of it
2403      * (i.e. it will not transiently lose focus). For applications that for instance play spoken
2404      * content, such as audio book or podcast players, ducking may never be acceptable, and will
2405      * thus always pause. This flag enables them to be declared as such whenever they request focus.
2406      */
2407     @SystemApi
2408     public static final int AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS = 0x1 << 1;
2409     /**
2410      * @hide
2411      * Use this flag to lock audio focus so granting is temporarily disabled.
2412      * <br>This flag can only be used by owners of a registered
2413      * {@link android.media.audiopolicy.AudioPolicy} in
2414      * {@link #requestAudioFocus(OnAudioFocusChangeListener, AudioAttributes, int, int, AudioPolicy)}
2415      */
2416     @SystemApi
2417     public static final int AUDIOFOCUS_FLAG_LOCK     = 0x1 << 2;
2418     /** @hide */
2419     public static final int AUDIOFOCUS_FLAGS_APPS = AUDIOFOCUS_FLAG_DELAY_OK
2420             | AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS;
2421     /** @hide */
2422     public static final int AUDIOFOCUS_FLAGS_SYSTEM = AUDIOFOCUS_FLAG_DELAY_OK
2423             | AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS | AUDIOFOCUS_FLAG_LOCK;
2424 
2425     /**
2426      * @hide
2427      * Request audio focus.
2428      * Send a request to obtain the audio focus. This method differs from
2429      * {@link #requestAudioFocus(OnAudioFocusChangeListener, int, int)} in that it can express
2430      * that the requester accepts delayed grants of audio focus.
2431      * @param l the listener to be notified of audio focus changes. It is not allowed to be null
2432      *     when the request is flagged with {@link #AUDIOFOCUS_FLAG_DELAY_OK}.
2433      * @param requestAttributes non null {@link AudioAttributes} describing the main reason for
2434      *     requesting audio focus.
2435      * @param durationHint use {@link #AUDIOFOCUS_GAIN_TRANSIENT} to indicate this focus request
2436      *      is temporary, and focus will be abandonned shortly. Examples of transient requests are
2437      *      for the playback of driving directions, or notifications sounds.
2438      *      Use {@link #AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK} to indicate also that it's ok for
2439      *      the previous focus owner to keep playing if it ducks its audio output.
2440      *      Alternatively use {@link #AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE} for a temporary request
2441      *      that benefits from the system not playing disruptive sounds like notifications, for
2442      *      usecases such as voice memo recording, or speech recognition.
2443      *      Use {@link #AUDIOFOCUS_GAIN} for a focus request of unknown duration such
2444      *      as the playback of a song or a video.
2445      * @param flags 0 or a combination of {link #AUDIOFOCUS_FLAG_DELAY_OK}
2446      *     and {@link #AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS}.
2447      *     <br>Use 0 when not using any flags for the request, which behaves like
2448      *     {@link #requestAudioFocus(OnAudioFocusChangeListener, int, int)}, where either audio
2449      *     focus is granted immediately, or the grant request fails because the system is in a
2450      *     state where focus cannot change (e.g. a phone call).
2451      * @return {@link #AUDIOFOCUS_REQUEST_FAILED}, {@link #AUDIOFOCUS_REQUEST_GRANTED}
2452      *     or {@link #AUDIOFOCUS_REQUEST_DELAYED}.
2453      *     The return value is never {@link #AUDIOFOCUS_REQUEST_DELAYED} when focus is requested
2454      *     without the {@link #AUDIOFOCUS_FLAG_DELAY_OK} flag.
2455      * @throws IllegalArgumentException
2456      */
2457     @SystemApi
requestAudioFocus(OnAudioFocusChangeListener l, @NonNull AudioAttributes requestAttributes, int durationHint, int flags)2458     public int requestAudioFocus(OnAudioFocusChangeListener l,
2459             @NonNull AudioAttributes requestAttributes,
2460             int durationHint,
2461             int flags) throws IllegalArgumentException {
2462         if (flags != (flags & AUDIOFOCUS_FLAGS_APPS)) {
2463             throw new IllegalArgumentException("Invalid flags 0x"
2464                     + Integer.toHexString(flags).toUpperCase());
2465         }
2466         return requestAudioFocus(l, requestAttributes, durationHint,
2467                 flags & AUDIOFOCUS_FLAGS_APPS,
2468                 null /* no AudioPolicy*/);
2469     }
2470 
2471     /**
2472      * @hide
2473      * Request or lock audio focus.
2474      * This method is to be used by system components that have registered an
2475      * {@link android.media.audiopolicy.AudioPolicy} to request audio focus, but also to "lock" it
2476      * so focus granting is temporarily disabled.
2477      * @param l see the description of the same parameter in
2478      *     {@link #requestAudioFocus(OnAudioFocusChangeListener, AudioAttributes, int, int)}
2479      * @param requestAttributes non null {@link AudioAttributes} describing the main reason for
2480      *     requesting audio focus.
2481      * @param durationHint see the description of the same parameter in
2482      *     {@link #requestAudioFocus(OnAudioFocusChangeListener, AudioAttributes, int, int)}
2483      * @param flags 0 or a combination of {link #AUDIOFOCUS_FLAG_DELAY_OK},
2484      *     {@link #AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS}, and {@link #AUDIOFOCUS_FLAG_LOCK}.
2485      *     <br>Use 0 when not using any flags for the request, which behaves like
2486      *     {@link #requestAudioFocus(OnAudioFocusChangeListener, int, int)}, where either audio
2487      *     focus is granted immediately, or the grant request fails because the system is in a
2488      *     state where focus cannot change (e.g. a phone call).
2489      * @param ap a registered {@link android.media.audiopolicy.AudioPolicy} instance when locking
2490      *     focus, or null.
2491      * @return see the description of the same return value in
2492      *     {@link #requestAudioFocus(OnAudioFocusChangeListener, AudioAttributes, int, int)}
2493      * @throws IllegalArgumentException
2494      */
2495     @SystemApi
requestAudioFocus(OnAudioFocusChangeListener l, @NonNull AudioAttributes requestAttributes, int durationHint, int flags, AudioPolicy ap)2496     public int requestAudioFocus(OnAudioFocusChangeListener l,
2497             @NonNull AudioAttributes requestAttributes,
2498             int durationHint,
2499             int flags,
2500             AudioPolicy ap) throws IllegalArgumentException {
2501         // parameter checking
2502         if (requestAttributes == null) {
2503             throw new IllegalArgumentException("Illegal null AudioAttributes argument");
2504         }
2505         if ((durationHint < AUDIOFOCUS_GAIN) ||
2506                 (durationHint > AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE)) {
2507             throw new IllegalArgumentException("Invalid duration hint");
2508         }
2509         if (flags != (flags & AUDIOFOCUS_FLAGS_SYSTEM)) {
2510             throw new IllegalArgumentException("Illegal flags 0x"
2511                 + Integer.toHexString(flags).toUpperCase());
2512         }
2513         if (((flags & AUDIOFOCUS_FLAG_DELAY_OK) == AUDIOFOCUS_FLAG_DELAY_OK) && (l == null)) {
2514             throw new IllegalArgumentException(
2515                     "Illegal null focus listener when flagged as accepting delayed focus grant");
2516         }
2517         if (((flags & AUDIOFOCUS_FLAG_LOCK) == AUDIOFOCUS_FLAG_LOCK) && (ap == null)) {
2518             throw new IllegalArgumentException(
2519                     "Illegal null audio policy when locking audio focus");
2520         }
2521 
2522         int status = AUDIOFOCUS_REQUEST_FAILED;
2523         registerAudioFocusListener(l);
2524         IAudioService service = getService();
2525         try {
2526             status = service.requestAudioFocus(requestAttributes, durationHint, mICallBack,
2527                     mAudioFocusDispatcher, getIdForAudioFocusListener(l),
2528                     mContext.getOpPackageName() /* package name */, flags,
2529                     ap != null ? ap.cb() : null);
2530         } catch (RemoteException e) {
2531             Log.e(TAG, "Can't call requestAudioFocus() on AudioService:", e);
2532         }
2533         return status;
2534     }
2535 
2536     /**
2537      * @hide
2538      * Used internally by telephony package to request audio focus. Will cause the focus request
2539      * to be associated with the "voice communication" identifier only used in AudioService
2540      * to identify this use case.
2541      * @param streamType use STREAM_RING for focus requests when ringing, VOICE_CALL for
2542      *    the establishment of the call
2543      * @param durationHint the type of focus request. AUDIOFOCUS_GAIN_TRANSIENT is recommended so
2544      *    media applications resume after a call
2545      */
requestAudioFocusForCall(int streamType, int durationHint)2546     public void requestAudioFocusForCall(int streamType, int durationHint) {
2547         IAudioService service = getService();
2548         try {
2549             service.requestAudioFocus(new AudioAttributes.Builder()
2550                         .setInternalLegacyStreamType(streamType).build(),
2551                     durationHint, mICallBack, null,
2552                     MediaFocusControl.IN_VOICE_COMM_FOCUS_ID,
2553                     mContext.getOpPackageName(),
2554                     AUDIOFOCUS_FLAG_LOCK,
2555                     null /* policy token */);
2556         } catch (RemoteException e) {
2557             Log.e(TAG, "Can't call requestAudioFocusForCall() on AudioService:", e);
2558         }
2559     }
2560 
2561     /**
2562      * @hide
2563      * Used internally by telephony package to abandon audio focus, typically after a call or
2564      * when ringing ends and the call is rejected or not answered.
2565      * Should match one or more calls to {@link #requestAudioFocusForCall(int, int)}.
2566      */
abandonAudioFocusForCall()2567     public void abandonAudioFocusForCall() {
2568         IAudioService service = getService();
2569         try {
2570             service.abandonAudioFocus(null, MediaFocusControl.IN_VOICE_COMM_FOCUS_ID,
2571                     null /*AudioAttributes, legacy behavior*/);
2572         } catch (RemoteException e) {
2573             Log.e(TAG, "Can't call abandonAudioFocusForCall() on AudioService:", e);
2574         }
2575     }
2576 
2577     /**
2578      *  Abandon audio focus. Causes the previous focus owner, if any, to receive focus.
2579      *  @param l the listener with which focus was requested.
2580      *  @return {@link #AUDIOFOCUS_REQUEST_FAILED} or {@link #AUDIOFOCUS_REQUEST_GRANTED}
2581      */
abandonAudioFocus(OnAudioFocusChangeListener l)2582     public int abandonAudioFocus(OnAudioFocusChangeListener l) {
2583         return abandonAudioFocus(l, null /*AudioAttributes, legacy behavior*/);
2584     }
2585 
2586     /**
2587      * @hide
2588      * Abandon audio focus. Causes the previous focus owner, if any, to receive focus.
2589      *  @param l the listener with which focus was requested.
2590      * @param aa the {@link AudioAttributes} with which audio focus was requested
2591      * @return {@link #AUDIOFOCUS_REQUEST_FAILED} or {@link #AUDIOFOCUS_REQUEST_GRANTED}
2592      */
2593     @SystemApi
abandonAudioFocus(OnAudioFocusChangeListener l, AudioAttributes aa)2594     public int abandonAudioFocus(OnAudioFocusChangeListener l, AudioAttributes aa) {
2595         int status = AUDIOFOCUS_REQUEST_FAILED;
2596         unregisterAudioFocusListener(l);
2597         IAudioService service = getService();
2598         try {
2599             status = service.abandonAudioFocus(mAudioFocusDispatcher,
2600                     getIdForAudioFocusListener(l), aa);
2601         } catch (RemoteException e) {
2602             Log.e(TAG, "Can't call abandonAudioFocus() on AudioService:", e);
2603         }
2604         return status;
2605     }
2606 
2607     //====================================================================
2608     // Remote Control
2609     /**
2610      * Register a component to be the sole receiver of MEDIA_BUTTON intents.
2611      * @param eventReceiver identifier of a {@link android.content.BroadcastReceiver}
2612      *      that will receive the media button intent. This broadcast receiver must be declared
2613      *      in the application manifest. The package of the component must match that of
2614      *      the context you're registering from.
2615      * @deprecated Use {@link MediaSession#setMediaButtonReceiver(PendingIntent)} instead.
2616      */
2617     @Deprecated
registerMediaButtonEventReceiver(ComponentName eventReceiver)2618     public void registerMediaButtonEventReceiver(ComponentName eventReceiver) {
2619         if (eventReceiver == null) {
2620             return;
2621         }
2622         if (!eventReceiver.getPackageName().equals(mContext.getPackageName())) {
2623             Log.e(TAG, "registerMediaButtonEventReceiver() error: " +
2624                     "receiver and context package names don't match");
2625             return;
2626         }
2627         // construct a PendingIntent for the media button and register it
2628         Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
2629         //     the associated intent will be handled by the component being registered
2630         mediaButtonIntent.setComponent(eventReceiver);
2631         PendingIntent pi = PendingIntent.getBroadcast(mContext,
2632                 0/*requestCode, ignored*/, mediaButtonIntent, 0/*flags*/);
2633         registerMediaButtonIntent(pi, eventReceiver);
2634     }
2635 
2636     /**
2637      * Register a component to be the sole receiver of MEDIA_BUTTON intents.  This is like
2638      * {@link #registerMediaButtonEventReceiver(android.content.ComponentName)}, but allows
2639      * the buttons to go to any PendingIntent.  Note that you should only use this form if
2640      * you know you will continue running for the full time until unregistering the
2641      * PendingIntent.
2642      * @param eventReceiver target that will receive media button intents.  The PendingIntent
2643      * will be sent an {@link Intent#ACTION_MEDIA_BUTTON} event when a media button action
2644      * occurs, with {@link Intent#EXTRA_KEY_EVENT} added and holding the key code of the
2645      * media button that was pressed.
2646      * @deprecated Use {@link MediaSession#setMediaButtonReceiver(PendingIntent)} instead.
2647      */
2648     @Deprecated
registerMediaButtonEventReceiver(PendingIntent eventReceiver)2649     public void registerMediaButtonEventReceiver(PendingIntent eventReceiver) {
2650         if (eventReceiver == null) {
2651             return;
2652         }
2653         registerMediaButtonIntent(eventReceiver, null);
2654     }
2655 
2656     /**
2657      * @hide
2658      * no-op if (pi == null) or (eventReceiver == null)
2659      */
registerMediaButtonIntent(PendingIntent pi, ComponentName eventReceiver)2660     public void registerMediaButtonIntent(PendingIntent pi, ComponentName eventReceiver) {
2661         if (pi == null) {
2662             Log.e(TAG, "Cannot call registerMediaButtonIntent() with a null parameter");
2663             return;
2664         }
2665         MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mContext);
2666         helper.addMediaButtonListener(pi, eventReceiver, mContext);
2667     }
2668 
2669     /**
2670      * Unregister the receiver of MEDIA_BUTTON intents.
2671      * @param eventReceiver identifier of a {@link android.content.BroadcastReceiver}
2672      *      that was registered with {@link #registerMediaButtonEventReceiver(ComponentName)}.
2673      * @deprecated Use {@link MediaSession} instead.
2674      */
2675     @Deprecated
unregisterMediaButtonEventReceiver(ComponentName eventReceiver)2676     public void unregisterMediaButtonEventReceiver(ComponentName eventReceiver) {
2677         if (eventReceiver == null) {
2678             return;
2679         }
2680         // construct a PendingIntent for the media button and unregister it
2681         Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
2682         //     the associated intent will be handled by the component being registered
2683         mediaButtonIntent.setComponent(eventReceiver);
2684         PendingIntent pi = PendingIntent.getBroadcast(mContext,
2685                 0/*requestCode, ignored*/, mediaButtonIntent, 0/*flags*/);
2686         unregisterMediaButtonIntent(pi);
2687     }
2688 
2689     /**
2690      * Unregister the receiver of MEDIA_BUTTON intents.
2691      * @param eventReceiver same PendingIntent that was registed with
2692      *      {@link #registerMediaButtonEventReceiver(PendingIntent)}.
2693      * @deprecated Use {@link MediaSession} instead.
2694      */
2695     @Deprecated
unregisterMediaButtonEventReceiver(PendingIntent eventReceiver)2696     public void unregisterMediaButtonEventReceiver(PendingIntent eventReceiver) {
2697         if (eventReceiver == null) {
2698             return;
2699         }
2700         unregisterMediaButtonIntent(eventReceiver);
2701     }
2702 
2703     /**
2704      * @hide
2705      */
unregisterMediaButtonIntent(PendingIntent pi)2706     public void unregisterMediaButtonIntent(PendingIntent pi) {
2707         MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mContext);
2708         helper.removeMediaButtonListener(pi);
2709     }
2710 
2711     /**
2712      * Registers the remote control client for providing information to display on the remote
2713      * controls.
2714      * @param rcClient The remote control client from which remote controls will receive
2715      *      information to display.
2716      * @see RemoteControlClient
2717      * @deprecated Use {@link MediaSession} instead.
2718      */
2719     @Deprecated
registerRemoteControlClient(RemoteControlClient rcClient)2720     public void registerRemoteControlClient(RemoteControlClient rcClient) {
2721         if ((rcClient == null) || (rcClient.getRcMediaIntent() == null)) {
2722             return;
2723         }
2724         rcClient.registerWithSession(MediaSessionLegacyHelper.getHelper(mContext));
2725     }
2726 
2727     /**
2728      * Unregisters the remote control client that was providing information to display on the
2729      * remote controls.
2730      * @param rcClient The remote control client to unregister.
2731      * @see #registerRemoteControlClient(RemoteControlClient)
2732      * @deprecated Use {@link MediaSession} instead.
2733      */
2734     @Deprecated
unregisterRemoteControlClient(RemoteControlClient rcClient)2735     public void unregisterRemoteControlClient(RemoteControlClient rcClient) {
2736         if ((rcClient == null) || (rcClient.getRcMediaIntent() == null)) {
2737             return;
2738         }
2739         rcClient.unregisterWithSession(MediaSessionLegacyHelper.getHelper(mContext));
2740     }
2741 
2742     /**
2743      * Registers a {@link RemoteController} instance for it to receive media
2744      * metadata updates and playback state information from applications using
2745      * {@link RemoteControlClient}, and control their playback.
2746      * <p>
2747      * Registration requires the {@link OnClientUpdateListener} listener to be
2748      * one of the enabled notification listeners (see
2749      * {@link android.service.notification.NotificationListenerService}).
2750      *
2751      * @param rctlr the object to register.
2752      * @return true if the {@link RemoteController} was successfully registered,
2753      *         false if an error occurred, due to an internal system error, or
2754      *         insufficient permissions.
2755      * @deprecated Use
2756      *             {@link MediaSessionManager#addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, ComponentName)}
2757      *             and {@link MediaController} instead.
2758      */
2759     @Deprecated
registerRemoteController(RemoteController rctlr)2760     public boolean registerRemoteController(RemoteController rctlr) {
2761         if (rctlr == null) {
2762             return false;
2763         }
2764         rctlr.startListeningToSessions();
2765         return true;
2766     }
2767 
2768     /**
2769      * Unregisters a {@link RemoteController}, causing it to no longer receive
2770      * media metadata and playback state information, and no longer be capable
2771      * of controlling playback.
2772      *
2773      * @param rctlr the object to unregister.
2774      * @deprecated Use
2775      *             {@link MediaSessionManager#removeOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener)}
2776      *             instead.
2777      */
2778     @Deprecated
unregisterRemoteController(RemoteController rctlr)2779     public void unregisterRemoteController(RemoteController rctlr) {
2780         if (rctlr == null) {
2781             return;
2782         }
2783         rctlr.stopListeningToSessions();
2784     }
2785 
2786     /**
2787      * @hide
2788      * Registers a remote control display that will be sent information by remote control clients.
2789      * Use this method if your IRemoteControlDisplay is not going to display artwork, otherwise
2790      * use {@link #registerRemoteControlDisplay(IRemoteControlDisplay, int, int)} to pass the
2791      * artwork size directly, or
2792      * {@link #remoteControlDisplayUsesBitmapSize(IRemoteControlDisplay, int, int)} later if artwork
2793      * is not yet needed.
2794      * <p>Registration requires the {@link Manifest.permission#MEDIA_CONTENT_CONTROL} permission.
2795      * @param rcd the IRemoteControlDisplay
2796      */
registerRemoteControlDisplay(IRemoteControlDisplay rcd)2797     public void registerRemoteControlDisplay(IRemoteControlDisplay rcd) {
2798         // passing a negative value for art work width and height as they are unknown at this stage
2799         registerRemoteControlDisplay(rcd, /*w*/-1, /*h*/ -1);
2800     }
2801 
2802     /**
2803      * @hide
2804      * Registers a remote control display that will be sent information by remote control clients.
2805      * <p>Registration requires the {@link Manifest.permission#MEDIA_CONTENT_CONTROL} permission.
2806      * @param rcd
2807      * @param w the maximum width of the expected bitmap. Negative values indicate it is
2808      *   useless to send artwork.
2809      * @param h the maximum height of the expected bitmap. Negative values indicate it is
2810      *   useless to send artwork.
2811      */
registerRemoteControlDisplay(IRemoteControlDisplay rcd, int w, int h)2812     public void registerRemoteControlDisplay(IRemoteControlDisplay rcd, int w, int h) {
2813         if (rcd == null) {
2814             return;
2815         }
2816         IAudioService service = getService();
2817         try {
2818             service.registerRemoteControlDisplay(rcd, w, h);
2819         } catch (RemoteException e) {
2820             Log.e(TAG, "Dead object in registerRemoteControlDisplay " + e);
2821         }
2822     }
2823 
2824     /**
2825      * @hide
2826      * Unregisters a remote control display that was sent information by remote control clients.
2827      * @param rcd
2828      */
unregisterRemoteControlDisplay(IRemoteControlDisplay rcd)2829     public void unregisterRemoteControlDisplay(IRemoteControlDisplay rcd) {
2830         if (rcd == null) {
2831             return;
2832         }
2833         IAudioService service = getService();
2834         try {
2835             service.unregisterRemoteControlDisplay(rcd);
2836         } catch (RemoteException e) {
2837             Log.e(TAG, "Dead object in unregisterRemoteControlDisplay " + e);
2838         }
2839     }
2840 
2841     /**
2842      * @hide
2843      * Sets the artwork size a remote control display expects when receiving bitmaps.
2844      * @param rcd
2845      * @param w the maximum width of the expected bitmap. Negative values indicate it is
2846      *   useless to send artwork.
2847      * @param h the maximum height of the expected bitmap. Negative values indicate it is
2848      *   useless to send artwork.
2849      */
remoteControlDisplayUsesBitmapSize(IRemoteControlDisplay rcd, int w, int h)2850     public void remoteControlDisplayUsesBitmapSize(IRemoteControlDisplay rcd, int w, int h) {
2851         if (rcd == null) {
2852             return;
2853         }
2854         IAudioService service = getService();
2855         try {
2856             service.remoteControlDisplayUsesBitmapSize(rcd, w, h);
2857         } catch (RemoteException e) {
2858             Log.e(TAG, "Dead object in remoteControlDisplayUsesBitmapSize " + e);
2859         }
2860     }
2861 
2862     /**
2863      * @hide
2864      * Controls whether a remote control display needs periodic checks of the RemoteControlClient
2865      * playback position to verify that the estimated position has not drifted from the actual
2866      * position. By default the check is not performed.
2867      * The IRemoteControlDisplay must have been previously registered for this to have any effect.
2868      * @param rcd the IRemoteControlDisplay for which the anti-drift mechanism will be enabled
2869      *     or disabled. No effect is null.
2870      * @param wantsSync if true, RemoteControlClient instances which expose their playback position
2871      *     to the framework will regularly compare the estimated playback position with the actual
2872      *     position, and will update the IRemoteControlDisplay implementation whenever a drift is
2873      *     detected.
2874      */
remoteControlDisplayWantsPlaybackPositionSync(IRemoteControlDisplay rcd, boolean wantsSync)2875     public void remoteControlDisplayWantsPlaybackPositionSync(IRemoteControlDisplay rcd,
2876             boolean wantsSync) {
2877         if (rcd == null) {
2878             return;
2879         }
2880         IAudioService service = getService();
2881         try {
2882             service.remoteControlDisplayWantsPlaybackPositionSync(rcd, wantsSync);
2883         } catch (RemoteException e) {
2884             Log.e(TAG, "Dead object in remoteControlDisplayWantsPlaybackPositionSync " + e);
2885         }
2886     }
2887 
2888     /**
2889      * @hide
2890      * Register the given {@link AudioPolicy}.
2891      * This call is synchronous and blocks until the registration process successfully completed
2892      * or failed to complete.
2893      * @param policy the non-null {@link AudioPolicy} to register.
2894      * @return {@link #ERROR} if there was an error communicating with the registration service
2895      *    or if the user doesn't have the required
2896      *    {@link android.Manifest.permission#MODIFY_AUDIO_ROUTING} permission,
2897      *    {@link #SUCCESS} otherwise.
2898      */
2899     @SystemApi
registerAudioPolicy(@onNull AudioPolicy policy)2900     public int registerAudioPolicy(@NonNull AudioPolicy policy) {
2901         if (policy == null) {
2902             throw new IllegalArgumentException("Illegal null AudioPolicy argument");
2903         }
2904         IAudioService service = getService();
2905         try {
2906             String regId = service.registerAudioPolicy(policy.getConfig(), policy.cb(),
2907                     policy.hasFocusListener());
2908             if (regId == null) {
2909                 return ERROR;
2910             } else {
2911                 policy.setRegistration(regId);
2912             }
2913             // successful registration
2914         } catch (RemoteException e) {
2915             Log.e(TAG, "Dead object in registerAudioPolicyAsync()", e);
2916             return ERROR;
2917         }
2918         return SUCCESS;
2919     }
2920 
2921     /**
2922      * @hide
2923      * @param policy the non-null {@link AudioPolicy} to unregister.
2924      */
2925     @SystemApi
unregisterAudioPolicyAsync(@onNull AudioPolicy policy)2926     public void unregisterAudioPolicyAsync(@NonNull AudioPolicy policy) {
2927         if (policy == null) {
2928             throw new IllegalArgumentException("Illegal null AudioPolicy argument");
2929         }
2930         IAudioService service = getService();
2931         try {
2932             service.unregisterAudioPolicyAsync(policy.cb());
2933             policy.setRegistration(null);
2934         } catch (RemoteException e) {
2935             Log.e(TAG, "Dead object in unregisterAudioPolicyAsync()", e);
2936         }
2937     }
2938 
2939 
2940     /**
2941      *  @hide
2942      *  Reload audio settings. This method is called by Settings backup
2943      *  agent when audio settings are restored and causes the AudioService
2944      *  to read and apply restored settings.
2945      */
reloadAudioSettings()2946     public void reloadAudioSettings() {
2947         IAudioService service = getService();
2948         try {
2949             service.reloadAudioSettings();
2950         } catch (RemoteException e) {
2951             Log.e(TAG, "Dead object in reloadAudioSettings"+e);
2952         }
2953     }
2954 
2955     /**
2956      * @hide
2957      * Notifies AudioService that it is connected to an A2DP device that supports absolute volume,
2958      * so that AudioService can send volume change events to the A2DP device, rather than handling
2959      * them.
2960      */
avrcpSupportsAbsoluteVolume(String address, boolean support)2961     public void avrcpSupportsAbsoluteVolume(String address, boolean support) {
2962         IAudioService service = getService();
2963         try {
2964             service.avrcpSupportsAbsoluteVolume(address, support);
2965         } catch (RemoteException e) {
2966             Log.e(TAG, "Dead object in avrcpSupportsAbsoluteVolume", e);
2967         }
2968     }
2969 
2970      /**
2971       * {@hide}
2972       */
2973      private final IBinder mICallBack = new Binder();
2974 
2975     /**
2976      * Checks whether the phone is in silent mode, with or without vibrate.
2977      *
2978      * @return true if phone is in silent mode, with or without vibrate.
2979      *
2980      * @see #getRingerMode()
2981      *
2982      * @hide pending API Council approval
2983      */
isSilentMode()2984     public boolean isSilentMode() {
2985         int ringerMode = getRingerMode();
2986         boolean silentMode =
2987             (ringerMode == RINGER_MODE_SILENT) ||
2988             (ringerMode == RINGER_MODE_VIBRATE);
2989         return silentMode;
2990     }
2991 
2992     // This section re-defines new output device constants from AudioSystem, because the AudioSystem
2993     // class is not used by other parts of the framework, which instead use definitions and methods
2994     // from AudioManager. AudioSystem is an internal class used by AudioManager and AudioService.
2995 
2996     /** @hide
2997      * The audio device code for representing "no device." */
2998     public static final int DEVICE_NONE = AudioSystem.DEVICE_NONE;
2999     /** @hide
3000      *  The audio output device code for the small speaker at the front of the device used
3001      *  when placing calls.  Does not refer to an in-ear headphone without attached microphone,
3002      *  such as earbuds, earphones, or in-ear monitors (IEM). Those would be handled as a
3003      *  {@link #DEVICE_OUT_WIRED_HEADPHONE}.
3004      */
3005     public static final int DEVICE_OUT_EARPIECE = AudioSystem.DEVICE_OUT_EARPIECE;
3006     /** @hide
3007      *  The audio output device code for the built-in speaker */
3008     public static final int DEVICE_OUT_SPEAKER = AudioSystem.DEVICE_OUT_SPEAKER;
3009     /** @hide
3010      * The audio output device code for a wired headset with attached microphone */
3011     public static final int DEVICE_OUT_WIRED_HEADSET = AudioSystem.DEVICE_OUT_WIRED_HEADSET;
3012     /** @hide
3013      * The audio output device code for a wired headphone without attached microphone */
3014     public static final int DEVICE_OUT_WIRED_HEADPHONE = AudioSystem.DEVICE_OUT_WIRED_HEADPHONE;
3015     /** @hide
3016      * The audio output device code for generic Bluetooth SCO, for voice */
3017     public static final int DEVICE_OUT_BLUETOOTH_SCO = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO;
3018     /** @hide
3019      * The audio output device code for Bluetooth SCO Headset Profile (HSP) and
3020      * Hands-Free Profile (HFP), for voice
3021      */
3022     public static final int DEVICE_OUT_BLUETOOTH_SCO_HEADSET =
3023             AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
3024     /** @hide
3025      * The audio output device code for Bluetooth SCO car audio, for voice */
3026     public static final int DEVICE_OUT_BLUETOOTH_SCO_CARKIT =
3027             AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
3028     /** @hide
3029      * The audio output device code for generic Bluetooth A2DP, for music */
3030     public static final int DEVICE_OUT_BLUETOOTH_A2DP = AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP;
3031     /** @hide
3032      * The audio output device code for Bluetooth A2DP headphones, for music */
3033     public static final int DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES =
3034             AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
3035     /** @hide
3036      * The audio output device code for Bluetooth A2DP external speaker, for music */
3037     public static final int DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER =
3038             AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
3039     /** @hide
3040      * The audio output device code for S/PDIF (legacy) or HDMI
3041      * Deprecated: replaced by {@link #DEVICE_OUT_HDMI} */
3042     public static final int DEVICE_OUT_AUX_DIGITAL = AudioSystem.DEVICE_OUT_AUX_DIGITAL;
3043     /** @hide
3044      * The audio output device code for HDMI */
3045     public static final int DEVICE_OUT_HDMI = AudioSystem.DEVICE_OUT_HDMI;
3046     /** @hide
3047      * The audio output device code for an analog wired headset attached via a
3048      *  docking station
3049      */
3050     public static final int DEVICE_OUT_ANLG_DOCK_HEADSET = AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET;
3051     /** @hide
3052      * The audio output device code for a digital wired headset attached via a
3053      *  docking station
3054      */
3055     public static final int DEVICE_OUT_DGTL_DOCK_HEADSET = AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET;
3056     /** @hide
3057      * The audio output device code for a USB audio accessory. The accessory is in USB host
3058      * mode and the Android device in USB device mode
3059      */
3060     public static final int DEVICE_OUT_USB_ACCESSORY = AudioSystem.DEVICE_OUT_USB_ACCESSORY;
3061     /** @hide
3062      * The audio output device code for a USB audio device. The device is in USB device
3063      * mode and the Android device in USB host mode
3064      */
3065     public static final int DEVICE_OUT_USB_DEVICE = AudioSystem.DEVICE_OUT_USB_DEVICE;
3066     /** @hide
3067      * The audio output device code for projection output.
3068      */
3069     public static final int DEVICE_OUT_REMOTE_SUBMIX = AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
3070     /** @hide
3071      * The audio output device code the telephony voice TX path.
3072      */
3073     public static final int DEVICE_OUT_TELEPHONY_TX = AudioSystem.DEVICE_OUT_TELEPHONY_TX;
3074     /** @hide
3075      * The audio output device code for an analog jack with line impedance detected.
3076      */
3077     public static final int DEVICE_OUT_LINE = AudioSystem.DEVICE_OUT_LINE;
3078     /** @hide
3079      * The audio output device code for HDMI Audio Return Channel.
3080      */
3081     public static final int DEVICE_OUT_HDMI_ARC = AudioSystem.DEVICE_OUT_HDMI_ARC;
3082     /** @hide
3083      * The audio output device code for S/PDIF digital connection.
3084      */
3085     public static final int DEVICE_OUT_SPDIF = AudioSystem.DEVICE_OUT_SPDIF;
3086     /** @hide
3087      * The audio output device code for built-in FM transmitter.
3088      */
3089     public static final int DEVICE_OUT_FM = AudioSystem.DEVICE_OUT_FM;
3090     /** @hide
3091      * This is not used as a returned value from {@link #getDevicesForStream}, but could be
3092      *  used in the future in a set method to select whatever default device is chosen by the
3093      *  platform-specific implementation.
3094      */
3095     public static final int DEVICE_OUT_DEFAULT = AudioSystem.DEVICE_OUT_DEFAULT;
3096 
3097     /** @hide
3098      * The audio input device code for default built-in microphone
3099      */
3100     public static final int DEVICE_IN_BUILTIN_MIC = AudioSystem.DEVICE_IN_BUILTIN_MIC;
3101     /** @hide
3102      * The audio input device code for a Bluetooth SCO headset
3103      */
3104     public static final int DEVICE_IN_BLUETOOTH_SCO_HEADSET =
3105                                     AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET;
3106     /** @hide
3107      * The audio input device code for wired headset microphone
3108      */
3109     public static final int DEVICE_IN_WIRED_HEADSET =
3110                                     AudioSystem.DEVICE_IN_WIRED_HEADSET;
3111     /** @hide
3112      * The audio input device code for HDMI
3113      */
3114     public static final int DEVICE_IN_HDMI =
3115                                     AudioSystem.DEVICE_IN_HDMI;
3116     /** @hide
3117      * The audio input device code for telephony voice RX path
3118      */
3119     public static final int DEVICE_IN_TELEPHONY_RX =
3120                                     AudioSystem.DEVICE_IN_TELEPHONY_RX;
3121     /** @hide
3122      * The audio input device code for built-in microphone pointing to the back
3123      */
3124     public static final int DEVICE_IN_BACK_MIC =
3125                                     AudioSystem.DEVICE_IN_BACK_MIC;
3126     /** @hide
3127      * The audio input device code for analog from a docking station
3128      */
3129     public static final int DEVICE_IN_ANLG_DOCK_HEADSET =
3130                                     AudioSystem.DEVICE_IN_ANLG_DOCK_HEADSET;
3131     /** @hide
3132      * The audio input device code for digital from a docking station
3133      */
3134     public static final int DEVICE_IN_DGTL_DOCK_HEADSET =
3135                                     AudioSystem.DEVICE_IN_DGTL_DOCK_HEADSET;
3136     /** @hide
3137      * The audio input device code for a USB audio accessory. The accessory is in USB host
3138      * mode and the Android device in USB device mode
3139      */
3140     public static final int DEVICE_IN_USB_ACCESSORY =
3141                                     AudioSystem.DEVICE_IN_USB_ACCESSORY;
3142     /** @hide
3143      * The audio input device code for a USB audio device. The device is in USB device
3144      * mode and the Android device in USB host mode
3145      */
3146     public static final int DEVICE_IN_USB_DEVICE =
3147                                     AudioSystem.DEVICE_IN_USB_DEVICE;
3148     /** @hide
3149      * The audio input device code for a FM radio tuner
3150      */
3151     public static final int DEVICE_IN_FM_TUNER = AudioSystem.DEVICE_IN_FM_TUNER;
3152     /** @hide
3153      * The audio input device code for a TV tuner
3154      */
3155     public static final int DEVICE_IN_TV_TUNER = AudioSystem.DEVICE_IN_TV_TUNER;
3156     /** @hide
3157      * The audio input device code for an analog jack with line impedance detected
3158      */
3159     public static final int DEVICE_IN_LINE = AudioSystem.DEVICE_IN_LINE;
3160     /** @hide
3161      * The audio input device code for a S/PDIF digital connection
3162      */
3163     public static final int DEVICE_IN_SPDIF = AudioSystem.DEVICE_IN_SPDIF;
3164     /** @hide
3165      * The audio input device code for audio loopback
3166      */
3167     public static final int DEVICE_IN_LOOPBACK = AudioSystem.DEVICE_IN_LOOPBACK;
3168 
3169     /**
3170      * Return true if the device code corresponds to an output device.
3171      * @hide
3172      */
isOutputDevice(int device)3173     public static boolean isOutputDevice(int device)
3174     {
3175         return (device & AudioSystem.DEVICE_BIT_IN) == 0;
3176     }
3177 
3178     /**
3179      * Return true if the device code corresponds to an input device.
3180      * @hide
3181      */
isInputDevice(int device)3182     public static boolean isInputDevice(int device)
3183     {
3184         return (device & AudioSystem.DEVICE_BIT_IN) == AudioSystem.DEVICE_BIT_IN;
3185     }
3186 
3187 
3188     /**
3189      * Return the enabled devices for the specified output stream type.
3190      *
3191      * @param streamType The stream type to query. One of
3192      *            {@link #STREAM_VOICE_CALL},
3193      *            {@link #STREAM_SYSTEM},
3194      *            {@link #STREAM_RING},
3195      *            {@link #STREAM_MUSIC},
3196      *            {@link #STREAM_ALARM},
3197      *            {@link #STREAM_NOTIFICATION},
3198      *            {@link #STREAM_DTMF}.
3199      *
3200      * @return The bit-mask "or" of audio output device codes for all enabled devices on this
3201      *         stream. Zero or more of
3202      *            {@link #DEVICE_OUT_EARPIECE},
3203      *            {@link #DEVICE_OUT_SPEAKER},
3204      *            {@link #DEVICE_OUT_WIRED_HEADSET},
3205      *            {@link #DEVICE_OUT_WIRED_HEADPHONE},
3206      *            {@link #DEVICE_OUT_BLUETOOTH_SCO},
3207      *            {@link #DEVICE_OUT_BLUETOOTH_SCO_HEADSET},
3208      *            {@link #DEVICE_OUT_BLUETOOTH_SCO_CARKIT},
3209      *            {@link #DEVICE_OUT_BLUETOOTH_A2DP},
3210      *            {@link #DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES},
3211      *            {@link #DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER},
3212      *            {@link #DEVICE_OUT_HDMI},
3213      *            {@link #DEVICE_OUT_ANLG_DOCK_HEADSET},
3214      *            {@link #DEVICE_OUT_DGTL_DOCK_HEADSET}.
3215      *            {@link #DEVICE_OUT_USB_ACCESSORY}.
3216      *            {@link #DEVICE_OUT_USB_DEVICE}.
3217      *            {@link #DEVICE_OUT_REMOTE_SUBMIX}.
3218      *            {@link #DEVICE_OUT_TELEPHONY_TX}.
3219      *            {@link #DEVICE_OUT_LINE}.
3220      *            {@link #DEVICE_OUT_HDMI_ARC}.
3221      *            {@link #DEVICE_OUT_SPDIF}.
3222      *            {@link #DEVICE_OUT_FM}.
3223      *            {@link #DEVICE_OUT_DEFAULT} is not used here.
3224      *
3225      * The implementation may support additional device codes beyond those listed, so
3226      * the application should ignore any bits which it does not recognize.
3227      * Note that the information may be imprecise when the implementation
3228      * cannot distinguish whether a particular device is enabled.
3229      *
3230      * {@hide}
3231      */
getDevicesForStream(int streamType)3232     public int getDevicesForStream(int streamType) {
3233         switch (streamType) {
3234         case STREAM_VOICE_CALL:
3235         case STREAM_SYSTEM:
3236         case STREAM_RING:
3237         case STREAM_MUSIC:
3238         case STREAM_ALARM:
3239         case STREAM_NOTIFICATION:
3240         case STREAM_DTMF:
3241             return AudioSystem.getDevicesForStream(streamType);
3242         default:
3243             return 0;
3244         }
3245     }
3246 
3247      /**
3248      * Indicate wired accessory connection state change.
3249      * @param device type of device connected/disconnected (AudioManager.DEVICE_OUT_xxx)
3250      * @param state  new connection state: 1 connected, 0 disconnected
3251      * @param name   device name
3252      * {@hide}
3253      */
setWiredDeviceConnectionState(int device, int state, String name)3254     public void setWiredDeviceConnectionState(int device, int state, String name) {
3255         IAudioService service = getService();
3256         try {
3257             service.setWiredDeviceConnectionState(device, state, name);
3258         } catch (RemoteException e) {
3259             Log.e(TAG, "Dead object in setWiredDeviceConnectionState "+e);
3260         }
3261     }
3262 
3263      /**
3264      * Indicate A2DP source or sink connection state change.
3265      * @param device Bluetooth device connected/disconnected
3266      * @param state  new connection state (BluetoothProfile.STATE_xxx)
3267      * @param profile profile for the A2DP device
3268      * (either {@link android.bluetooth.BluetoothProfile.A2DP} or
3269      * {@link android.bluetooth.BluetoothProfile.A2DP_SINK})
3270      * @return a delay in ms that the caller should wait before broadcasting
3271      * BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED intent.
3272      * {@hide}
3273      */
setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state, int profile)3274     public int setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state,
3275             int profile) {
3276         IAudioService service = getService();
3277         int delay = 0;
3278         try {
3279             delay = service.setBluetoothA2dpDeviceConnectionState(device, state, profile);
3280         } catch (RemoteException e) {
3281             Log.e(TAG, "Dead object in setBluetoothA2dpDeviceConnectionState "+e);
3282         } finally {
3283             return delay;
3284         }
3285     }
3286 
3287     /** {@hide} */
getRingtonePlayer()3288     public IRingtonePlayer getRingtonePlayer() {
3289         try {
3290             return getService().getRingtonePlayer();
3291         } catch (RemoteException e) {
3292             return null;
3293         }
3294     }
3295 
3296     /**
3297      * Used as a key for {@link #getProperty} to request the native or optimal output sample rate
3298      * for this device's primary output stream, in decimal Hz.
3299      */
3300     public static final String PROPERTY_OUTPUT_SAMPLE_RATE =
3301             "android.media.property.OUTPUT_SAMPLE_RATE";
3302 
3303     /**
3304      * Used as a key for {@link #getProperty} to request the native or optimal output buffer size
3305      * for this device's primary output stream, in decimal PCM frames.
3306      */
3307     public static final String PROPERTY_OUTPUT_FRAMES_PER_BUFFER =
3308             "android.media.property.OUTPUT_FRAMES_PER_BUFFER";
3309 
3310     /**
3311      * Returns the value of the property with the specified key.
3312      * @param key One of the strings corresponding to a property key: either
3313      *            {@link #PROPERTY_OUTPUT_SAMPLE_RATE} or
3314      *            {@link #PROPERTY_OUTPUT_FRAMES_PER_BUFFER}
3315      * @return A string representing the associated value for that property key,
3316      *         or null if there is no value for that key.
3317      */
getProperty(String key)3318     public String getProperty(String key) {
3319         if (PROPERTY_OUTPUT_SAMPLE_RATE.equals(key)) {
3320             int outputSampleRate = AudioSystem.getPrimaryOutputSamplingRate();
3321             return outputSampleRate > 0 ? Integer.toString(outputSampleRate) : null;
3322         } else if (PROPERTY_OUTPUT_FRAMES_PER_BUFFER.equals(key)) {
3323             int outputFramesPerBuffer = AudioSystem.getPrimaryOutputFrameCount();
3324             return outputFramesPerBuffer > 0 ? Integer.toString(outputFramesPerBuffer) : null;
3325         } else {
3326             // null or unknown key
3327             return null;
3328         }
3329     }
3330 
3331     /**
3332      * Returns the estimated latency for the given stream type in milliseconds.
3333      *
3334      * DO NOT UNHIDE. The existing approach for doing A/V sync has too many problems. We need
3335      * a better solution.
3336      * @hide
3337      */
getOutputLatency(int streamType)3338     public int getOutputLatency(int streamType) {
3339         return AudioSystem.getOutputLatency(streamType);
3340     }
3341 
3342     /**
3343      * Registers a global volume controller interface.  Currently limited to SystemUI.
3344      *
3345      * @hide
3346      */
setVolumeController(IVolumeController controller)3347     public void setVolumeController(IVolumeController controller) {
3348         try {
3349             getService().setVolumeController(controller);
3350         } catch (RemoteException e) {
3351             Log.w(TAG, "Error setting volume controller", e);
3352         }
3353     }
3354 
3355     /**
3356      * Notify audio manager about volume controller visibility changes.
3357      * Currently limited to SystemUI.
3358      *
3359      * @hide
3360      */
notifyVolumeControllerVisible(IVolumeController controller, boolean visible)3361     public void notifyVolumeControllerVisible(IVolumeController controller, boolean visible) {
3362         try {
3363             getService().notifyVolumeControllerVisible(controller, visible);
3364         } catch (RemoteException e) {
3365             Log.w(TAG, "Error notifying about volume controller visibility", e);
3366         }
3367     }
3368 
3369     /**
3370      * Only useful for volume controllers.
3371      * @hide
3372      */
isStreamAffectedByRingerMode(int streamType)3373     public boolean isStreamAffectedByRingerMode(int streamType) {
3374         try {
3375             return getService().isStreamAffectedByRingerMode(streamType);
3376         } catch (RemoteException e) {
3377             Log.w(TAG, "Error calling isStreamAffectedByRingerMode", e);
3378             return false;
3379         }
3380     }
3381 
3382     /**
3383      * Only useful for volume controllers.
3384      * @hide
3385      */
disableSafeMediaVolume()3386     public void disableSafeMediaVolume() {
3387         try {
3388             getService().disableSafeMediaVolume();
3389         } catch (RemoteException e) {
3390             Log.w(TAG, "Error disabling safe media volume", e);
3391         }
3392     }
3393 
3394     /**
3395      * Only useful for volume controllers.
3396      * @hide
3397      */
setRingerModeInternal(int ringerMode)3398     public void setRingerModeInternal(int ringerMode) {
3399         try {
3400             getService().setRingerModeInternal(ringerMode, mContext.getOpPackageName());
3401         } catch (RemoteException e) {
3402             Log.w(TAG, "Error calling setRingerModeInternal", e);
3403         }
3404     }
3405 
3406     /**
3407      * Only useful for volume controllers.
3408      * @hide
3409      */
getRingerModeInternal()3410     public int getRingerModeInternal() {
3411         try {
3412             return getService().getRingerModeInternal();
3413         } catch (RemoteException e) {
3414             Log.w(TAG, "Error calling getRingerModeInternal", e);
3415             return RINGER_MODE_NORMAL;
3416         }
3417     }
3418 
3419     /**
3420      * Set Hdmi Cec system audio mode.
3421      *
3422      * @param on whether to be on system audio mode
3423      * @return output device type. 0 (DEVICE_NONE) if failed to set device.
3424      * @hide
3425      */
setHdmiSystemAudioSupported(boolean on)3426     public int setHdmiSystemAudioSupported(boolean on) {
3427         try {
3428             return getService().setHdmiSystemAudioSupported(on);
3429         } catch (RemoteException e) {
3430             Log.w(TAG, "Error setting system audio mode", e);
3431             return AudioSystem.DEVICE_NONE;
3432         }
3433     }
3434 
3435     /**
3436      * Returns true if Hdmi Cec system audio mode is supported.
3437      *
3438      * @hide
3439      */
3440     @SystemApi
isHdmiSystemAudioSupported()3441     public boolean isHdmiSystemAudioSupported() {
3442         try {
3443             return getService().isHdmiSystemAudioSupported();
3444         } catch (RemoteException e) {
3445             Log.w(TAG, "Error querying system audio mode", e);
3446             return false;
3447         }
3448     }
3449 
3450     /**
3451      * Return codes for listAudioPorts(), createAudioPatch() ...
3452      */
3453 
3454     /** @hide
3455      * CANDIDATE FOR PUBLIC API
3456      */
3457     public static final int SUCCESS = AudioSystem.SUCCESS;
3458     /**
3459      * A default error code.
3460      */
3461     public static final int ERROR = AudioSystem.ERROR;
3462     /** @hide
3463      * CANDIDATE FOR PUBLIC API
3464      */
3465     public static final int ERROR_BAD_VALUE = AudioSystem.BAD_VALUE;
3466     /** @hide
3467      */
3468     public static final int ERROR_INVALID_OPERATION = AudioSystem.INVALID_OPERATION;
3469     /** @hide
3470      */
3471     public static final int ERROR_PERMISSION_DENIED = AudioSystem.PERMISSION_DENIED;
3472     /** @hide
3473      */
3474     public static final int ERROR_NO_INIT = AudioSystem.NO_INIT;
3475     /**
3476      * An error code indicating that the object reporting it is no longer valid and needs to
3477      * be recreated.
3478      */
3479     public static final int ERROR_DEAD_OBJECT = AudioSystem.DEAD_OBJECT;
3480 
3481     /**
3482      * Returns a list of descriptors for all audio ports managed by the audio framework.
3483      * Audio ports are nodes in the audio framework or audio hardware that can be configured
3484      * or connected and disconnected with createAudioPatch() or releaseAudioPatch().
3485      * See AudioPort for a list of attributes of each audio port.
3486      * @param ports An AudioPort ArrayList where the list will be returned.
3487      * @hide
3488      */
listAudioPorts(ArrayList<AudioPort> ports)3489     public int listAudioPorts(ArrayList<AudioPort> ports) {
3490         return updateAudioPortCache(ports, null);
3491     }
3492 
3493     /**
3494      * Specialized version of listAudioPorts() listing only audio devices (AudioDevicePort)
3495      * @see listAudioPorts(ArrayList<AudioPort>)
3496      * @hide
3497      */
listAudioDevicePorts(ArrayList<AudioPort> devices)3498     public int listAudioDevicePorts(ArrayList<AudioPort> devices) {
3499         ArrayList<AudioPort> ports = new ArrayList<AudioPort>();
3500         int status = updateAudioPortCache(ports, null);
3501         if (status == SUCCESS) {
3502             devices.clear();
3503             for (int i = 0; i < ports.size(); i++) {
3504                 if (ports.get(i) instanceof AudioDevicePort) {
3505                     devices.add(ports.get(i));
3506                 }
3507             }
3508         }
3509         return status;
3510     }
3511 
3512     /**
3513      * Create a connection between two or more devices. The framework will reject the request if
3514      * device types are not compatible or the implementation does not support the requested
3515      * configuration.
3516      * NOTE: current implementation is limited to one source and one sink per patch.
3517      * @param patch AudioPatch array where the newly created patch will be returned.
3518      *              As input, if patch[0] is not null, the specified patch will be replaced by the
3519      *              new patch created. This avoids calling releaseAudioPatch() when modifying a
3520      *              patch and allows the implementation to optimize transitions.
3521      * @param sources List of source audio ports. All must be AudioPort.ROLE_SOURCE.
3522      * @param sinks   List of sink audio ports. All must be AudioPort.ROLE_SINK.
3523      *
3524      * @return - {@link #SUCCESS} if connection is successful.
3525      *         - {@link #ERROR_BAD_VALUE} if incompatible device types are passed.
3526      *         - {@link #ERROR_INVALID_OPERATION} if the requested connection is not supported.
3527      *         - {@link #ERROR_PERMISSION_DENIED} if the client does not have permission to create
3528      *         a patch.
3529      *         - {@link #ERROR_DEAD_OBJECT} if the server process is dead
3530      *         - {@link #ERROR} if patch cannot be connected for any other reason.
3531      *
3532      *         patch[0] contains the newly created patch
3533      * @hide
3534      */
createAudioPatch(AudioPatch[] patch, AudioPortConfig[] sources, AudioPortConfig[] sinks)3535     public int createAudioPatch(AudioPatch[] patch,
3536                                  AudioPortConfig[] sources,
3537                                  AudioPortConfig[] sinks) {
3538         return AudioSystem.createAudioPatch(patch, sources, sinks);
3539     }
3540 
3541     /**
3542      * Releases an existing audio patch connection.
3543      * @param patch The audio patch to disconnect.
3544      * @return - {@link #SUCCESS} if disconnection is successful.
3545      *         - {@link #ERROR_BAD_VALUE} if the specified patch does not exist.
3546      *         - {@link #ERROR_PERMISSION_DENIED} if the client does not have permission to release
3547      *         a patch.
3548      *         - {@link #ERROR_DEAD_OBJECT} if the server process is dead
3549      *         - {@link #ERROR} if patch cannot be released for any other reason.
3550      * @hide
3551      */
releaseAudioPatch(AudioPatch patch)3552     public int releaseAudioPatch(AudioPatch patch) {
3553         return AudioSystem.releaseAudioPatch(patch);
3554     }
3555 
3556     /**
3557      * List all existing connections between audio ports.
3558      * @param patches An AudioPatch array where the list will be returned.
3559      * @hide
3560      */
listAudioPatches(ArrayList<AudioPatch> patches)3561     public int listAudioPatches(ArrayList<AudioPatch> patches) {
3562         return updateAudioPortCache(null, patches);
3563     }
3564 
3565     /**
3566      * Set the gain on the specified AudioPort. The AudioGainConfig config is build by
3567      * AudioGain.buildConfig()
3568      * @hide
3569      */
setAudioPortGain(AudioPort port, AudioGainConfig gain)3570     public int setAudioPortGain(AudioPort port, AudioGainConfig gain) {
3571         if (port == null || gain == null) {
3572             return ERROR_BAD_VALUE;
3573         }
3574         AudioPortConfig activeConfig = port.activeConfig();
3575         AudioPortConfig config = new AudioPortConfig(port, activeConfig.samplingRate(),
3576                                         activeConfig.channelMask(), activeConfig.format(), gain);
3577         config.mConfigMask = AudioPortConfig.GAIN;
3578         return AudioSystem.setAudioPortConfig(config);
3579     }
3580 
3581     /**
3582      * Listener registered by client to be notified upon new audio port connections,
3583      * disconnections or attributes update.
3584      * @hide
3585      */
3586     public interface OnAudioPortUpdateListener {
3587         /**
3588          * Callback method called upon audio port list update.
3589          * @param portList the updated list of audio ports
3590          */
onAudioPortListUpdate(AudioPort[] portList)3591         public void onAudioPortListUpdate(AudioPort[] portList);
3592 
3593         /**
3594          * Callback method called upon audio patch list update.
3595          * @param patchList the updated list of audio patches
3596          */
onAudioPatchListUpdate(AudioPatch[] patchList)3597         public void onAudioPatchListUpdate(AudioPatch[] patchList);
3598 
3599         /**
3600          * Callback method called when the mediaserver dies
3601          */
onServiceDied()3602         public void onServiceDied();
3603     }
3604 
3605     /**
3606      * Register an audio port list update listener.
3607      * @hide
3608      */
registerAudioPortUpdateListener(OnAudioPortUpdateListener l)3609     public void registerAudioPortUpdateListener(OnAudioPortUpdateListener l) {
3610         sAudioPortEventHandler.registerListener(l);
3611     }
3612 
3613     /**
3614      * Unregister an audio port list update listener.
3615      * @hide
3616      */
unregisterAudioPortUpdateListener(OnAudioPortUpdateListener l)3617     public void unregisterAudioPortUpdateListener(OnAudioPortUpdateListener l) {
3618         sAudioPortEventHandler.unregisterListener(l);
3619     }
3620 
3621     //
3622     // AudioPort implementation
3623     //
3624 
3625     static final int AUDIOPORT_GENERATION_INIT = 0;
3626     static Integer sAudioPortGeneration = new Integer(AUDIOPORT_GENERATION_INIT);
3627     static ArrayList<AudioPort> sAudioPortsCached = new ArrayList<AudioPort>();
3628     static ArrayList<AudioPatch> sAudioPatchesCached = new ArrayList<AudioPatch>();
3629 
resetAudioPortGeneration()3630     static int resetAudioPortGeneration() {
3631         int generation;
3632         synchronized (sAudioPortGeneration) {
3633             generation = sAudioPortGeneration;
3634             sAudioPortGeneration = AUDIOPORT_GENERATION_INIT;
3635         }
3636         return generation;
3637     }
3638 
updateAudioPortCache(ArrayList<AudioPort> ports, ArrayList<AudioPatch> patches)3639     static int updateAudioPortCache(ArrayList<AudioPort> ports, ArrayList<AudioPatch> patches) {
3640         synchronized (sAudioPortGeneration) {
3641 
3642             if (sAudioPortGeneration == AUDIOPORT_GENERATION_INIT) {
3643                 int[] patchGeneration = new int[1];
3644                 int[] portGeneration = new int[1];
3645                 int status;
3646                 ArrayList<AudioPort> newPorts = new ArrayList<AudioPort>();
3647                 ArrayList<AudioPatch> newPatches = new ArrayList<AudioPatch>();
3648 
3649                 do {
3650                     newPorts.clear();
3651                     status = AudioSystem.listAudioPorts(newPorts, portGeneration);
3652                     if (status != SUCCESS) {
3653                         Log.w(TAG, "updateAudioPortCache: listAudioPorts failed");
3654                         return status;
3655                     }
3656                     newPatches.clear();
3657                     status = AudioSystem.listAudioPatches(newPatches, patchGeneration);
3658                     if (status != SUCCESS) {
3659                         Log.w(TAG, "updateAudioPortCache: listAudioPatches failed");
3660                         return status;
3661                     }
3662                 } while (patchGeneration[0] != portGeneration[0]);
3663 
3664                 for (int i = 0; i < newPatches.size(); i++) {
3665                     for (int j = 0; j < newPatches.get(i).sources().length; j++) {
3666                         AudioPortConfig portCfg = updatePortConfig(newPatches.get(i).sources()[j],
3667                                                                    newPorts);
3668                         newPatches.get(i).sources()[j] = portCfg;
3669                     }
3670                     for (int j = 0; j < newPatches.get(i).sinks().length; j++) {
3671                         AudioPortConfig portCfg = updatePortConfig(newPatches.get(i).sinks()[j],
3672                                                                    newPorts);
3673                         newPatches.get(i).sinks()[j] = portCfg;
3674                     }
3675                 }
3676                 for (Iterator<AudioPatch> i = newPatches.iterator(); i.hasNext(); ) {
3677                     AudioPatch newPatch = i.next();
3678                     boolean hasInvalidPort = false;
3679                     for (AudioPortConfig portCfg : newPatch.sources()) {
3680                         if (portCfg == null) {
3681                             hasInvalidPort = true;
3682                             break;
3683                         }
3684                     }
3685                     for (AudioPortConfig portCfg : newPatch.sinks()) {
3686                         if (portCfg == null) {
3687                             hasInvalidPort = true;
3688                             break;
3689                         }
3690                     }
3691                     if (hasInvalidPort) {
3692                         // Temporarily remove patches with invalid ports. One who created the patch
3693                         // is responsible for dealing with the port change.
3694                         i.remove();
3695                     }
3696                 }
3697 
3698                 sAudioPortsCached = newPorts;
3699                 sAudioPatchesCached = newPatches;
3700                 sAudioPortGeneration = portGeneration[0];
3701             }
3702             if (ports != null) {
3703                 ports.clear();
3704                 ports.addAll(sAudioPortsCached);
3705             }
3706             if (patches != null) {
3707                 patches.clear();
3708                 patches.addAll(sAudioPatchesCached);
3709             }
3710         }
3711         return SUCCESS;
3712     }
3713 
updatePortConfig(AudioPortConfig portCfg, ArrayList<AudioPort> ports)3714     static AudioPortConfig updatePortConfig(AudioPortConfig portCfg, ArrayList<AudioPort> ports) {
3715         AudioPort port = portCfg.port();
3716         int k;
3717         for (k = 0; k < ports.size(); k++) {
3718             // compare handles because the port returned by JNI is not of the correct
3719             // subclass
3720             if (ports.get(k).handle().equals(port.handle())) {
3721                 port = ports.get(k);
3722                 break;
3723             }
3724         }
3725         if (k == ports.size()) {
3726             // this hould never happen
3727             Log.e(TAG, "updatePortConfig port not found for handle: "+port.handle().id());
3728             return null;
3729         }
3730         AudioGainConfig gainCfg = portCfg.gain();
3731         if (gainCfg != null) {
3732             AudioGain gain = port.gain(gainCfg.index());
3733             gainCfg = gain.buildConfig(gainCfg.mode(),
3734                                        gainCfg.channelMask(),
3735                                        gainCfg.values(),
3736                                        gainCfg.rampDurationMs());
3737         }
3738         return port.buildConfig(portCfg.samplingRate(),
3739                                                  portCfg.channelMask(),
3740                                                  portCfg.format(),
3741                                                  gainCfg);
3742     }
3743 }
3744