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