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