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