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