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