AudioManager.java revision 72668b2c040b581b298b069f3b5af5ed7f212d89
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.annotation.SdkConstant;
20import android.annotation.SdkConstant.SdkConstantType;
21import android.content.ComponentName;
22import android.content.Context;
23import android.database.ContentObserver;
24import android.os.Binder;
25import android.os.Handler;
26import android.os.IBinder;
27import android.os.Looper;
28import android.os.Message;
29import android.os.RemoteException;
30import android.os.SystemClock;
31import android.os.ServiceManager;
32import android.provider.Settings;
33import android.util.Log;
34import android.view.KeyEvent;
35import android.view.VolumePanel;
36
37import java.util.Iterator;
38import java.util.HashMap;
39
40/**
41 * AudioManager provides access to volume and ringer mode control.
42 * <p>
43 * Use <code>Context.getSystemService(Context.AUDIO_SERVICE)</code> to get
44 * an instance of this class.
45 */
46public class AudioManager {
47
48    private final Context mContext;
49    private final Handler mHandler;
50    private long mVolumeKeyUpTime;
51    private int  mVolumeControlStream = -1;
52    private static String TAG = "AudioManager";
53    private static boolean localLOGV = false;
54
55    /**
56     * Broadcast intent, a hint for applications that audio is about to become
57     * 'noisy' due to a change in audio outputs. For example, this intent may
58     * be sent when a wired headset is unplugged, or when an A2DP audio
59     * sink is disconnected, and the audio system is about to automatically
60     * switch audio route to the speaker. Applications that are controlling
61     * audio streams may consider pausing, reducing volume or some other action
62     * on receipt of this intent so as not to surprise the user with audio
63     * from the speaker.
64     */
65    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
66    public static final String ACTION_AUDIO_BECOMING_NOISY = "android.media.AUDIO_BECOMING_NOISY";
67
68    /**
69     * Sticky broadcast intent action indicating that the ringer mode has
70     * changed. Includes the new ringer mode.
71     *
72     * @see #EXTRA_RINGER_MODE
73     */
74    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
75    public static final String RINGER_MODE_CHANGED_ACTION = "android.media.RINGER_MODE_CHANGED";
76
77    /**
78     * The new ringer mode.
79     *
80     * @see #RINGER_MODE_CHANGED_ACTION
81     * @see #RINGER_MODE_NORMAL
82     * @see #RINGER_MODE_SILENT
83     * @see #RINGER_MODE_VIBRATE
84     */
85    public static final String EXTRA_RINGER_MODE = "android.media.EXTRA_RINGER_MODE";
86
87    /**
88     * Broadcast intent action indicating that the vibrate setting has
89     * changed. Includes the vibrate type and its new setting.
90     *
91     * @see #EXTRA_VIBRATE_TYPE
92     * @see #EXTRA_VIBRATE_SETTING
93     */
94    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
95    public static final String VIBRATE_SETTING_CHANGED_ACTION = "android.media.VIBRATE_SETTING_CHANGED";
96
97    /**
98     * @hide Broadcast intent when the volume for a particular stream type changes.
99     * Includes the stream, the new volume and previous volumes
100     *
101     * @see #EXTRA_VOLUME_STREAM_TYPE
102     * @see #EXTRA_VOLUME_STREAM_VALUE
103     * @see #EXTRA_PREV_VOLUME_STREAM_VALUE
104     */
105    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
106    public static final String VOLUME_CHANGED_ACTION = "android.media.VOLUME_CHANGED_ACTION";
107
108    /**
109     * The new vibrate setting for a particular type.
110     *
111     * @see #VIBRATE_SETTING_CHANGED_ACTION
112     * @see #EXTRA_VIBRATE_TYPE
113     * @see #VIBRATE_SETTING_ON
114     * @see #VIBRATE_SETTING_OFF
115     * @see #VIBRATE_SETTING_ONLY_SILENT
116     */
117    public static final String EXTRA_VIBRATE_SETTING = "android.media.EXTRA_VIBRATE_SETTING";
118
119    /**
120     * The vibrate type whose setting has changed.
121     *
122     * @see #VIBRATE_SETTING_CHANGED_ACTION
123     * @see #VIBRATE_TYPE_NOTIFICATION
124     * @see #VIBRATE_TYPE_RINGER
125     */
126    public static final String EXTRA_VIBRATE_TYPE = "android.media.EXTRA_VIBRATE_TYPE";
127
128    /**
129     * @hide The stream type for the volume changed intent.
130     */
131    public static final String EXTRA_VOLUME_STREAM_TYPE = "android.media.EXTRA_VOLUME_STREAM_TYPE";
132
133    /**
134     * @hide The volume associated with the stream for the volume changed intent.
135     */
136    public static final String EXTRA_VOLUME_STREAM_VALUE =
137        "android.media.EXTRA_VOLUME_STREAM_VALUE";
138
139    /**
140     * @hide The previous volume associated with the stream for the volume changed intent.
141     */
142    public static final String EXTRA_PREV_VOLUME_STREAM_VALUE =
143        "android.media.EXTRA_PREV_VOLUME_STREAM_VALUE";
144
145    /** The audio stream for phone calls */
146    public static final int STREAM_VOICE_CALL = AudioSystem.STREAM_VOICE_CALL;
147    /** The audio stream for system sounds */
148    public static final int STREAM_SYSTEM = AudioSystem.STREAM_SYSTEM;
149    /** The audio stream for the phone ring */
150    public static final int STREAM_RING = AudioSystem.STREAM_RING;
151    /** The audio stream for music playback */
152    public static final int STREAM_MUSIC = AudioSystem.STREAM_MUSIC;
153    /** The audio stream for alarms */
154    public static final int STREAM_ALARM = AudioSystem.STREAM_ALARM;
155    /** The audio stream for notifications */
156    public static final int STREAM_NOTIFICATION = AudioSystem.STREAM_NOTIFICATION;
157    /** @hide The audio stream for phone calls when connected to bluetooth */
158    public static final int STREAM_BLUETOOTH_SCO = AudioSystem.STREAM_BLUETOOTH_SCO;
159    /** @hide The audio stream for enforced system sounds in certain countries (e.g camera in Japan) */
160    public static final int STREAM_SYSTEM_ENFORCED = AudioSystem.STREAM_SYSTEM_ENFORCED;
161    /** The audio stream for DTMF Tones */
162    public static final int STREAM_DTMF = AudioSystem.STREAM_DTMF;
163    /** @hide The audio stream for text to speech (TTS) */
164    public static final int STREAM_TTS = AudioSystem.STREAM_TTS;
165    /** Number of audio streams */
166    /**
167     * @deprecated Use AudioSystem.getNumStreamTypes() instead
168     */
169    @Deprecated public static final int NUM_STREAMS = AudioSystem.NUM_STREAMS;
170
171
172    /**  @hide Default volume index values for audio streams */
173    public static final int[] DEFAULT_STREAM_VOLUME = new int[] {
174        4,  // STREAM_VOICE_CALL
175        7,  // STREAM_SYSTEM
176        5,  // STREAM_RING
177        11, // STREAM_MUSIC
178        6,  // STREAM_ALARM
179        5,  // STREAM_NOTIFICATION
180        7,  // STREAM_BLUETOOTH_SCO
181        7,  // STREAM_SYSTEM_ENFORCED
182        11, // STREAM_DTMF
183        11  // STREAM_TTS
184    };
185
186    /**
187     * Increase the ringer volume.
188     *
189     * @see #adjustVolume(int, int)
190     * @see #adjustStreamVolume(int, int, int)
191     */
192    public static final int ADJUST_RAISE = 1;
193
194    /**
195     * Decrease the ringer volume.
196     *
197     * @see #adjustVolume(int, int)
198     * @see #adjustStreamVolume(int, int, int)
199     */
200    public static final int ADJUST_LOWER = -1;
201
202    /**
203     * Maintain the previous ringer volume. This may be useful when needing to
204     * show the volume toast without actually modifying the volume.
205     *
206     * @see #adjustVolume(int, int)
207     * @see #adjustStreamVolume(int, int, int)
208     */
209    public static final int ADJUST_SAME = 0;
210
211    // Flags should be powers of 2!
212
213    /**
214     * Show a toast containing the current volume.
215     *
216     * @see #adjustStreamVolume(int, int, int)
217     * @see #adjustVolume(int, int)
218     * @see #setStreamVolume(int, int, int)
219     * @see #setRingerMode(int)
220     */
221    public static final int FLAG_SHOW_UI = 1 << 0;
222
223    /**
224     * Whether to include ringer modes as possible options when changing volume.
225     * For example, if true and volume level is 0 and the volume is adjusted
226     * with {@link #ADJUST_LOWER}, then the ringer mode may switch the silent or
227     * vibrate mode.
228     * <p>
229     * By default this is on for the ring stream. If this flag is included,
230     * this behavior will be present regardless of the stream type being
231     * affected by the ringer mode.
232     *
233     * @see #adjustVolume(int, int)
234     * @see #adjustStreamVolume(int, int, int)
235     */
236    public static final int FLAG_ALLOW_RINGER_MODES = 1 << 1;
237
238    /**
239     * Whether to play a sound when changing the volume.
240     * <p>
241     * If this is given to {@link #adjustVolume(int, int)} or
242     * {@link #adjustSuggestedStreamVolume(int, int, int)}, it may be ignored
243     * in some cases (for example, the decided stream type is not
244     * {@link AudioManager#STREAM_RING}, or the volume is being adjusted
245     * downward).
246     *
247     * @see #adjustStreamVolume(int, int, int)
248     * @see #adjustVolume(int, int)
249     * @see #setStreamVolume(int, int, int)
250     */
251    public static final int FLAG_PLAY_SOUND = 1 << 2;
252
253    /**
254     * Removes any sounds/vibrate that may be in the queue, or are playing (related to
255     * changing volume).
256     */
257    public static final int FLAG_REMOVE_SOUND_AND_VIBRATE = 1 << 3;
258
259    /**
260     * Whether to vibrate if going into the vibrate ringer mode.
261     */
262    public static final int FLAG_VIBRATE = 1 << 4;
263
264    /**
265     * forces use of specified stream
266     * @hide
267     */
268    public static final int FLAG_FORCE_STREAM = 1 << 5;
269
270
271    /**
272     * Ringer mode that will be silent and will not vibrate. (This overrides the
273     * vibrate setting.)
274     *
275     * @see #setRingerMode(int)
276     * @see #getRingerMode()
277     */
278    public static final int RINGER_MODE_SILENT = 0;
279
280    /**
281     * Ringer mode that will be silent and will vibrate. (This will cause the
282     * phone ringer to always vibrate, but the notification vibrate to only
283     * vibrate if set.)
284     *
285     * @see #setRingerMode(int)
286     * @see #getRingerMode()
287     */
288    public static final int RINGER_MODE_VIBRATE = 1;
289
290    /**
291     * Ringer mode that may be audible and may vibrate. It will be audible if
292     * the volume before changing out of this mode was audible. It will vibrate
293     * if the vibrate setting is on.
294     *
295     * @see #setRingerMode(int)
296     * @see #getRingerMode()
297     */
298    public static final int RINGER_MODE_NORMAL = 2;
299
300    // maximum valid ringer mode value. Values must start from 0 and be contiguous.
301    private static final int RINGER_MODE_MAX = RINGER_MODE_NORMAL;
302
303    /**
304     * Vibrate type that corresponds to the ringer.
305     *
306     * @see #setVibrateSetting(int, int)
307     * @see #getVibrateSetting(int)
308     * @see #shouldVibrate(int)
309     */
310    public static final int VIBRATE_TYPE_RINGER = 0;
311
312    /**
313     * Vibrate type that corresponds to notifications.
314     *
315     * @see #setVibrateSetting(int, int)
316     * @see #getVibrateSetting(int)
317     * @see #shouldVibrate(int)
318     */
319    public static final int VIBRATE_TYPE_NOTIFICATION = 1;
320
321    /**
322     * Vibrate setting that suggests to never vibrate.
323     *
324     * @see #setVibrateSetting(int, int)
325     * @see #getVibrateSetting(int)
326     */
327    public static final int VIBRATE_SETTING_OFF = 0;
328
329    /**
330     * Vibrate setting that suggests to vibrate when possible.
331     *
332     * @see #setVibrateSetting(int, int)
333     * @see #getVibrateSetting(int)
334     */
335    public static final int VIBRATE_SETTING_ON = 1;
336
337    /**
338     * Vibrate setting that suggests to only vibrate when in the vibrate ringer
339     * mode.
340     *
341     * @see #setVibrateSetting(int, int)
342     * @see #getVibrateSetting(int)
343     */
344    public static final int VIBRATE_SETTING_ONLY_SILENT = 2;
345
346    /**
347     * Suggests using the default stream type. This may not be used in all
348     * places a stream type is needed.
349     */
350    public static final int USE_DEFAULT_STREAM_TYPE = Integer.MIN_VALUE;
351
352    private static IAudioService sService;
353
354    /**
355     * @hide
356     */
357    public AudioManager(Context context) {
358        mContext = context;
359        mHandler = new Handler(context.getMainLooper());
360    }
361
362    private static IAudioService getService()
363    {
364        if (sService != null) {
365            return sService;
366        }
367        IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
368        sService = IAudioService.Stub.asInterface(b);
369        return sService;
370    }
371
372    /**
373     * @hide
374     */
375    public void preDispatchKeyEvent(int keyCode, int stream) {
376        /*
377         * If the user hits another key within the play sound delay, then
378         * cancel the sound
379         */
380        if (keyCode != KeyEvent.KEYCODE_VOLUME_DOWN && keyCode != KeyEvent.KEYCODE_VOLUME_UP
381                && keyCode != KeyEvent.KEYCODE_VOLUME_MUTE
382                && mVolumeKeyUpTime + VolumePanel.PLAY_SOUND_DELAY
383                        > SystemClock.uptimeMillis()) {
384            /*
385             * The user has hit another key during the delay (e.g., 300ms)
386             * since the last volume key up, so cancel any sounds.
387             */
388            adjustSuggestedStreamVolume(AudioManager.ADJUST_SAME,
389                        stream, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
390        }
391    }
392
393    /**
394     * @hide
395     */
396    public void handleKeyDown(int keyCode, int stream) {
397        switch (keyCode) {
398            case KeyEvent.KEYCODE_VOLUME_UP:
399            case KeyEvent.KEYCODE_VOLUME_DOWN:
400                /*
401                 * Adjust the volume in on key down since it is more
402                 * responsive to the user.
403                 */
404                int flags = FLAG_SHOW_UI | FLAG_VIBRATE;
405                if (mVolumeControlStream != -1) {
406                    stream = mVolumeControlStream;
407                    flags |= FLAG_FORCE_STREAM;
408                }
409                adjustSuggestedStreamVolume(
410                        keyCode == KeyEvent.KEYCODE_VOLUME_UP
411                                ? ADJUST_RAISE
412                                : ADJUST_LOWER,
413                        stream,
414                        flags);
415                break;
416            case KeyEvent.KEYCODE_VOLUME_MUTE:
417                // TODO: Actually handle MUTE.
418                break;
419        }
420    }
421
422    /**
423     * @hide
424     */
425    public void handleKeyUp(int keyCode, int stream) {
426        switch (keyCode) {
427            case KeyEvent.KEYCODE_VOLUME_UP:
428            case KeyEvent.KEYCODE_VOLUME_DOWN:
429                /*
430                 * Play a sound. This is done on key up since we don't want the
431                 * sound to play when a user holds down volume down to mute.
432                 */
433                int flags = FLAG_PLAY_SOUND;
434                if (mVolumeControlStream != -1) {
435                    stream = mVolumeControlStream;
436                    flags |= FLAG_FORCE_STREAM;
437                }
438                adjustSuggestedStreamVolume(
439                        ADJUST_SAME,
440                        stream,
441                        flags);
442
443                mVolumeKeyUpTime = SystemClock.uptimeMillis();
444                break;
445            case KeyEvent.KEYCODE_VOLUME_MUTE:
446                // TODO: Actually handle MUTE.
447                break;
448        }
449    }
450
451    /**
452     * Adjusts the volume of a particular stream by one step in a direction.
453     * <p>
454     * This method should only be used by applications that replace the platform-wide
455     * management of audio settings or the main telephony application.
456     *
457     * @param streamType The stream type to adjust. One of {@link #STREAM_VOICE_CALL},
458     * {@link #STREAM_SYSTEM}, {@link #STREAM_RING}, {@link #STREAM_MUSIC} or
459     * {@link #STREAM_ALARM}
460     * @param direction The direction to adjust the volume. One of
461     *            {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, or
462     *            {@link #ADJUST_SAME}.
463     * @param flags One or more flags.
464     * @see #adjustVolume(int, int)
465     * @see #setStreamVolume(int, int, int)
466     */
467    public void adjustStreamVolume(int streamType, int direction, int flags) {
468        IAudioService service = getService();
469        try {
470            service.adjustStreamVolume(streamType, direction, flags);
471        } catch (RemoteException e) {
472            Log.e(TAG, "Dead object in adjustStreamVolume", e);
473        }
474    }
475
476    /**
477     * Adjusts the volume of the most relevant stream. For example, if a call is
478     * active, it will have the highest priority regardless of if the in-call
479     * screen is showing. Another example, if music is playing in the background
480     * and a call is not active, the music stream will be adjusted.
481     * <p>
482     * This method should only be used by applications that replace the platform-wide
483     * management of audio settings or the main telephony application.
484     *
485     * @param direction The direction to adjust the volume. One of
486     *            {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, or
487     *            {@link #ADJUST_SAME}.
488     * @param flags One or more flags.
489     * @see #adjustSuggestedStreamVolume(int, int, int)
490     * @see #adjustStreamVolume(int, int, int)
491     * @see #setStreamVolume(int, int, int)
492     */
493    public void adjustVolume(int direction, int flags) {
494        IAudioService service = getService();
495        try {
496            service.adjustVolume(direction, flags);
497        } catch (RemoteException e) {
498            Log.e(TAG, "Dead object in adjustVolume", e);
499        }
500    }
501
502    /**
503     * Adjusts the volume of the most relevant stream, or the given fallback
504     * stream.
505     * <p>
506     * This method should only be used by applications that replace the platform-wide
507     * management of audio settings or the main telephony application.
508     *
509     * @param direction The direction to adjust the volume. One of
510     *            {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, or
511     *            {@link #ADJUST_SAME}.
512     * @param suggestedStreamType The stream type that will be used if there
513     *            isn't a relevant stream. {@link #USE_DEFAULT_STREAM_TYPE} is valid here.
514     * @param flags One or more flags.
515     * @see #adjustVolume(int, int)
516     * @see #adjustStreamVolume(int, int, int)
517     * @see #setStreamVolume(int, int, int)
518     */
519    public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags) {
520        IAudioService service = getService();
521        try {
522            service.adjustSuggestedStreamVolume(direction, suggestedStreamType, flags);
523        } catch (RemoteException e) {
524            Log.e(TAG, "Dead object in adjustVolume", e);
525        }
526    }
527
528    /**
529     * Returns the current ringtone mode.
530     *
531     * @return The current ringtone mode, one of {@link #RINGER_MODE_NORMAL},
532     *         {@link #RINGER_MODE_SILENT}, or {@link #RINGER_MODE_VIBRATE}.
533     * @see #setRingerMode(int)
534     */
535    public int getRingerMode() {
536        IAudioService service = getService();
537        try {
538            return service.getRingerMode();
539        } catch (RemoteException e) {
540            Log.e(TAG, "Dead object in getRingerMode", e);
541            return RINGER_MODE_NORMAL;
542        }
543    }
544
545    /**
546     * Checks valid ringer mode values.
547     *
548     * @return true if the ringer mode indicated is valid, false otherwise.
549     *
550     * @see #setRingerMode(int)
551     * @hide
552     */
553    public static boolean isValidRingerMode(int ringerMode) {
554        if (ringerMode < 0 || ringerMode > RINGER_MODE_MAX) {
555            return false;
556        }
557        return true;
558    }
559
560    /**
561     * Returns the maximum volume index for a particular stream.
562     *
563     * @param streamType The stream type whose maximum volume index is returned.
564     * @return The maximum valid volume index for the stream.
565     * @see #getStreamVolume(int)
566     */
567    public int getStreamMaxVolume(int streamType) {
568        IAudioService service = getService();
569        try {
570            return service.getStreamMaxVolume(streamType);
571        } catch (RemoteException e) {
572            Log.e(TAG, "Dead object in getStreamMaxVolume", e);
573            return 0;
574        }
575    }
576
577    /**
578     * Returns the current volume index for a particular stream.
579     *
580     * @param streamType The stream type whose volume index is returned.
581     * @return The current volume index for the stream.
582     * @see #getStreamMaxVolume(int)
583     * @see #setStreamVolume(int, int, int)
584     */
585    public int getStreamVolume(int streamType) {
586        IAudioService service = getService();
587        try {
588            return service.getStreamVolume(streamType);
589        } catch (RemoteException e) {
590            Log.e(TAG, "Dead object in getStreamVolume", e);
591            return 0;
592        }
593    }
594
595    /**
596     * Get last audible volume before stream was muted.
597     *
598     * @hide
599     */
600    public int getLastAudibleStreamVolume(int streamType) {
601        IAudioService service = getService();
602        try {
603            return service.getLastAudibleStreamVolume(streamType);
604        } catch (RemoteException e) {
605            Log.e(TAG, "Dead object in getLastAudibleStreamVolume", e);
606            return 0;
607        }
608    }
609
610    /**
611     * Sets the ringer mode.
612     * <p>
613     * Silent mode will mute the volume and will not vibrate. Vibrate mode will
614     * mute the volume and vibrate. Normal mode will be audible and may vibrate
615     * according to user settings.
616     *
617     * @param ringerMode The ringer mode, one of {@link #RINGER_MODE_NORMAL},
618     *            {@link #RINGER_MODE_SILENT}, or {@link #RINGER_MODE_VIBRATE}.
619     * @see #getRingerMode()
620     */
621    public void setRingerMode(int ringerMode) {
622        if (!isValidRingerMode(ringerMode)) {
623            return;
624        }
625        IAudioService service = getService();
626        try {
627            service.setRingerMode(ringerMode);
628        } catch (RemoteException e) {
629            Log.e(TAG, "Dead object in setRingerMode", e);
630        }
631    }
632
633    /**
634     * Sets the volume index for a particular stream.
635     *
636     * @param streamType The stream whose volume index should be set.
637     * @param index The volume index to set. See
638     *            {@link #getStreamMaxVolume(int)} for the largest valid value.
639     * @param flags One or more flags.
640     * @see #getStreamMaxVolume(int)
641     * @see #getStreamVolume(int)
642     */
643    public void setStreamVolume(int streamType, int index, int flags) {
644        IAudioService service = getService();
645        try {
646            service.setStreamVolume(streamType, index, flags);
647        } catch (RemoteException e) {
648            Log.e(TAG, "Dead object in setStreamVolume", e);
649        }
650    }
651
652    /**
653     * Solo or unsolo a particular stream. All other streams are muted.
654     * <p>
655     * The solo command is protected against client process death: if a process
656     * with an active solo request on a stream dies, all streams that were muted
657     * because of this request will be unmuted automatically.
658     * <p>
659     * The solo requests for a given stream are cumulative: the AudioManager
660     * can receive several solo requests from one or more clients and the stream
661     * will be unsoloed only when the same number of unsolo requests are received.
662     * <p>
663     * For a better user experience, applications MUST unsolo a soloed stream
664     * in onPause() and solo is again in onResume() if appropriate.
665     *
666     * @param streamType The stream to be soloed/unsoloed.
667     * @param state The required solo state: true for solo ON, false for solo OFF
668     */
669    public void setStreamSolo(int streamType, boolean state) {
670        IAudioService service = getService();
671        try {
672            service.setStreamSolo(streamType, state, mICallBack);
673        } catch (RemoteException e) {
674            Log.e(TAG, "Dead object in setStreamSolo", e);
675        }
676    }
677
678    /**
679     * Mute or unmute an audio stream.
680     * <p>
681     * The mute command is protected against client process death: if a process
682     * with an active mute request on a stream dies, this stream will be unmuted
683     * automatically.
684     * <p>
685     * The mute requests for a given stream are cumulative: the AudioManager
686     * can receive several mute requests from one or more clients and the stream
687     * will be unmuted only when the same number of unmute requests are received.
688     * <p>
689     * For a better user experience, applications MUST unmute a muted stream
690     * in onPause() and mute is again in onResume() if appropriate.
691     * <p>
692     * This method should only be used by applications that replace the platform-wide
693     * management of audio settings or the main telephony application.
694     *
695     * @param streamType The stream to be muted/unmuted.
696     * @param state The required mute state: true for mute ON, false for mute OFF
697     */
698    public void setStreamMute(int streamType, boolean state) {
699        IAudioService service = getService();
700        try {
701            service.setStreamMute(streamType, state, mICallBack);
702        } catch (RemoteException e) {
703            Log.e(TAG, "Dead object in setStreamMute", e);
704        }
705    }
706
707    /**
708     * get stream mute state.
709     *
710     * @hide
711     */
712    public boolean isStreamMute(int streamType) {
713        IAudioService service = getService();
714        try {
715            return service.isStreamMute(streamType);
716        } catch (RemoteException e) {
717            Log.e(TAG, "Dead object in isStreamMute", e);
718            return false;
719        }
720    }
721
722    /**
723     * forces the stream controlled by hard volume keys
724     * specifying streamType == -1 releases control to the
725     * logic.
726     *
727     * @hide
728     */
729    public void forceVolumeControlStream(int streamType) {
730        mVolumeControlStream = streamType;
731    }
732
733    /**
734     * Returns whether a particular type should vibrate according to user
735     * settings and the current ringer mode.
736     * <p>
737     * This shouldn't be needed by most clients that use notifications to
738     * vibrate. The notification manager will not vibrate if the policy doesn't
739     * allow it, so the client should always set a vibrate pattern and let the
740     * notification manager control whether or not to actually vibrate.
741     *
742     * @param vibrateType The type of vibrate. One of
743     *            {@link #VIBRATE_TYPE_NOTIFICATION} or
744     *            {@link #VIBRATE_TYPE_RINGER}.
745     * @return Whether the type should vibrate at the instant this method is
746     *         called.
747     * @see #setVibrateSetting(int, int)
748     * @see #getVibrateSetting(int)
749     */
750    public boolean shouldVibrate(int vibrateType) {
751        IAudioService service = getService();
752        try {
753            return service.shouldVibrate(vibrateType);
754        } catch (RemoteException e) {
755            Log.e(TAG, "Dead object in shouldVibrate", e);
756            return false;
757        }
758    }
759
760    /**
761     * Returns whether the user's vibrate setting for a vibrate type.
762     * <p>
763     * This shouldn't be needed by most clients that want to vibrate, instead
764     * see {@link #shouldVibrate(int)}.
765     *
766     * @param vibrateType The type of vibrate. One of
767     *            {@link #VIBRATE_TYPE_NOTIFICATION} or
768     *            {@link #VIBRATE_TYPE_RINGER}.
769     * @return The vibrate setting, one of {@link #VIBRATE_SETTING_ON},
770     *         {@link #VIBRATE_SETTING_OFF}, or
771     *         {@link #VIBRATE_SETTING_ONLY_SILENT}.
772     * @see #setVibrateSetting(int, int)
773     * @see #shouldVibrate(int)
774     */
775    public int getVibrateSetting(int vibrateType) {
776        IAudioService service = getService();
777        try {
778            return service.getVibrateSetting(vibrateType);
779        } catch (RemoteException e) {
780            Log.e(TAG, "Dead object in getVibrateSetting", e);
781            return VIBRATE_SETTING_OFF;
782        }
783    }
784
785    /**
786     * Sets the setting for when the vibrate type should vibrate.
787     * <p>
788     * This method should only be used by applications that replace the platform-wide
789     * management of audio settings or the main telephony application.
790     *
791     * @param vibrateType The type of vibrate. One of
792     *            {@link #VIBRATE_TYPE_NOTIFICATION} or
793     *            {@link #VIBRATE_TYPE_RINGER}.
794     * @param vibrateSetting The vibrate setting, one of
795     *            {@link #VIBRATE_SETTING_ON},
796     *            {@link #VIBRATE_SETTING_OFF}, or
797     *            {@link #VIBRATE_SETTING_ONLY_SILENT}.
798     * @see #getVibrateSetting(int)
799     * @see #shouldVibrate(int)
800     */
801    public void setVibrateSetting(int vibrateType, int vibrateSetting) {
802        IAudioService service = getService();
803        try {
804            service.setVibrateSetting(vibrateType, vibrateSetting);
805        } catch (RemoteException e) {
806            Log.e(TAG, "Dead object in setVibrateSetting", e);
807        }
808    }
809
810    /**
811     * Sets the speakerphone on or off.
812     * <p>
813     * This method should only be used by applications that replace the platform-wide
814     * management of audio settings or the main telephony application.
815     *
816     * @param on set <var>true</var> to turn on speakerphone;
817     *           <var>false</var> to turn it off
818     */
819    public void setSpeakerphoneOn(boolean on){
820        IAudioService service = getService();
821        try {
822            service.setSpeakerphoneOn(on);
823        } catch (RemoteException e) {
824            Log.e(TAG, "Dead object in setSpeakerphoneOn", e);
825        }
826    }
827
828    /**
829     * Checks whether the speakerphone is on or off.
830     *
831     * @return true if speakerphone is on, false if it's off
832     */
833    public boolean isSpeakerphoneOn() {
834        IAudioService service = getService();
835        try {
836            return service.isSpeakerphoneOn();
837        } catch (RemoteException e) {
838            Log.e(TAG, "Dead object in isSpeakerphoneOn", e);
839            return false;
840        }
841     }
842
843    //====================================================================
844    // Bluetooth SCO control
845    /**
846     * Sticky broadcast intent action indicating that the bluetoooth SCO audio
847     * connection state has changed. The intent contains on extra {@link #EXTRA_SCO_AUDIO_STATE}
848     * indicating the new state which is either {@link #SCO_AUDIO_STATE_DISCONNECTED}
849     * or {@link #SCO_AUDIO_STATE_CONNECTED}
850     *
851     * @see #startBluetoothSco()
852     * @deprecated Use  {@link #ACTION_SCO_AUDIO_STATE_UPDATED} instead
853     */
854    @Deprecated
855    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
856    public static final String ACTION_SCO_AUDIO_STATE_CHANGED =
857            "android.media.SCO_AUDIO_STATE_CHANGED";
858
859     /**
860     * Sticky broadcast intent action indicating that the bluetoooth SCO audio
861     * connection state has been updated.
862     * <p>This intent has two extras:
863     * <ul>
864     *   <li> {@link #EXTRA_SCO_AUDIO_STATE} - The new SCO audio state. </li>
865     *   <li> {@link #EXTRA_SCO_AUDIO_PREVIOUS_STATE}- The previous SCO audio state. </li>
866     * </ul>
867     * <p> EXTRA_SCO_AUDIO_STATE or EXTRA_SCO_AUDIO_PREVIOUS_STATE can be any of:
868     * <ul>
869     *   <li> {@link #SCO_AUDIO_STATE_DISCONNECTED}, </li>
870     *   <li> {@link #SCO_AUDIO_STATE_CONNECTING} or </li>
871     *   <li> {@link #SCO_AUDIO_STATE_CONNECTED}, </li>
872     * </ul>
873     * @see #startBluetoothSco()
874     */
875    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
876    public static final String ACTION_SCO_AUDIO_STATE_UPDATED =
877            "android.media.ACTION_SCO_AUDIO_STATE_UPDATED";
878
879    /**
880     * Extra for intent {@link #ACTION_SCO_AUDIO_STATE_CHANGED} or
881     * {@link #ACTION_SCO_AUDIO_STATE_UPDATED} containing the new bluetooth SCO connection state.
882     */
883    public static final String EXTRA_SCO_AUDIO_STATE =
884            "android.media.extra.SCO_AUDIO_STATE";
885
886    /**
887     * Extra for intent {@link #ACTION_SCO_AUDIO_STATE_UPDATED} containing the previous
888     * bluetooth SCO connection state.
889     */
890    public static final String EXTRA_SCO_AUDIO_PREVIOUS_STATE =
891            "android.media.extra.SCO_AUDIO_PREVIOUS_STATE";
892
893    /**
894     * Value for extra EXTRA_SCO_AUDIO_STATE or EXTRA_SCO_AUDIO_PREVIOUS_STATE
895     * indicating that the SCO audio channel is not established
896     */
897    public static final int SCO_AUDIO_STATE_DISCONNECTED = 0;
898    /**
899     * Value for extra {@link #EXTRA_SCO_AUDIO_STATE} or {@link #EXTRA_SCO_AUDIO_PREVIOUS_STATE}
900     * indicating that the SCO audio channel is established
901     */
902    public static final int SCO_AUDIO_STATE_CONNECTED = 1;
903    /**
904     * Value for extra EXTRA_SCO_AUDIO_STATE or EXTRA_SCO_AUDIO_PREVIOUS_STATE
905     * indicating that the SCO audio channel is being established
906     */
907    public static final int SCO_AUDIO_STATE_CONNECTING = 2;
908    /**
909     * Value for extra EXTRA_SCO_AUDIO_STATE indicating that
910     * there was an error trying to obtain the state
911     */
912    public static final int SCO_AUDIO_STATE_ERROR = -1;
913
914
915    /**
916     * Indicates if current platform supports use of SCO for off call use cases.
917     * Application wanted to use bluetooth SCO audio when the phone is not in call
918     * must first call thsi method to make sure that the platform supports this
919     * feature.
920     * @return true if bluetooth SCO can be used for audio when not in call
921     *         false otherwise
922     * @see #startBluetoothSco()
923    */
924    public boolean isBluetoothScoAvailableOffCall() {
925        return mContext.getResources().getBoolean(
926               com.android.internal.R.bool.config_bluetooth_sco_off_call);
927    }
928
929    /**
930     * Start bluetooth SCO audio connection.
931     * <p>Requires Permission:
932     *   {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}.
933     * <p>This method can be used by applications wanting to send and received audio
934     * to/from a bluetooth SCO headset while the phone is not in call.
935     * <p>As the SCO connection establishment can take several seconds,
936     * applications should not rely on the connection to be available when the method
937     * returns but instead register to receive the intent {@link #ACTION_SCO_AUDIO_STATE_UPDATED}
938     * and wait for the state to be {@link #SCO_AUDIO_STATE_CONNECTED}.
939     * <p>As the ACTION_SCO_AUDIO_STATE_UPDATED intent is sticky, the application can check the SCO
940     * audio state before calling startBluetoothSco() by reading the intent returned by the receiver
941     * registration. If the state is already CONNECTED, no state change will be received via the
942     * intent after calling startBluetoothSco(). It is however useful to call startBluetoothSco()
943     * so that the connection stays active in case the current initiator stops the connection.
944     * <p>Unless the connection is already active as described above, the state will always
945     * transition from DISCONNECTED to CONNECTING and then either to CONNECTED if the connection
946     * succeeds or back to DISCONNECTED if the connection fails (e.g no headset is connected).
947     * <p>When finished with the SCO connection or if the establishment fails, the application must
948     * call {@link #stopBluetoothSco()} to clear the request and turn down the bluetooth connection.
949     * <p>Even if a SCO connection is established, the following restrictions apply on audio
950     * output streams so that they can be routed to SCO headset:
951     * <ul>
952     *   <li> the stream type must be {@link #STREAM_VOICE_CALL} </li>
953     *   <li> the format must be mono </li>
954     *   <li> the sampling must be 16kHz or 8kHz </li>
955     * </ul>
956     * <p>The following restrictions apply on input streams:
957     * <ul>
958     *   <li> the format must be mono </li>
959     *   <li> the sampling must be 8kHz </li>
960     * </ul>
961     * <p>Note that the phone application always has the priority on the usage of the SCO
962     * connection for telephony. If this method is called while the phone is in call
963     * it will be ignored. Similarly, if a call is received or sent while an application
964     * is using the SCO connection, the connection will be lost for the application and NOT
965     * returned automatically when the call ends.
966     * @see #stopBluetoothSco()
967     * @see #ACTION_SCO_AUDIO_STATE_UPDATED
968     */
969    public void startBluetoothSco(){
970        IAudioService service = getService();
971        try {
972            service.startBluetoothSco(mICallBack);
973        } catch (RemoteException e) {
974            Log.e(TAG, "Dead object in startBluetoothSco", e);
975        }
976    }
977
978    /**
979     * Stop bluetooth SCO audio connection.
980     * <p>Requires Permission:
981     *   {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}.
982     * <p>This method must be called by applications having requested the use of
983     * bluetooth SCO audio with {@link #startBluetoothSco()}
984     * when finished with the SCO connection or if connection fails.
985     * @see #startBluetoothSco()
986     */
987    public void stopBluetoothSco(){
988        IAudioService service = getService();
989        try {
990            service.stopBluetoothSco(mICallBack);
991        } catch (RemoteException e) {
992            Log.e(TAG, "Dead object in stopBluetoothSco", e);
993        }
994    }
995
996    /**
997     * Request use of Bluetooth SCO headset for communications.
998     * <p>
999     * This method should only be used by applications that replace the platform-wide
1000     * management of audio settings or the main telephony application.
1001     *
1002     * @param on set <var>true</var> to use bluetooth SCO for communications;
1003     *               <var>false</var> to not use bluetooth SCO for communications
1004     */
1005    public void setBluetoothScoOn(boolean on){
1006        IAudioService service = getService();
1007        try {
1008            service.setBluetoothScoOn(on);
1009        } catch (RemoteException e) {
1010            Log.e(TAG, "Dead object in setBluetoothScoOn", e);
1011        }
1012    }
1013
1014    /**
1015     * Checks whether communications use Bluetooth SCO.
1016     *
1017     * @return true if SCO is used for communications;
1018     *         false if otherwise
1019     */
1020    public boolean isBluetoothScoOn() {
1021        IAudioService service = getService();
1022        try {
1023            return service.isBluetoothScoOn();
1024        } catch (RemoteException e) {
1025            Log.e(TAG, "Dead object in isBluetoothScoOn", e);
1026            return false;
1027        }
1028    }
1029
1030    /**
1031     * @param on set <var>true</var> to route A2DP audio to/from Bluetooth
1032     *           headset; <var>false</var> disable A2DP audio
1033     * @deprecated Do not use.
1034     */
1035    @Deprecated public void setBluetoothA2dpOn(boolean on){
1036    }
1037
1038    /**
1039     * Checks whether A2DP audio routing to the Bluetooth headset is on or off.
1040     *
1041     * @return true if A2DP audio is being routed to/from Bluetooth headset;
1042     *         false if otherwise
1043     */
1044    public boolean isBluetoothA2dpOn() {
1045        if (AudioSystem.getDeviceConnectionState(DEVICE_OUT_BLUETOOTH_A2DP,"")
1046            == AudioSystem.DEVICE_STATE_UNAVAILABLE) {
1047            return false;
1048        } else {
1049            return true;
1050        }
1051    }
1052
1053    /**
1054     * Sets audio routing to the wired headset on or off.
1055     *
1056     * @param on set <var>true</var> to route audio to/from wired
1057     *           headset; <var>false</var> disable wired headset audio
1058     * @deprecated Do not use.
1059     */
1060    @Deprecated public void setWiredHeadsetOn(boolean on){
1061    }
1062
1063    /**
1064     * Checks whether audio routing to the wired headset is on or off.
1065     *
1066     * @return true if audio is being routed to/from wired headset;
1067     *         false if otherwise
1068     */
1069    public boolean isWiredHeadsetOn() {
1070        if (AudioSystem.getDeviceConnectionState(DEVICE_OUT_WIRED_HEADSET,"")
1071                == AudioSystem.DEVICE_STATE_UNAVAILABLE &&
1072            AudioSystem.getDeviceConnectionState(DEVICE_OUT_WIRED_HEADPHONE,"")
1073                == AudioSystem.DEVICE_STATE_UNAVAILABLE) {
1074            return false;
1075        } else {
1076            return true;
1077        }
1078    }
1079
1080    /**
1081     * Sets the microphone mute on or off.
1082     * <p>
1083     * This method should only be used by applications that replace the platform-wide
1084     * management of audio settings or the main telephony application.
1085     *
1086     * @param on set <var>true</var> to mute the microphone;
1087     *           <var>false</var> to turn mute off
1088     */
1089    public void setMicrophoneMute(boolean on){
1090        AudioSystem.muteMicrophone(on);
1091    }
1092
1093    /**
1094     * Checks whether the microphone mute is on or off.
1095     *
1096     * @return true if microphone is muted, false if it's not
1097     */
1098    public boolean isMicrophoneMute() {
1099        return AudioSystem.isMicrophoneMuted();
1100    }
1101
1102    /**
1103     * Sets the audio mode.
1104     * <p>
1105     * The audio mode encompasses audio routing AND the behavior of
1106     * the telephony layer. Therefore this method should only be used by applications that
1107     * replace the platform-wide management of audio settings or the main telephony application.
1108     * In particular, the {@link #MODE_IN_CALL} mode should only be used by the telephony
1109     * application when it places a phone call, as it will cause signals from the radio layer
1110     * to feed the platform mixer.
1111     *
1112     * @param mode  the requested audio mode ({@link #MODE_NORMAL}, {@link #MODE_RINGTONE},
1113     *              {@link #MODE_IN_CALL} or {@link #MODE_IN_COMMUNICATION}).
1114     *              Informs the HAL about the current audio state so that
1115     *              it can route the audio appropriately.
1116     */
1117    public void setMode(int mode) {
1118        IAudioService service = getService();
1119        try {
1120            service.setMode(mode, mICallBack);
1121        } catch (RemoteException e) {
1122            Log.e(TAG, "Dead object in setMode", e);
1123        }
1124    }
1125
1126    /**
1127     * Returns the current audio mode.
1128     *
1129     * @return      the current audio mode ({@link #MODE_NORMAL}, {@link #MODE_RINGTONE},
1130     *              {@link #MODE_IN_CALL} or {@link #MODE_IN_COMMUNICATION}).
1131     *              Returns the current current audio state from the HAL.
1132     */
1133    public int getMode() {
1134        IAudioService service = getService();
1135        try {
1136            return service.getMode();
1137        } catch (RemoteException e) {
1138            Log.e(TAG, "Dead object in getMode", e);
1139            return MODE_INVALID;
1140        }
1141    }
1142
1143    /* modes for setMode/getMode/setRoute/getRoute */
1144    /**
1145     * Audio harware modes.
1146     */
1147    /**
1148     * Invalid audio mode.
1149     */
1150    public static final int MODE_INVALID            = AudioSystem.MODE_INVALID;
1151    /**
1152     * Current audio mode. Used to apply audio routing to current mode.
1153     */
1154    public static final int MODE_CURRENT            = AudioSystem.MODE_CURRENT;
1155    /**
1156     * Normal audio mode: not ringing and no call established.
1157     */
1158    public static final int MODE_NORMAL             = AudioSystem.MODE_NORMAL;
1159    /**
1160     * Ringing audio mode. An incoming is being signaled.
1161     */
1162    public static final int MODE_RINGTONE           = AudioSystem.MODE_RINGTONE;
1163    /**
1164     * In call audio mode. A telephony call is established.
1165     */
1166    public static final int MODE_IN_CALL            = AudioSystem.MODE_IN_CALL;
1167    /**
1168     * In communication audio mode. An audio/video chat or VoIP call is established.
1169     */
1170    public static final int MODE_IN_COMMUNICATION   = AudioSystem.MODE_IN_COMMUNICATION;
1171
1172    /* Routing bits for setRouting/getRouting API */
1173    /**
1174     * Routing audio output to earpiece
1175     * @deprecated   Do not set audio routing directly, use setSpeakerphoneOn(),
1176     * setBluetoothScoOn() methods instead.
1177     */
1178    @Deprecated public static final int ROUTE_EARPIECE          = AudioSystem.ROUTE_EARPIECE;
1179    /**
1180     * Routing audio output to speaker
1181     * @deprecated   Do not set audio routing directly, use setSpeakerphoneOn(),
1182     * setBluetoothScoOn() methods instead.
1183     */
1184    @Deprecated public static final int ROUTE_SPEAKER           = AudioSystem.ROUTE_SPEAKER;
1185    /**
1186     * @deprecated use {@link #ROUTE_BLUETOOTH_SCO}
1187     * @deprecated   Do not set audio routing directly, use setSpeakerphoneOn(),
1188     * setBluetoothScoOn() methods instead.
1189     */
1190    @Deprecated public static final int ROUTE_BLUETOOTH = AudioSystem.ROUTE_BLUETOOTH_SCO;
1191    /**
1192     * Routing audio output to bluetooth SCO
1193     * @deprecated   Do not set audio routing directly, use setSpeakerphoneOn(),
1194     * setBluetoothScoOn() methods instead.
1195     */
1196    @Deprecated public static final int ROUTE_BLUETOOTH_SCO     = AudioSystem.ROUTE_BLUETOOTH_SCO;
1197    /**
1198     * Routing audio output to headset
1199     * @deprecated   Do not set audio routing directly, use setSpeakerphoneOn(),
1200     * setBluetoothScoOn() methods instead.
1201     */
1202    @Deprecated public static final int ROUTE_HEADSET           = AudioSystem.ROUTE_HEADSET;
1203    /**
1204     * Routing audio output to bluetooth A2DP
1205     * @deprecated   Do not set audio routing directly, use setSpeakerphoneOn(),
1206     * setBluetoothScoOn() methods instead.
1207     */
1208    @Deprecated public static final int ROUTE_BLUETOOTH_A2DP    = AudioSystem.ROUTE_BLUETOOTH_A2DP;
1209    /**
1210     * Used for mask parameter of {@link #setRouting(int,int,int)}.
1211     * @deprecated   Do not set audio routing directly, use setSpeakerphoneOn(),
1212     * setBluetoothScoOn() methods instead.
1213     */
1214    @Deprecated public static final int ROUTE_ALL               = AudioSystem.ROUTE_ALL;
1215
1216    /**
1217     * Sets the audio routing for a specified mode
1218     *
1219     * @param mode   audio mode to change route. E.g., MODE_RINGTONE.
1220     * @param routes bit vector of routes requested, created from one or
1221     *               more of ROUTE_xxx types. Set bits indicate that route should be on
1222     * @param mask   bit vector of routes to change, created from one or more of
1223     * ROUTE_xxx types. Unset bits indicate the route should be left unchanged
1224     *
1225     * @deprecated   Do not set audio routing directly, use setSpeakerphoneOn(),
1226     * setBluetoothScoOn() methods instead.
1227     */
1228    @Deprecated
1229    public void setRouting(int mode, int routes, int mask) {
1230    }
1231
1232    /**
1233     * Returns the current audio routing bit vector for a specified mode.
1234     *
1235     * @param mode audio mode to get route (e.g., MODE_RINGTONE)
1236     * @return an audio route bit vector that can be compared with ROUTE_xxx
1237     * bits
1238     * @deprecated   Do not query audio routing directly, use isSpeakerphoneOn(),
1239     * isBluetoothScoOn(), isBluetoothA2dpOn() and isWiredHeadsetOn() methods instead.
1240     */
1241    @Deprecated
1242    public int getRouting(int mode) {
1243        return -1;
1244    }
1245
1246    /**
1247     * Checks whether any music is active.
1248     *
1249     * @return true if any music tracks are active.
1250     */
1251    public boolean isMusicActive() {
1252        return AudioSystem.isStreamActive(STREAM_MUSIC, 0);
1253    }
1254
1255    /*
1256     * Sets a generic audio configuration parameter. The use of these parameters
1257     * are platform dependant, see libaudio
1258     *
1259     * ** Temporary interface - DO NOT USE
1260     *
1261     * TODO: Replace with a more generic key:value get/set mechanism
1262     *
1263     * param key   name of parameter to set. Must not be null.
1264     * param value value of parameter. Must not be null.
1265     */
1266    /**
1267     * @hide
1268     * @deprecated Use {@link #setPrameters(String)} instead
1269     */
1270    @Deprecated public void setParameter(String key, String value) {
1271        setParameters(key+"="+value);
1272    }
1273
1274    /**
1275     * Sets a variable number of parameter values to audio hardware.
1276     *
1277     * @param keyValuePairs list of parameters key value pairs in the form:
1278     *    key1=value1;key2=value2;...
1279     *
1280     */
1281    public void setParameters(String keyValuePairs) {
1282        AudioSystem.setParameters(keyValuePairs);
1283    }
1284
1285    /**
1286     * Sets a varaible number of parameter values to audio hardware.
1287     *
1288     * @param keys list of parameters
1289     * @return list of parameters key value pairs in the form:
1290     *    key1=value1;key2=value2;...
1291     */
1292    public String getParameters(String keys) {
1293        return AudioSystem.getParameters(keys);
1294    }
1295
1296    /* Sound effect identifiers */
1297    /**
1298     * Keyboard and direction pad click sound
1299     * @see #playSoundEffect(int)
1300     */
1301    public static final int FX_KEY_CLICK = 0;
1302    /**
1303     * Focus has moved up
1304     * @see #playSoundEffect(int)
1305     */
1306    public static final int FX_FOCUS_NAVIGATION_UP = 1;
1307    /**
1308     * Focus has moved down
1309     * @see #playSoundEffect(int)
1310     */
1311    public static final int FX_FOCUS_NAVIGATION_DOWN = 2;
1312    /**
1313     * Focus has moved left
1314     * @see #playSoundEffect(int)
1315     */
1316    public static final int FX_FOCUS_NAVIGATION_LEFT = 3;
1317    /**
1318     * Focus has moved right
1319     * @see #playSoundEffect(int)
1320     */
1321    public static final int FX_FOCUS_NAVIGATION_RIGHT = 4;
1322    /**
1323     * IME standard keypress sound
1324     * @see #playSoundEffect(int)
1325     */
1326    public static final int FX_KEYPRESS_STANDARD = 5;
1327    /**
1328     * IME spacebar keypress sound
1329     * @see #playSoundEffect(int)
1330     */
1331    public static final int FX_KEYPRESS_SPACEBAR = 6;
1332    /**
1333     * IME delete keypress sound
1334     * @see #playSoundEffect(int)
1335     */
1336    public static final int FX_KEYPRESS_DELETE = 7;
1337    /**
1338     * IME return_keypress sound
1339     * @see #playSoundEffect(int)
1340     */
1341    public static final int FX_KEYPRESS_RETURN = 8;
1342    /**
1343     * @hide Number of sound effects
1344     */
1345    public static final int NUM_SOUND_EFFECTS = 9;
1346
1347    /**
1348     * Plays a sound effect (Key clicks, lid open/close...)
1349     * @param effectType The type of sound effect. One of
1350     *            {@link #FX_KEY_CLICK},
1351     *            {@link #FX_FOCUS_NAVIGATION_UP},
1352     *            {@link #FX_FOCUS_NAVIGATION_DOWN},
1353     *            {@link #FX_FOCUS_NAVIGATION_LEFT},
1354     *            {@link #FX_FOCUS_NAVIGATION_RIGHT},
1355     *            {@link #FX_KEYPRESS_STANDARD},
1356     *            {@link #FX_KEYPRESS_SPACEBAR},
1357     *            {@link #FX_KEYPRESS_DELETE},
1358     *            {@link #FX_KEYPRESS_RETURN},
1359     * NOTE: This version uses the UI settings to determine
1360     * whether sounds are heard or not.
1361     */
1362    public void  playSoundEffect(int effectType) {
1363        if (effectType < 0 || effectType >= NUM_SOUND_EFFECTS) {
1364            return;
1365        }
1366
1367        if (!querySoundEffectsEnabled()) {
1368            return;
1369        }
1370
1371        IAudioService service = getService();
1372        try {
1373            service.playSoundEffect(effectType);
1374        } catch (RemoteException e) {
1375            Log.e(TAG, "Dead object in playSoundEffect"+e);
1376        }
1377    }
1378
1379    /**
1380     * Plays a sound effect (Key clicks, lid open/close...)
1381     * @param effectType The type of sound effect. One of
1382     *            {@link #FX_KEY_CLICK},
1383     *            {@link #FX_FOCUS_NAVIGATION_UP},
1384     *            {@link #FX_FOCUS_NAVIGATION_DOWN},
1385     *            {@link #FX_FOCUS_NAVIGATION_LEFT},
1386     *            {@link #FX_FOCUS_NAVIGATION_RIGHT},
1387     *            {@link #FX_KEYPRESS_STANDARD},
1388     *            {@link #FX_KEYPRESS_SPACEBAR},
1389     *            {@link #FX_KEYPRESS_DELETE},
1390     *            {@link #FX_KEYPRESS_RETURN},
1391     * @param volume Sound effect volume.
1392     * The volume value is a raw scalar so UI controls should be scaled logarithmically.
1393     * If a volume of -1 is specified, the AudioManager.STREAM_MUSIC stream volume minus 3dB will be used.
1394     * NOTE: This version is for applications that have their own
1395     * settings panel for enabling and controlling volume.
1396     */
1397    public void  playSoundEffect(int effectType, float volume) {
1398        if (effectType < 0 || effectType >= NUM_SOUND_EFFECTS) {
1399            return;
1400        }
1401
1402        IAudioService service = getService();
1403        try {
1404            service.playSoundEffectVolume(effectType, volume);
1405        } catch (RemoteException e) {
1406            Log.e(TAG, "Dead object in playSoundEffect"+e);
1407        }
1408    }
1409
1410    /**
1411     * Settings has an in memory cache, so this is fast.
1412     */
1413    private boolean querySoundEffectsEnabled() {
1414        return Settings.System.getInt(mContext.getContentResolver(), Settings.System.SOUND_EFFECTS_ENABLED, 0) != 0;
1415    }
1416
1417
1418    /**
1419     *  Load Sound effects.
1420     *  This method must be called when sound effects are enabled.
1421     */
1422    public void loadSoundEffects() {
1423        IAudioService service = getService();
1424        try {
1425            service.loadSoundEffects();
1426        } catch (RemoteException e) {
1427            Log.e(TAG, "Dead object in loadSoundEffects"+e);
1428        }
1429    }
1430
1431    /**
1432     *  Unload Sound effects.
1433     *  This method can be called to free some memory when
1434     *  sound effects are disabled.
1435     */
1436    public void unloadSoundEffects() {
1437        IAudioService service = getService();
1438        try {
1439            service.unloadSoundEffects();
1440        } catch (RemoteException e) {
1441            Log.e(TAG, "Dead object in unloadSoundEffects"+e);
1442        }
1443    }
1444
1445    /**
1446     * Used to indicate a gain of audio focus, or a request of audio focus, of unknown duration.
1447     * @see OnAudioFocusChangeListener#onAudioFocusChange(int)
1448     * @see #requestAudioFocus(OnAudioFocusChangeListener, int, int)
1449     */
1450    public static final int AUDIOFOCUS_GAIN = 1;
1451    /**
1452     * Used to indicate a temporary gain or request of audio focus, anticipated to last a short
1453     * amount of time. Examples of temporary changes are the playback of driving directions, or an
1454     * event notification.
1455     * @see OnAudioFocusChangeListener#onAudioFocusChange(int)
1456     * @see #requestAudioFocus(OnAudioFocusChangeListener, int, int)
1457     */
1458    public static final int AUDIOFOCUS_GAIN_TRANSIENT = 2;
1459    /**
1460     * Used to indicate a temporary request of audio focus, anticipated to last a short
1461     * amount of time, and where it is acceptable for other audio applications to keep playing
1462     * after having lowered their output level (also referred to as "ducking").
1463     * Examples of temporary changes are the playback of driving directions where playback of music
1464     * in the background is acceptable.
1465     * @see OnAudioFocusChangeListener#onAudioFocusChange(int)
1466     * @see #requestAudioFocus(OnAudioFocusChangeListener, int, int)
1467     */
1468    public static final int AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK = 3;
1469    /**
1470     * Used to indicate a loss of audio focus of unknown duration.
1471     * @see OnAudioFocusChangeListener#onAudioFocusChange(int)
1472     */
1473    public static final int AUDIOFOCUS_LOSS = -1 * AUDIOFOCUS_GAIN;
1474    /**
1475     * Used to indicate a transient loss of audio focus.
1476     * @see OnAudioFocusChangeListener#onAudioFocusChange(int)
1477     */
1478    public static final int AUDIOFOCUS_LOSS_TRANSIENT = -1 * AUDIOFOCUS_GAIN_TRANSIENT;
1479    /**
1480     * Used to indicate a transient loss of audio focus where the loser of the audio focus can
1481     * lower its output volume if it wants to continue playing (also referred to as "ducking"), as
1482     * the new focus owner doesn't require others to be silent.
1483     * @see OnAudioFocusChangeListener#onAudioFocusChange(int)
1484     */
1485    public static final int AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK =
1486            -1 * AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK;
1487
1488    /**
1489     * Interface definition for a callback to be invoked when the audio focus of the system is
1490     * updated.
1491     */
1492    public interface OnAudioFocusChangeListener {
1493        /**
1494         * Called on the listener to notify it the audio focus for this listener has been changed.
1495         * The focusChange value indicates whether the focus was gained,
1496         * whether the focus was lost, and whether that loss is transient, or whether the new focus
1497         * holder will hold it for an unknown amount of time.
1498         * When losing focus, listeners can use the focus change information to decide what
1499         * behavior to adopt when losing focus. A music player could for instance elect to lower
1500         * the volume of its music stream (duck) for transient focus losses, and pause otherwise.
1501         * @param focusChange the type of focus change, one of {@link AudioManager#AUDIOFOCUS_GAIN},
1502         *   {@link AudioManager#AUDIOFOCUS_LOSS}, {@link AudioManager#AUDIOFOCUS_LOSS_TRANSIENT}
1503         *   and {@link AudioManager#AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK}.
1504         */
1505        public void onAudioFocusChange(int focusChange);
1506    }
1507
1508    /**
1509     * Map to convert focus event listener IDs, as used in the AudioService audio focus stack,
1510     * to actual listener objects.
1511     */
1512    private HashMap<String, OnAudioFocusChangeListener> mAudioFocusIdListenerMap =
1513            new HashMap<String, OnAudioFocusChangeListener>();
1514    /**
1515     * Lock to prevent concurrent changes to the list of focus listeners for this AudioManager
1516     * instance.
1517     */
1518    private final Object mFocusListenerLock = new Object();
1519
1520    private OnAudioFocusChangeListener findFocusListener(String id) {
1521        return mAudioFocusIdListenerMap.get(id);
1522    }
1523
1524    /**
1525     * Handler for audio focus events coming from the audio service.
1526     */
1527    private FocusEventHandlerDelegate mAudioFocusEventHandlerDelegate =
1528            new FocusEventHandlerDelegate();
1529
1530    /**
1531     * Helper class to handle the forwarding of audio focus events to the appropriate listener
1532     */
1533    private class FocusEventHandlerDelegate {
1534        private final Handler mHandler;
1535
1536        FocusEventHandlerDelegate() {
1537            Looper looper;
1538            if ((looper = Looper.myLooper()) == null) {
1539                looper = Looper.getMainLooper();
1540            }
1541
1542            if (looper != null) {
1543                // implement the event handler delegate to receive audio focus events
1544                mHandler = new Handler(looper) {
1545                    @Override
1546                    public void handleMessage(Message msg) {
1547                        OnAudioFocusChangeListener listener = null;
1548                        synchronized(mFocusListenerLock) {
1549                            listener = findFocusListener((String)msg.obj);
1550                        }
1551                        if (listener != null) {
1552                            listener.onAudioFocusChange(msg.what);
1553                        }
1554                    }
1555                };
1556            } else {
1557                mHandler = null;
1558            }
1559        }
1560
1561        Handler getHandler() {
1562            return mHandler;
1563        }
1564    }
1565
1566    private IAudioFocusDispatcher mAudioFocusDispatcher = new IAudioFocusDispatcher.Stub() {
1567
1568        public void dispatchAudioFocusChange(int focusChange, String id) {
1569            Message m = mAudioFocusEventHandlerDelegate.getHandler().obtainMessage(focusChange, id);
1570            mAudioFocusEventHandlerDelegate.getHandler().sendMessage(m);
1571        }
1572
1573    };
1574
1575    private String getIdForAudioFocusListener(OnAudioFocusChangeListener l) {
1576        if (l == null) {
1577            return new String(this.toString());
1578        } else {
1579            return new String(this.toString() + l.toString());
1580        }
1581    }
1582
1583    /**
1584     * @hide
1585     * Registers a listener to be called when audio focus changes. Calling this method is optional
1586     * before calling {@link #requestAudioFocus(OnAudioFocusChangeListener, int, int)}, as it
1587     * will register the listener as well if it wasn't registered already.
1588     * @param l the listener to be notified of audio focus changes.
1589     */
1590    public void registerAudioFocusListener(OnAudioFocusChangeListener l) {
1591        synchronized(mFocusListenerLock) {
1592            if (mAudioFocusIdListenerMap.containsKey(getIdForAudioFocusListener(l))) {
1593                return;
1594            }
1595            mAudioFocusIdListenerMap.put(getIdForAudioFocusListener(l), l);
1596        }
1597    }
1598
1599    /**
1600     * @hide
1601     * Causes the specified listener to not be called anymore when focus is gained or lost.
1602     * @param l the listener to unregister.
1603     */
1604    public void unregisterAudioFocusListener(OnAudioFocusChangeListener l) {
1605
1606        // remove locally
1607        synchronized(mFocusListenerLock) {
1608            mAudioFocusIdListenerMap.remove(getIdForAudioFocusListener(l));
1609        }
1610    }
1611
1612
1613    /**
1614     * A failed focus change request.
1615     */
1616    public static final int AUDIOFOCUS_REQUEST_FAILED = 0;
1617    /**
1618     * A successful focus change request.
1619     */
1620    public static final int AUDIOFOCUS_REQUEST_GRANTED = 1;
1621
1622
1623    /**
1624     *  Request audio focus.
1625     *  Send a request to obtain the audio focus
1626     *  @param l the listener to be notified of audio focus changes
1627     *  @param streamType the main audio stream type affected by the focus request
1628     *  @param durationHint use {@link #AUDIOFOCUS_GAIN_TRANSIENT} to indicate this focus request
1629     *      is temporary, and focus will be abandonned shortly. Examples of transient requests are
1630     *      for the playback of driving directions, or notifications sounds.
1631     *      Use {@link #AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK} to indicate also that it's ok for
1632     *      the previous focus owner to keep playing if it ducks its audio output.
1633     *      Use {@link #AUDIOFOCUS_GAIN} for a focus request of unknown duration such
1634     *      as the playback of a song or a video.
1635     *  @return {@link #AUDIOFOCUS_REQUEST_FAILED} or {@link #AUDIOFOCUS_REQUEST_GRANTED}
1636     */
1637    public int requestAudioFocus(OnAudioFocusChangeListener l, int streamType, int durationHint) {
1638        int status = AUDIOFOCUS_REQUEST_FAILED;
1639        if ((durationHint < AUDIOFOCUS_GAIN) || (durationHint > AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK))
1640        {
1641            Log.e(TAG, "Invalid duration hint, audio focus request denied");
1642            return status;
1643        }
1644        registerAudioFocusListener(l);
1645        //TODO protect request by permission check?
1646        IAudioService service = getService();
1647        try {
1648            status = service.requestAudioFocus(streamType, durationHint, mICallBack,
1649                    mAudioFocusDispatcher, getIdForAudioFocusListener(l));
1650        } catch (RemoteException e) {
1651            Log.e(TAG, "Can't call requestAudioFocus() from AudioService due to "+e);
1652        }
1653        return status;
1654    }
1655
1656
1657    /**
1658     *  Abandon audio focus. Causes the previous focus owner, if any, to receive focus.
1659     *  @param l the listener with which focus was requested.
1660     *  @return {@link #AUDIOFOCUS_REQUEST_FAILED} or {@link #AUDIOFOCUS_REQUEST_GRANTED}
1661     */
1662    public int abandonAudioFocus(OnAudioFocusChangeListener l) {
1663        int status = AUDIOFOCUS_REQUEST_FAILED;
1664        unregisterAudioFocusListener(l);
1665        IAudioService service = getService();
1666        try {
1667            status = service.abandonAudioFocus(mAudioFocusDispatcher,
1668                    getIdForAudioFocusListener(l));
1669        } catch (RemoteException e) {
1670            Log.e(TAG, "Can't call abandonAudioFocus() from AudioService due to "+e);
1671        }
1672        return status;
1673    }
1674
1675
1676    //====================================================================
1677    // Remote Control
1678    /**
1679     * Register a component to be the sole receiver of MEDIA_BUTTON intents.
1680     * @param eventReceiver identifier of a {@link android.content.BroadcastReceiver}
1681     *      that will receive the media button intent. This broadcast receiver must be declared
1682     *      in the application manifest.
1683     */
1684    public void registerMediaButtonEventReceiver(ComponentName eventReceiver) {
1685        //TODO enforce the rule about the receiver being declared in the manifest
1686        IAudioService service = getService();
1687        try {
1688            service.registerMediaButtonEventReceiver(eventReceiver);
1689        } catch (RemoteException e) {
1690            Log.e(TAG, "Dead object in registerMediaButtonEventReceiver"+e);
1691        }
1692    }
1693
1694    /**
1695     * Unregister the receiver of MEDIA_BUTTON intents.
1696     * @param eventReceiver identifier of a {@link android.content.BroadcastReceiver}
1697     *      that was registered with {@link #registerMediaButtonEventReceiver(ComponentName)}.
1698     */
1699    public void unregisterMediaButtonEventReceiver(ComponentName eventReceiver) {
1700        IAudioService service = getService();
1701        try {
1702            service.unregisterMediaButtonEventReceiver(eventReceiver);
1703        } catch (RemoteException e) {
1704            Log.e(TAG, "Dead object in unregisterMediaButtonEventReceiver"+e);
1705        }
1706    }
1707
1708    /**
1709     *  @hide
1710     *  Reload audio settings. This method is called by Settings backup
1711     *  agent when audio settings are restored and causes the AudioService
1712     *  to read and apply restored settings.
1713     */
1714    public void reloadAudioSettings() {
1715        IAudioService service = getService();
1716        try {
1717            service.reloadAudioSettings();
1718        } catch (RemoteException e) {
1719            Log.e(TAG, "Dead object in reloadAudioSettings"+e);
1720        }
1721    }
1722
1723     /**
1724      * {@hide}
1725      */
1726     private IBinder mICallBack = new Binder();
1727
1728    /**
1729     * Checks whether the phone is in silent mode, with or without vibrate.
1730     *
1731     * @return true if phone is in silent mode, with or without vibrate.
1732     *
1733     * @see #getRingerMode()
1734     *
1735     * @hide pending API Council approval
1736     */
1737    public boolean isSilentMode() {
1738        int ringerMode = getRingerMode();
1739        boolean silentMode =
1740            (ringerMode == RINGER_MODE_SILENT) ||
1741            (ringerMode == RINGER_MODE_VIBRATE);
1742        return silentMode;
1743    }
1744
1745    // This section re-defines new output device constants from AudioSystem, because the AudioSystem
1746    // class is not used by other parts of the framework, which instead use definitions and methods
1747    // from AudioManager. AudioSystem is an internal class used by AudioManager and AudioService.
1748
1749    /** {@hide} The audio output device code for the small speaker at the front of the device used
1750     *  when placing calls.  Does not refer to an in-ear headphone without attached microphone,
1751     *  such as earbuds, earphones, or in-ear monitors (IEM). Those would be handled as a
1752     *  {@link #DEVICE_OUT_WIRED_HEADPHONE}.
1753     */
1754    public static final int DEVICE_OUT_EARPIECE = AudioSystem.DEVICE_OUT_EARPIECE;
1755    /** {@hide} The audio output device code for the built-in speaker */
1756    public static final int DEVICE_OUT_SPEAKER = AudioSystem.DEVICE_OUT_SPEAKER;
1757    /** {@hide} The audio output device code for a wired headset with attached microphone */
1758    public static final int DEVICE_OUT_WIRED_HEADSET = AudioSystem.DEVICE_OUT_WIRED_HEADSET;
1759    /** {@hide} The audio output device code for a wired headphone without attached microphone */
1760    public static final int DEVICE_OUT_WIRED_HEADPHONE = AudioSystem.DEVICE_OUT_WIRED_HEADPHONE;
1761    /** {@hide} The audio output device code for generic Bluetooth SCO, for voice */
1762    public static final int DEVICE_OUT_BLUETOOTH_SCO = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO;
1763    /** {@hide} The audio output device code for Bluetooth SCO Headset Profile (HSP) and
1764     *  Hands-Free Profile (HFP), for voice
1765     */
1766    public static final int DEVICE_OUT_BLUETOOTH_SCO_HEADSET =
1767            AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
1768    /** {@hide} The audio output device code for Bluetooth SCO car audio, for voice */
1769    public static final int DEVICE_OUT_BLUETOOTH_SCO_CARKIT =
1770            AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
1771    /** {@hide} The audio output device code for generic Bluetooth A2DP, for music */
1772    public static final int DEVICE_OUT_BLUETOOTH_A2DP = AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP;
1773    /** {@hide} The audio output device code for Bluetooth A2DP headphones, for music */
1774    public static final int DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES =
1775            AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
1776    /** {@hide} The audio output device code for Bluetooth A2DP external speaker, for music */
1777    public static final int DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER =
1778            AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
1779    /** {@hide} The audio output device code for S/PDIF or HDMI */
1780    public static final int DEVICE_OUT_AUX_DIGITAL = AudioSystem.DEVICE_OUT_AUX_DIGITAL;
1781    /** {@hide} The audio output device code for an analog wired headset attached via a
1782     *  docking station
1783     */
1784    public static final int DEVICE_OUT_ANLG_DOCK_HEADSET = AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET;
1785    /** {@hide} The audio output device code for a digital wired headset attached via a
1786     *  docking station
1787     */
1788    public static final int DEVICE_OUT_DGTL_DOCK_HEADSET = AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET;
1789    /** {@hide} This is not used as a returned value from {@link #getDevicesForStream}, but could be
1790     *  used in the future in a set method to select whatever default device is chosen by the
1791     *  platform-specific implementation.
1792     */
1793    public static final int DEVICE_OUT_DEFAULT = AudioSystem.DEVICE_OUT_DEFAULT;
1794
1795    /**
1796     * Return the enabled devices for the specified output stream type.
1797     *
1798     * @param streamType The stream type to query. One of
1799     *            {@link #STREAM_VOICE_CALL},
1800     *            {@link #STREAM_SYSTEM},
1801     *            {@link #STREAM_RING},
1802     *            {@link #STREAM_MUSIC},
1803     *            {@link #STREAM_ALARM},
1804     *            {@link #STREAM_NOTIFICATION},
1805     *            {@link #STREAM_DTMF}.
1806     *
1807     * @return The bit-mask "or" of audio output device codes for all enabled devices on this
1808     *         stream. Zero or more of
1809     *            {@link #DEVICE_OUT_EARPIECE},
1810     *            {@link #DEVICE_OUT_SPEAKER},
1811     *            {@link #DEVICE_OUT_WIRED_HEADSET},
1812     *            {@link #DEVICE_OUT_WIRED_HEADPHONE},
1813     *            {@link #DEVICE_OUT_BLUETOOTH_SCO},
1814     *            {@link #DEVICE_OUT_BLUETOOTH_SCO_HEADSET},
1815     *            {@link #DEVICE_OUT_BLUETOOTH_SCO_CARKIT},
1816     *            {@link #DEVICE_OUT_BLUETOOTH_A2DP},
1817     *            {@link #DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES},
1818     *            {@link #DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER},
1819     *            {@link #DEVICE_OUT_AUX_DIGITAL},
1820     *            {@link #DEVICE_OUT_ANLG_DOCK_HEADSET},
1821     *            {@link #DEVICE_OUT_DGTL_DOCK_HEADSET}.
1822     *            {@link #DEVICE_OUT_DEFAULT} is not used here.
1823     *
1824     * The implementation may support additional device codes beyond those listed, so
1825     * the application should ignore any bits which it does not recognize.
1826     * Note that the information may be imprecise when the implementation
1827     * cannot distinguish whether a particular device is enabled.
1828     *
1829     * {@hide}
1830     */
1831    public int getDevicesForStream(int streamType) {
1832        switch (streamType) {
1833        case STREAM_VOICE_CALL:
1834        case STREAM_SYSTEM:
1835        case STREAM_RING:
1836        case STREAM_MUSIC:
1837        case STREAM_ALARM:
1838        case STREAM_NOTIFICATION:
1839        case STREAM_DTMF:
1840            return AudioSystem.getDevicesForStream(streamType);
1841        default:
1842            return 0;
1843        }
1844    }
1845
1846}
1847