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