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