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