• 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.Manifest;
20 import android.annotation.SdkConstant;
21 import android.annotation.SdkConstant.SdkConstantType;
22 import android.annotation.SystemApi;
23 import android.app.PendingIntent;
24 import android.bluetooth.BluetoothDevice;
25 import android.content.ComponentName;
26 import android.content.Context;
27 import android.content.Intent;
28 import android.media.RemoteController.OnClientUpdateListener;
29 import android.media.audiopolicy.AudioPolicy;
30 import android.media.audiopolicy.AudioPolicyConfig;
31 import android.media.session.MediaController;
32 import android.media.session.MediaSession;
33 import android.media.session.MediaSessionLegacyHelper;
34 import android.media.session.MediaSessionManager;
35 import android.os.Binder;
36 import android.os.Handler;
37 import android.os.IBinder;
38 import android.os.Looper;
39 import android.os.Message;
40 import android.os.Process;
41 import android.os.RemoteException;
42 import android.os.SystemClock;
43 import android.os.ServiceManager;
44 import android.provider.Settings;
45 import android.util.Log;
46 import android.view.KeyEvent;
47 
48 import java.util.HashMap;
49 import java.util.ArrayList;
50 
51 
52 /**
53  * AudioManager provides access to volume and ringer mode control.
54  * <p>
55  * Use <code>Context.getSystemService(Context.AUDIO_SERVICE)</code> to get
56  * an instance of this class.
57  */
58 public class AudioManager {
59 
60     private final Context mContext;
61     private long mVolumeKeyUpTime;
62     private final boolean mUseMasterVolume;
63     private final boolean mUseVolumeKeySounds;
64     private final boolean mUseFixedVolume;
65     private final Binder mToken = new Binder();
66     private static String TAG = "AudioManager";
67     AudioPortEventHandler mAudioPortEventHandler;
68 
69     /**
70      * Broadcast intent, a hint for applications that audio is about to become
71      * 'noisy' due to a change in audio outputs. For example, this intent may
72      * be sent when a wired headset is unplugged, or when an A2DP audio
73      * sink is disconnected, and the audio system is about to automatically
74      * switch audio route to the speaker. Applications that are controlling
75      * audio streams may consider pausing, reducing volume or some other action
76      * on receipt of this intent so as not to surprise the user with audio
77      * from the speaker.
78      */
79     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
80     public static final String ACTION_AUDIO_BECOMING_NOISY = "android.media.AUDIO_BECOMING_NOISY";
81 
82     /**
83      * Sticky broadcast intent action indicating that the ringer mode has
84      * changed. Includes the new ringer mode.
85      *
86      * @see #EXTRA_RINGER_MODE
87      */
88     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
89     public static final String RINGER_MODE_CHANGED_ACTION = "android.media.RINGER_MODE_CHANGED";
90 
91     /**
92      * The new ringer mode.
93      *
94      * @see #RINGER_MODE_CHANGED_ACTION
95      * @see #RINGER_MODE_NORMAL
96      * @see #RINGER_MODE_SILENT
97      * @see #RINGER_MODE_VIBRATE
98      */
99     public static final String EXTRA_RINGER_MODE = "android.media.EXTRA_RINGER_MODE";
100 
101     /**
102      * Broadcast intent action indicating that the vibrate setting has
103      * changed. Includes the vibrate type and its new setting.
104      *
105      * @see #EXTRA_VIBRATE_TYPE
106      * @see #EXTRA_VIBRATE_SETTING
107      * @deprecated Applications should maintain their own vibrate policy based on
108      * current ringer mode and listen to {@link #RINGER_MODE_CHANGED_ACTION} instead.
109      */
110     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
111     public static final String VIBRATE_SETTING_CHANGED_ACTION =
112         "android.media.VIBRATE_SETTING_CHANGED";
113 
114     /**
115      * @hide Broadcast intent when the volume for a particular stream type changes.
116      * Includes the stream, the new volume and previous volumes.
117      * Notes:
118      *  - for internal platform use only, do not make public,
119      *  - never used for "remote" volume changes
120      *
121      * @see #EXTRA_VOLUME_STREAM_TYPE
122      * @see #EXTRA_VOLUME_STREAM_VALUE
123      * @see #EXTRA_PREV_VOLUME_STREAM_VALUE
124      */
125     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
126     public static final String VOLUME_CHANGED_ACTION = "android.media.VOLUME_CHANGED_ACTION";
127 
128     /**
129      * @hide Broadcast intent when the master volume changes.
130      * Includes the new volume
131      *
132      * @see #EXTRA_MASTER_VOLUME_VALUE
133      * @see #EXTRA_PREV_MASTER_VOLUME_VALUE
134      */
135     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
136     public static final String MASTER_VOLUME_CHANGED_ACTION =
137         "android.media.MASTER_VOLUME_CHANGED_ACTION";
138 
139     /**
140      * @hide Broadcast intent when the master mute state changes.
141      * Includes the the new volume
142      *
143      * @see #EXTRA_MASTER_VOLUME_MUTED
144      */
145     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
146     public static final String MASTER_MUTE_CHANGED_ACTION =
147         "android.media.MASTER_MUTE_CHANGED_ACTION";
148 
149     /**
150      * The new vibrate setting for a particular type.
151      *
152      * @see #VIBRATE_SETTING_CHANGED_ACTION
153      * @see #EXTRA_VIBRATE_TYPE
154      * @see #VIBRATE_SETTING_ON
155      * @see #VIBRATE_SETTING_OFF
156      * @see #VIBRATE_SETTING_ONLY_SILENT
157      * @deprecated Applications should maintain their own vibrate policy based on
158      * current ringer mode and listen to {@link #RINGER_MODE_CHANGED_ACTION} instead.
159      */
160     public static final String EXTRA_VIBRATE_SETTING = "android.media.EXTRA_VIBRATE_SETTING";
161 
162     /**
163      * The vibrate type whose setting has changed.
164      *
165      * @see #VIBRATE_SETTING_CHANGED_ACTION
166      * @see #VIBRATE_TYPE_NOTIFICATION
167      * @see #VIBRATE_TYPE_RINGER
168      * @deprecated Applications should maintain their own vibrate policy based on
169      * current ringer mode and listen to {@link #RINGER_MODE_CHANGED_ACTION} instead.
170      */
171     public static final String EXTRA_VIBRATE_TYPE = "android.media.EXTRA_VIBRATE_TYPE";
172 
173     /**
174      * @hide The stream type for the volume changed intent.
175      */
176     public static final String EXTRA_VOLUME_STREAM_TYPE = "android.media.EXTRA_VOLUME_STREAM_TYPE";
177 
178     /**
179      * @hide The volume associated with the stream for the volume changed intent.
180      */
181     public static final String EXTRA_VOLUME_STREAM_VALUE =
182         "android.media.EXTRA_VOLUME_STREAM_VALUE";
183 
184     /**
185      * @hide The previous volume associated with the stream for the volume changed intent.
186      */
187     public static final String EXTRA_PREV_VOLUME_STREAM_VALUE =
188         "android.media.EXTRA_PREV_VOLUME_STREAM_VALUE";
189 
190     /**
191      * @hide The new master volume value for the master volume changed intent.
192      * Value is integer between 0 and 100 inclusive.
193      */
194     public static final String EXTRA_MASTER_VOLUME_VALUE =
195         "android.media.EXTRA_MASTER_VOLUME_VALUE";
196 
197     /**
198      * @hide The previous master volume value for the master volume changed intent.
199      * Value is integer between 0 and 100 inclusive.
200      */
201     public static final String EXTRA_PREV_MASTER_VOLUME_VALUE =
202         "android.media.EXTRA_PREV_MASTER_VOLUME_VALUE";
203 
204     /**
205      * @hide The new master volume mute state for the master mute changed intent.
206      * Value is boolean
207      */
208     public static final String EXTRA_MASTER_VOLUME_MUTED =
209         "android.media.EXTRA_MASTER_VOLUME_MUTED";
210 
211     /**
212      * Broadcast Action: Wired Headset plugged in or unplugged.
213      *
214      * You <em>cannot</em> receive this through components declared
215      * in manifests, only by explicitly registering for it with
216      * {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)
217      * Context.registerReceiver()}.
218      *
219      * <p>The intent will have the following extra values:
220      * <ul>
221      *   <li><em>state</em> - 0 for unplugged, 1 for plugged. </li>
222      *   <li><em>name</em> - Headset type, human readable string </li>
223      *   <li><em>microphone</em> - 1 if headset has a microphone, 0 otherwise </li>
224      * </ul>
225      * </ul>
226      */
227     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
228     public static final String ACTION_HEADSET_PLUG =
229             "android.intent.action.HEADSET_PLUG";
230 
231     /**
232      * Broadcast Action: A sticky broadcast indicating an HMDI cable was plugged or unplugged
233      *
234      * The intent will have the following extra values: {@link #EXTRA_AUDIO_PLUG_STATE},
235      * {@link #EXTRA_MAX_CHANNEL_COUNT}, {@link #EXTRA_ENCODINGS}.
236      * <p>It can only be received by explicitly registering for it with
237      * {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)}.
238      */
239     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
240     public static final String ACTION_HDMI_AUDIO_PLUG =
241             "android.media.action.HDMI_AUDIO_PLUG";
242 
243     /**
244      * Extra used in {@link #ACTION_HDMI_AUDIO_PLUG} to communicate whether HDMI is plugged in
245      * or unplugged.
246      * An integer value of 1 indicates a plugged-in state, 0 is unplugged.
247      */
248     public static final String EXTRA_AUDIO_PLUG_STATE = "android.media.extra.AUDIO_PLUG_STATE";
249 
250     /**
251      * Extra used in {@link #ACTION_HDMI_AUDIO_PLUG} to define the maximum number of channels
252      * supported by the HDMI device.
253      * The corresponding integer value is only available when the device is plugged in (as expressed
254      * by {@link #EXTRA_AUDIO_PLUG_STATE}).
255      */
256     public static final String EXTRA_MAX_CHANNEL_COUNT = "android.media.extra.MAX_CHANNEL_COUNT";
257 
258     /**
259      * Extra used in {@link #ACTION_HDMI_AUDIO_PLUG} to define the audio encodings supported by
260      * the connected HDMI device.
261      * The corresponding array of encoding values is only available when the device is plugged in
262      * (as expressed by {@link #EXTRA_AUDIO_PLUG_STATE}). Encoding values are defined in
263      * {@link AudioFormat} (for instance see {@link AudioFormat#ENCODING_PCM_16BIT}). Use
264      * {@link android.content.Intent#getIntArrayExtra(String)} to retrieve the encoding values.
265      */
266     public static final String EXTRA_ENCODINGS = "android.media.extra.ENCODINGS";
267 
268     /**
269      * Broadcast Action: An analog audio speaker/headset plugged in or unplugged.
270      *
271      * <p>The intent will have the following extra values:
272      * <ul>
273      *   <li><em>state</em> - 0 for unplugged, 1 for plugged. </li>
274      *   <li><em>name</em> - Headset type, human readable string </li>
275      * </ul>
276      * </ul>
277      * @hide
278      */
279     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
280     public static final String ACTION_ANALOG_AUDIO_DOCK_PLUG =
281             "android.media.action.ANALOG_AUDIO_DOCK_PLUG";
282 
283     /**
284      * Broadcast Action: A digital audio speaker/headset plugged in or unplugged.
285      *
286      * <p>The intent will have the following extra values:
287      * <ul>
288      *   <li><em>state</em> - 0 for unplugged, 1 for plugged. </li>
289      *   <li><em>name</em> - Headset type, human readable string </li>
290      * </ul>
291      * </ul>
292      * @hide
293      */
294     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
295     public static final String ACTION_DIGITAL_AUDIO_DOCK_PLUG =
296             "android.media.action.DIGITAL_AUDIO_DOCK_PLUG";
297 
298     /**
299      * Broadcast Action: A USB audio accessory was plugged in or unplugged.
300      *
301      * <p>The intent will have the following extra values:
302      * <ul>
303      *   <li><em>state</em> - 0 for unplugged, 1 for plugged. </li>
304      *   <li><em>card</em> - ALSA card number (integer) </li>
305      *   <li><em>device</em> - ALSA device number (integer) </li>
306      * </ul>
307      * </ul>
308      * @hide
309      */
310     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
311     public static final String ACTION_USB_AUDIO_ACCESSORY_PLUG =
312             "android.media.action.USB_AUDIO_ACCESSORY_PLUG";
313 
314     /**
315      * Broadcast Action: A USB audio device was plugged in or unplugged.
316      *
317      * <p>The intent will have the following extra values:
318      * <ul>
319      *   <li><em>state</em> - 0 for unplugged, 1 for plugged. </li>
320      *   <li><em>card</em> - ALSA card number (integer) </li>
321      *   <li><em>device</em> - ALSA device number (integer) </li>
322      * </ul>
323      * </ul>
324      * @hide
325      */
326     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
327     public static final String ACTION_USB_AUDIO_DEVICE_PLUG =
328             "android.media.action.USB_AUDIO_DEVICE_PLUG";
329 
330     /** The audio stream for phone calls */
331     public static final int STREAM_VOICE_CALL = AudioSystem.STREAM_VOICE_CALL;
332     /** The audio stream for system sounds */
333     public static final int STREAM_SYSTEM = AudioSystem.STREAM_SYSTEM;
334     /** The audio stream for the phone ring */
335     public static final int STREAM_RING = AudioSystem.STREAM_RING;
336     /** The audio stream for music playback */
337     public static final int STREAM_MUSIC = AudioSystem.STREAM_MUSIC;
338     /** The audio stream for alarms */
339     public static final int STREAM_ALARM = AudioSystem.STREAM_ALARM;
340     /** The audio stream for notifications */
341     public static final int STREAM_NOTIFICATION = AudioSystem.STREAM_NOTIFICATION;
342     /** @hide The audio stream for phone calls when connected to bluetooth */
343     public static final int STREAM_BLUETOOTH_SCO = AudioSystem.STREAM_BLUETOOTH_SCO;
344     /** @hide The audio stream for enforced system sounds in certain countries (e.g camera in Japan) */
345     public static final int STREAM_SYSTEM_ENFORCED = AudioSystem.STREAM_SYSTEM_ENFORCED;
346     /** The audio stream for DTMF Tones */
347     public static final int STREAM_DTMF = AudioSystem.STREAM_DTMF;
348     /** @hide The audio stream for text to speech (TTS) */
349     public static final int STREAM_TTS = AudioSystem.STREAM_TTS;
350     /** Number of audio streams */
351     /**
352      * @deprecated Use AudioSystem.getNumStreamTypes() instead
353      */
354     @Deprecated public static final int NUM_STREAMS = AudioSystem.NUM_STREAMS;
355 
356 
357     /**  @hide Default volume index values for audio streams */
358     public static final int[] DEFAULT_STREAM_VOLUME = new int[] {
359         4,  // STREAM_VOICE_CALL
360         7,  // STREAM_SYSTEM
361         5,  // STREAM_RING
362         11, // STREAM_MUSIC
363         6,  // STREAM_ALARM
364         5,  // STREAM_NOTIFICATION
365         7,  // STREAM_BLUETOOTH_SCO
366         7,  // STREAM_SYSTEM_ENFORCED
367         11, // STREAM_DTMF
368         11  // STREAM_TTS
369     };
370 
371     /**
372      * Increase the ringer volume.
373      *
374      * @see #adjustVolume(int, int)
375      * @see #adjustStreamVolume(int, int, int)
376      */
377     public static final int ADJUST_RAISE = 1;
378 
379     /**
380      * Decrease the ringer volume.
381      *
382      * @see #adjustVolume(int, int)
383      * @see #adjustStreamVolume(int, int, int)
384      */
385     public static final int ADJUST_LOWER = -1;
386 
387     /**
388      * Maintain the previous ringer volume. This may be useful when needing to
389      * show the volume toast without actually modifying the volume.
390      *
391      * @see #adjustVolume(int, int)
392      * @see #adjustStreamVolume(int, int, int)
393      */
394     public static final int ADJUST_SAME = 0;
395 
396     // Flags should be powers of 2!
397 
398     /**
399      * Show a toast containing the current volume.
400      *
401      * @see #adjustStreamVolume(int, int, int)
402      * @see #adjustVolume(int, int)
403      * @see #setStreamVolume(int, int, int)
404      * @see #setRingerMode(int)
405      */
406     public static final int FLAG_SHOW_UI = 1 << 0;
407 
408     /**
409      * Whether to include ringer modes as possible options when changing volume.
410      * For example, if true and volume level is 0 and the volume is adjusted
411      * with {@link #ADJUST_LOWER}, then the ringer mode may switch the silent or
412      * vibrate mode.
413      * <p>
414      * By default this is on for the ring stream. If this flag is included,
415      * this behavior will be present regardless of the stream type being
416      * affected by the ringer mode.
417      *
418      * @see #adjustVolume(int, int)
419      * @see #adjustStreamVolume(int, int, int)
420      */
421     public static final int FLAG_ALLOW_RINGER_MODES = 1 << 1;
422 
423     /**
424      * Whether to play a sound when changing the volume.
425      * <p>
426      * If this is given to {@link #adjustVolume(int, int)} or
427      * {@link #adjustSuggestedStreamVolume(int, int, int)}, it may be ignored
428      * in some cases (for example, the decided stream type is not
429      * {@link AudioManager#STREAM_RING}, or the volume is being adjusted
430      * downward).
431      *
432      * @see #adjustStreamVolume(int, int, int)
433      * @see #adjustVolume(int, int)
434      * @see #setStreamVolume(int, int, int)
435      */
436     public static final int FLAG_PLAY_SOUND = 1 << 2;
437 
438     /**
439      * Removes any sounds/vibrate that may be in the queue, or are playing (related to
440      * changing volume).
441      */
442     public static final int FLAG_REMOVE_SOUND_AND_VIBRATE = 1 << 3;
443 
444     /**
445      * Whether to vibrate if going into the vibrate ringer mode.
446      */
447     public static final int FLAG_VIBRATE = 1 << 4;
448 
449     /**
450      * Indicates to VolumePanel that the volume slider should be disabled as user
451      * cannot change the stream volume
452      * @hide
453      */
454     public static final int FLAG_FIXED_VOLUME = 1 << 5;
455 
456     /**
457      * Indicates the volume set/adjust call is for Bluetooth absolute volume
458      * @hide
459      */
460     public static final int FLAG_BLUETOOTH_ABS_VOLUME = 1 << 6;
461 
462     /**
463      * Adjusting the volume was prevented due to silent mode, display a hint in the UI.
464      * @hide
465      */
466     public static final int FLAG_SHOW_SILENT_HINT = 1 << 7;
467 
468     /**
469      * Indicates the volume call is for Hdmi Cec system audio volume
470      * @hide
471      */
472     public static final int FLAG_HDMI_SYSTEM_AUDIO_VOLUME = 1 << 8;
473 
474     /**
475      * Indicates that this should only be handled if media is actively playing.
476      * @hide
477      */
478     public static final int FLAG_ACTIVE_MEDIA_ONLY = 1 << 9;
479 
480     /**
481      * Like FLAG_SHOW_UI, but only dialog warnings and confirmations, no sliders.
482      * @hide
483      */
484     public static final int FLAG_SHOW_UI_WARNINGS = 1 << 10;
485 
486     /**
487      * Ringer mode that will be silent and will not vibrate. (This overrides the
488      * vibrate setting.)
489      *
490      * @see #setRingerMode(int)
491      * @see #getRingerMode()
492      */
493     public static final int RINGER_MODE_SILENT = 0;
494 
495     /**
496      * Ringer mode that will be silent and will vibrate. (This will cause the
497      * phone ringer to always vibrate, but the notification vibrate to only
498      * vibrate if set.)
499      *
500      * @see #setRingerMode(int)
501      * @see #getRingerMode()
502      */
503     public static final int RINGER_MODE_VIBRATE = 1;
504 
505     /**
506      * Ringer mode that may be audible and may vibrate. It will be audible if
507      * the volume before changing out of this mode was audible. It will vibrate
508      * if the vibrate setting is on.
509      *
510      * @see #setRingerMode(int)
511      * @see #getRingerMode()
512      */
513     public static final int RINGER_MODE_NORMAL = 2;
514 
515     // maximum valid ringer mode value. Values must start from 0 and be contiguous.
516     private static final int RINGER_MODE_MAX = RINGER_MODE_NORMAL;
517 
518     /**
519      * Vibrate type that corresponds to the ringer.
520      *
521      * @see #setVibrateSetting(int, int)
522      * @see #getVibrateSetting(int)
523      * @see #shouldVibrate(int)
524      * @deprecated Applications should maintain their own vibrate policy based on
525      * current ringer mode that can be queried via {@link #getRingerMode()}.
526      */
527     public static final int VIBRATE_TYPE_RINGER = 0;
528 
529     /**
530      * Vibrate type that corresponds to notifications.
531      *
532      * @see #setVibrateSetting(int, int)
533      * @see #getVibrateSetting(int)
534      * @see #shouldVibrate(int)
535      * @deprecated Applications should maintain their own vibrate policy based on
536      * current ringer mode that can be queried via {@link #getRingerMode()}.
537      */
538     public static final int VIBRATE_TYPE_NOTIFICATION = 1;
539 
540     /**
541      * Vibrate setting that suggests to never vibrate.
542      *
543      * @see #setVibrateSetting(int, int)
544      * @see #getVibrateSetting(int)
545      * @deprecated Applications should maintain their own vibrate policy based on
546      * current ringer mode that can be queried via {@link #getRingerMode()}.
547      */
548     public static final int VIBRATE_SETTING_OFF = 0;
549 
550     /**
551      * Vibrate setting that suggests to vibrate when possible.
552      *
553      * @see #setVibrateSetting(int, int)
554      * @see #getVibrateSetting(int)
555      * @deprecated Applications should maintain their own vibrate policy based on
556      * current ringer mode that can be queried via {@link #getRingerMode()}.
557      */
558     public static final int VIBRATE_SETTING_ON = 1;
559 
560     /**
561      * Vibrate setting that suggests to only vibrate when in the vibrate ringer
562      * mode.
563      *
564      * @see #setVibrateSetting(int, int)
565      * @see #getVibrateSetting(int)
566      * @deprecated Applications should maintain their own vibrate policy based on
567      * current ringer mode that can be queried via {@link #getRingerMode()}.
568      */
569     public static final int VIBRATE_SETTING_ONLY_SILENT = 2;
570 
571     /**
572      * Suggests using the default stream type. This may not be used in all
573      * places a stream type is needed.
574      */
575     public static final int USE_DEFAULT_STREAM_TYPE = Integer.MIN_VALUE;
576 
577     private static IAudioService sService;
578 
579     /**
580      * @hide
581      */
AudioManager(Context context)582     public AudioManager(Context context) {
583         mContext = context;
584         mUseMasterVolume = mContext.getResources().getBoolean(
585                 com.android.internal.R.bool.config_useMasterVolume);
586         mUseVolumeKeySounds = mContext.getResources().getBoolean(
587                 com.android.internal.R.bool.config_useVolumeKeySounds);
588         mAudioPortEventHandler = new AudioPortEventHandler(this);
589         mUseFixedVolume = mContext.getResources().getBoolean(
590                 com.android.internal.R.bool.config_useFixedVolume);
591     }
592 
getService()593     private static IAudioService getService()
594     {
595         if (sService != null) {
596             return sService;
597         }
598         IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
599         sService = IAudioService.Stub.asInterface(b);
600         return sService;
601     }
602 
603     /**
604      * Sends a simulated key event for a media button.
605      * To simulate a key press, you must first send a KeyEvent built with a
606      * {@link KeyEvent#ACTION_DOWN} action, then another event with the {@link KeyEvent#ACTION_UP}
607      * action.
608      * <p>The key event will be sent to the current media key event consumer which registered with
609      * {@link AudioManager#registerMediaButtonEventReceiver(PendingIntent)}.
610      * @param keyEvent a {@link KeyEvent} instance whose key code is one of
611      *     {@link KeyEvent#KEYCODE_MUTE},
612      *     {@link KeyEvent#KEYCODE_HEADSETHOOK},
613      *     {@link KeyEvent#KEYCODE_MEDIA_PLAY},
614      *     {@link KeyEvent#KEYCODE_MEDIA_PAUSE},
615      *     {@link KeyEvent#KEYCODE_MEDIA_PLAY_PAUSE},
616      *     {@link KeyEvent#KEYCODE_MEDIA_STOP},
617      *     {@link KeyEvent#KEYCODE_MEDIA_NEXT},
618      *     {@link KeyEvent#KEYCODE_MEDIA_PREVIOUS},
619      *     {@link KeyEvent#KEYCODE_MEDIA_REWIND},
620      *     {@link KeyEvent#KEYCODE_MEDIA_RECORD},
621      *     {@link KeyEvent#KEYCODE_MEDIA_FAST_FORWARD},
622      *     {@link KeyEvent#KEYCODE_MEDIA_CLOSE},
623      *     {@link KeyEvent#KEYCODE_MEDIA_EJECT},
624      *     or {@link KeyEvent#KEYCODE_MEDIA_AUDIO_TRACK}.
625      */
dispatchMediaKeyEvent(KeyEvent keyEvent)626     public void dispatchMediaKeyEvent(KeyEvent keyEvent) {
627         MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mContext);
628         helper.sendMediaButtonEvent(keyEvent, false);
629     }
630 
631     /**
632      * @hide
633      */
preDispatchKeyEvent(KeyEvent event, int stream)634     public void preDispatchKeyEvent(KeyEvent event, int stream) {
635         /*
636          * If the user hits another key within the play sound delay, then
637          * cancel the sound
638          */
639         int keyCode = event.getKeyCode();
640         if (keyCode != KeyEvent.KEYCODE_VOLUME_DOWN && keyCode != KeyEvent.KEYCODE_VOLUME_UP
641                 && keyCode != KeyEvent.KEYCODE_VOLUME_MUTE
642                 && mVolumeKeyUpTime + AudioService.PLAY_SOUND_DELAY
643                         > SystemClock.uptimeMillis()) {
644             /*
645              * The user has hit another key during the delay (e.g., 300ms)
646              * since the last volume key up, so cancel any sounds.
647              */
648             if (mUseMasterVolume) {
649                 adjustMasterVolume(ADJUST_SAME, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
650             } else {
651                 adjustSuggestedStreamVolume(ADJUST_SAME,
652                         stream, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
653             }
654         }
655     }
656 
657     /**
658      * @hide
659      */
handleKeyDown(KeyEvent event, int stream)660     public void handleKeyDown(KeyEvent event, int stream) {
661         int keyCode = event.getKeyCode();
662         switch (keyCode) {
663             case KeyEvent.KEYCODE_VOLUME_UP:
664             case KeyEvent.KEYCODE_VOLUME_DOWN:
665                 /*
666                  * Adjust the volume in on key down since it is more
667                  * responsive to the user.
668                  */
669                 int flags = FLAG_SHOW_UI | FLAG_VIBRATE;
670 
671                 if (mUseMasterVolume) {
672                     adjustMasterVolume(
673                             keyCode == KeyEvent.KEYCODE_VOLUME_UP
674                                     ? ADJUST_RAISE
675                                     : ADJUST_LOWER,
676                             flags);
677                 } else {
678                     adjustSuggestedStreamVolume(
679                             keyCode == KeyEvent.KEYCODE_VOLUME_UP
680                                     ? ADJUST_RAISE
681                                     : ADJUST_LOWER,
682                             stream,
683                             flags);
684                 }
685                 break;
686             case KeyEvent.KEYCODE_VOLUME_MUTE:
687                 if (event.getRepeatCount() == 0) {
688                     if (mUseMasterVolume) {
689                         setMasterMute(!isMasterMute());
690                     } else {
691                         // TODO: Actually handle MUTE.
692                     }
693                 }
694                 break;
695         }
696     }
697 
698     /**
699      * @hide
700      */
handleKeyUp(KeyEvent event, int stream)701     public void handleKeyUp(KeyEvent event, int stream) {
702         int keyCode = event.getKeyCode();
703         switch (keyCode) {
704             case KeyEvent.KEYCODE_VOLUME_UP:
705             case KeyEvent.KEYCODE_VOLUME_DOWN:
706                 /*
707                  * Play a sound. This is done on key up since we don't want the
708                  * sound to play when a user holds down volume down to mute.
709                  */
710                 if (mUseVolumeKeySounds) {
711                     if (mUseMasterVolume) {
712                         adjustMasterVolume(ADJUST_SAME, FLAG_PLAY_SOUND);
713                     } else {
714                         int flags = FLAG_PLAY_SOUND;
715                         adjustSuggestedStreamVolume(
716                                 ADJUST_SAME,
717                                 stream,
718                                 flags);
719                     }
720                 }
721                 mVolumeKeyUpTime = SystemClock.uptimeMillis();
722                 break;
723         }
724     }
725 
726     /**
727      * Indicates if the device implements a fixed volume policy.
728      * <p>Some devices may not have volume control and may operate at a fixed volume,
729      * and may not enable muting or changing the volume of audio streams.
730      * This method will return true on such devices.
731      * <p>The following APIs have no effect when volume is fixed:
732      * <ul>
733      *   <li> {@link #adjustVolume(int, int)}
734      *   <li> {@link #adjustSuggestedStreamVolume(int, int, int)}
735      *   <li> {@link #adjustStreamVolume(int, int, int)}
736      *   <li> {@link #setStreamVolume(int, int, int)}
737      *   <li> {@link #setRingerMode(int)}
738      *   <li> {@link #setStreamSolo(int, boolean)}
739      *   <li> {@link #setStreamMute(int, boolean)}
740      * </ul>
741      */
isVolumeFixed()742     public boolean isVolumeFixed() {
743         return mUseFixedVolume;
744     }
745 
746     /**
747      * Adjusts the volume of a particular stream by one step in a direction.
748      * <p>
749      * This method should only be used by applications that replace the platform-wide
750      * management of audio settings or the main telephony application.
751      *
752      * @param streamType The stream type to adjust. One of {@link #STREAM_VOICE_CALL},
753      * {@link #STREAM_SYSTEM}, {@link #STREAM_RING}, {@link #STREAM_MUSIC} or
754      * {@link #STREAM_ALARM}
755      * @param direction The direction to adjust the volume. One of
756      *            {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, or
757      *            {@link #ADJUST_SAME}.
758      * @param flags One or more flags.
759      * @see #adjustVolume(int, int)
760      * @see #setStreamVolume(int, int, int)
761      */
adjustStreamVolume(int streamType, int direction, int flags)762     public void adjustStreamVolume(int streamType, int direction, int flags) {
763         IAudioService service = getService();
764         try {
765             if (mUseMasterVolume) {
766                 service.adjustMasterVolume(direction, flags, mContext.getOpPackageName());
767             } else {
768                 service.adjustStreamVolume(streamType, direction, flags,
769                         mContext.getOpPackageName());
770             }
771         } catch (RemoteException e) {
772             Log.e(TAG, "Dead object in adjustStreamVolume", e);
773         }
774     }
775 
776     /**
777      * Adjusts the volume of the most relevant stream. For example, if a call is
778      * active, it will have the highest priority regardless of if the in-call
779      * screen is showing. Another example, if music is playing in the background
780      * and a call is not active, the music stream will be adjusted.
781      * <p>
782      * This method should only be used by applications that replace the platform-wide
783      * management of audio settings or the main telephony application.
784      * <p>This method has no effect if the device implements a fixed volume policy
785      * as indicated by {@link #isVolumeFixed()}.
786      * @param direction The direction to adjust the volume. One of
787      *            {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, or
788      *            {@link #ADJUST_SAME}.
789      * @param flags One or more flags.
790      * @see #adjustSuggestedStreamVolume(int, int, int)
791      * @see #adjustStreamVolume(int, int, int)
792      * @see #setStreamVolume(int, int, int)
793      * @see #isVolumeFixed()
794      */
adjustVolume(int direction, int flags)795     public void adjustVolume(int direction, int flags) {
796         IAudioService service = getService();
797         try {
798             if (mUseMasterVolume) {
799                 service.adjustMasterVolume(direction, flags, mContext.getOpPackageName());
800             } else {
801                 MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mContext);
802                 helper.sendAdjustVolumeBy(USE_DEFAULT_STREAM_TYPE, direction, flags);
803             }
804         } catch (RemoteException e) {
805             Log.e(TAG, "Dead object in adjustVolume", e);
806         }
807     }
808 
809     /**
810      * Adjusts the volume of the most relevant stream, or the given fallback
811      * stream.
812      * <p>
813      * This method should only be used by applications that replace the platform-wide
814      * management of audio settings or the main telephony application.
815      *
816      * <p>This method has no effect if the device implements a fixed volume policy
817      * as indicated by {@link #isVolumeFixed()}.
818      * @param direction The direction to adjust the volume. One of
819      *            {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, or
820      *            {@link #ADJUST_SAME}.
821      * @param suggestedStreamType The stream type that will be used if there
822      *            isn't a relevant stream. {@link #USE_DEFAULT_STREAM_TYPE} is valid here.
823      * @param flags One or more flags.
824      * @see #adjustVolume(int, int)
825      * @see #adjustStreamVolume(int, int, int)
826      * @see #setStreamVolume(int, int, int)
827      * @see #isVolumeFixed()
828      */
adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags)829     public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags) {
830         IAudioService service = getService();
831         try {
832             if (mUseMasterVolume) {
833                 service.adjustMasterVolume(direction, flags, mContext.getOpPackageName());
834             } else {
835                 MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mContext);
836                 helper.sendAdjustVolumeBy(suggestedStreamType, direction, flags);
837             }
838         } catch (RemoteException e) {
839             Log.e(TAG, "Dead object in adjustSuggestedStreamVolume", e);
840         }
841     }
842 
843     /**
844      * Adjusts the master volume for the device's audio amplifier.
845      * <p>
846      *
847      * @param steps The number of volume steps to adjust. A positive
848      *            value will raise the volume.
849      * @param flags One or more flags.
850      * @hide
851      */
adjustMasterVolume(int steps, int flags)852     public void adjustMasterVolume(int steps, int flags) {
853         IAudioService service = getService();
854         try {
855             service.adjustMasterVolume(steps, flags, mContext.getOpPackageName());
856         } catch (RemoteException e) {
857             Log.e(TAG, "Dead object in adjustMasterVolume", e);
858         }
859     }
860 
861     /**
862      * Returns the current ringtone mode.
863      *
864      * @return The current ringtone mode, one of {@link #RINGER_MODE_NORMAL},
865      *         {@link #RINGER_MODE_SILENT}, or {@link #RINGER_MODE_VIBRATE}.
866      * @see #setRingerMode(int)
867      */
getRingerMode()868     public int getRingerMode() {
869         IAudioService service = getService();
870         try {
871             return service.getRingerMode();
872         } catch (RemoteException e) {
873             Log.e(TAG, "Dead object in getRingerMode", e);
874             return RINGER_MODE_NORMAL;
875         }
876     }
877 
878     /**
879      * Checks valid ringer mode values.
880      *
881      * @return true if the ringer mode indicated is valid, false otherwise.
882      *
883      * @see #setRingerMode(int)
884      * @hide
885      */
isValidRingerMode(int ringerMode)886     public static boolean isValidRingerMode(int ringerMode) {
887         if (ringerMode < 0 || ringerMode > RINGER_MODE_MAX) {
888             return false;
889         }
890         return true;
891     }
892 
893     /**
894      * Returns the maximum volume index for a particular stream.
895      *
896      * @param streamType The stream type whose maximum volume index is returned.
897      * @return The maximum valid volume index for the stream.
898      * @see #getStreamVolume(int)
899      */
getStreamMaxVolume(int streamType)900     public int getStreamMaxVolume(int streamType) {
901         IAudioService service = getService();
902         try {
903             if (mUseMasterVolume) {
904                 return service.getMasterMaxVolume();
905             } else {
906                 return service.getStreamMaxVolume(streamType);
907             }
908         } catch (RemoteException e) {
909             Log.e(TAG, "Dead object in getStreamMaxVolume", e);
910             return 0;
911         }
912     }
913 
914     /**
915      * Returns the current volume index for a particular stream.
916      *
917      * @param streamType The stream type whose volume index is returned.
918      * @return The current volume index for the stream.
919      * @see #getStreamMaxVolume(int)
920      * @see #setStreamVolume(int, int, int)
921      */
getStreamVolume(int streamType)922     public int getStreamVolume(int streamType) {
923         IAudioService service = getService();
924         try {
925             if (mUseMasterVolume) {
926                 return service.getMasterVolume();
927             } else {
928                 return service.getStreamVolume(streamType);
929             }
930         } catch (RemoteException e) {
931             Log.e(TAG, "Dead object in getStreamVolume", e);
932             return 0;
933         }
934     }
935 
936     /**
937      * Get last audible volume before stream was muted.
938      *
939      * @hide
940      */
getLastAudibleStreamVolume(int streamType)941     public int getLastAudibleStreamVolume(int streamType) {
942         IAudioService service = getService();
943         try {
944             if (mUseMasterVolume) {
945                 return service.getLastAudibleMasterVolume();
946             } else {
947                 return service.getLastAudibleStreamVolume(streamType);
948             }
949         } catch (RemoteException e) {
950             Log.e(TAG, "Dead object in getLastAudibleStreamVolume", e);
951             return 0;
952         }
953     }
954 
955     /**
956      * Get the stream type whose volume is driving the UI sounds volume.
957      * UI sounds are screen lock/unlock, camera shutter, key clicks...
958      * It is assumed that this stream type is also tied to ringer mode changes.
959      * @hide
960      */
getMasterStreamType()961     public int getMasterStreamType() {
962         IAudioService service = getService();
963         try {
964             return service.getMasterStreamType();
965         } catch (RemoteException e) {
966             Log.e(TAG, "Dead object in getMasterStreamType", e);
967             return STREAM_RING;
968         }
969     }
970 
971     /**
972      * Sets the ringer mode.
973      * <p>
974      * Silent mode will mute the volume and will not vibrate. Vibrate mode will
975      * mute the volume and vibrate. Normal mode will be audible and may vibrate
976      * according to user settings.
977      * <p>This method has no effect if the device implements a fixed volume policy
978      * as indicated by {@link #isVolumeFixed()}.
979      * @param ringerMode The ringer mode, one of {@link #RINGER_MODE_NORMAL},
980      *            {@link #RINGER_MODE_SILENT}, or {@link #RINGER_MODE_VIBRATE}.
981      * @see #getRingerMode()
982      * @see #isVolumeFixed()
983      */
setRingerMode(int ringerMode)984     public void setRingerMode(int ringerMode) {
985         setRingerMode(ringerMode, true /*checkZen*/);
986     }
987 
988     /**
989      * @see #setRingerMode(int)
990      * @param checkZen  Update zen mode if necessary to compensate.
991      * @hide
992      */
setRingerMode(int ringerMode, boolean checkZen)993     public void setRingerMode(int ringerMode, boolean checkZen) {
994         if (!isValidRingerMode(ringerMode)) {
995             return;
996         }
997         IAudioService service = getService();
998         try {
999             service.setRingerMode(ringerMode, checkZen);
1000         } catch (RemoteException e) {
1001             Log.e(TAG, "Dead object in setRingerMode", e);
1002         }
1003     }
1004 
1005     /**
1006      * Sets the volume index for a particular stream.
1007      * <p>This method has no effect if the device implements a fixed volume policy
1008      * as indicated by {@link #isVolumeFixed()}.
1009      * @param streamType The stream whose volume index should be set.
1010      * @param index The volume index to set. See
1011      *            {@link #getStreamMaxVolume(int)} for the largest valid value.
1012      * @param flags One or more flags.
1013      * @see #getStreamMaxVolume(int)
1014      * @see #getStreamVolume(int)
1015      * @see #isVolumeFixed()
1016      */
setStreamVolume(int streamType, int index, int flags)1017     public void setStreamVolume(int streamType, int index, int flags) {
1018         IAudioService service = getService();
1019         try {
1020             if (mUseMasterVolume) {
1021                 service.setMasterVolume(index, flags, mContext.getOpPackageName());
1022             } else {
1023                 service.setStreamVolume(streamType, index, flags, mContext.getOpPackageName());
1024             }
1025         } catch (RemoteException e) {
1026             Log.e(TAG, "Dead object in setStreamVolume", e);
1027         }
1028     }
1029 
1030     /**
1031      * Returns the maximum volume index for master volume.
1032      *
1033      * @hide
1034      */
getMasterMaxVolume()1035     public int getMasterMaxVolume() {
1036         IAudioService service = getService();
1037         try {
1038             return service.getMasterMaxVolume();
1039         } catch (RemoteException e) {
1040             Log.e(TAG, "Dead object in getMasterMaxVolume", e);
1041             return 0;
1042         }
1043     }
1044 
1045     /**
1046      * Returns the current volume index for master volume.
1047      *
1048      * @return The current volume index for master volume.
1049      * @hide
1050      */
getMasterVolume()1051     public int getMasterVolume() {
1052         IAudioService service = getService();
1053         try {
1054             return service.getMasterVolume();
1055         } catch (RemoteException e) {
1056             Log.e(TAG, "Dead object in getMasterVolume", e);
1057             return 0;
1058         }
1059     }
1060 
1061     /**
1062      * Get last audible volume before master volume was muted.
1063      *
1064      * @hide
1065      */
getLastAudibleMasterVolume()1066     public int getLastAudibleMasterVolume() {
1067         IAudioService service = getService();
1068         try {
1069             return service.getLastAudibleMasterVolume();
1070         } catch (RemoteException e) {
1071             Log.e(TAG, "Dead object in getLastAudibleMasterVolume", e);
1072             return 0;
1073         }
1074     }
1075 
1076     /**
1077      * Sets the volume index for master volume.
1078      *
1079      * @param index The volume index to set. See
1080      *            {@link #getMasterMaxVolume()} for the largest valid value.
1081      * @param flags One or more flags.
1082      * @see #getMasterMaxVolume()
1083      * @see #getMasterVolume()
1084      * @hide
1085      */
setMasterVolume(int index, int flags)1086     public void setMasterVolume(int index, int flags) {
1087         IAudioService service = getService();
1088         try {
1089             service.setMasterVolume(index, flags, mContext.getOpPackageName());
1090         } catch (RemoteException e) {
1091             Log.e(TAG, "Dead object in setMasterVolume", e);
1092         }
1093     }
1094 
1095     /**
1096      * Solo or unsolo a particular stream. All other streams are muted.
1097      * <p>
1098      * The solo command is protected against client process death: if a process
1099      * with an active solo request on a stream dies, all streams that were muted
1100      * because of this request will be unmuted automatically.
1101      * <p>
1102      * The solo requests for a given stream are cumulative: the AudioManager
1103      * can receive several solo requests from one or more clients and the stream
1104      * will be unsoloed only when the same number of unsolo requests are received.
1105      * <p>
1106      * For a better user experience, applications MUST unsolo a soloed stream
1107      * in onPause() and solo is again in onResume() if appropriate.
1108      * <p>This method has no effect if the device implements a fixed volume policy
1109      * as indicated by {@link #isVolumeFixed()}.
1110      *
1111      * @param streamType The stream to be soloed/unsoloed.
1112      * @param state The required solo state: true for solo ON, false for solo OFF
1113      *
1114      * @see #isVolumeFixed()
1115      */
setStreamSolo(int streamType, boolean state)1116     public void setStreamSolo(int streamType, boolean state) {
1117         IAudioService service = getService();
1118         try {
1119             service.setStreamSolo(streamType, state, mICallBack);
1120         } catch (RemoteException e) {
1121             Log.e(TAG, "Dead object in setStreamSolo", e);
1122         }
1123     }
1124 
1125     /**
1126      * Mute or unmute an audio stream.
1127      * <p>
1128      * The mute command is protected against client process death: if a process
1129      * with an active mute request on a stream dies, this stream will be unmuted
1130      * automatically.
1131      * <p>
1132      * The mute requests for a given stream are cumulative: the AudioManager
1133      * can receive several mute requests from one or more clients and the stream
1134      * will be unmuted only when the same number of unmute requests are received.
1135      * <p>
1136      * For a better user experience, applications MUST unmute a muted stream
1137      * in onPause() and mute is again in onResume() if appropriate.
1138      * <p>
1139      * This method should only be used by applications that replace the platform-wide
1140      * management of audio settings or the main telephony application.
1141      * <p>This method has no effect if the device implements a fixed volume policy
1142      * as indicated by {@link #isVolumeFixed()}.
1143      *
1144      * @param streamType The stream to be muted/unmuted.
1145      * @param state The required mute state: true for mute ON, false for mute OFF
1146      *
1147      * @see #isVolumeFixed()
1148      */
setStreamMute(int streamType, boolean state)1149     public void setStreamMute(int streamType, boolean state) {
1150         IAudioService service = getService();
1151         try {
1152             service.setStreamMute(streamType, state, mICallBack);
1153         } catch (RemoteException e) {
1154             Log.e(TAG, "Dead object in setStreamMute", e);
1155         }
1156     }
1157 
1158     /**
1159      * get stream mute state.
1160      *
1161      * @hide
1162      */
isStreamMute(int streamType)1163     public boolean isStreamMute(int streamType) {
1164         IAudioService service = getService();
1165         try {
1166             return service.isStreamMute(streamType);
1167         } catch (RemoteException e) {
1168             Log.e(TAG, "Dead object in isStreamMute", e);
1169             return false;
1170         }
1171     }
1172 
1173     /**
1174      * set master mute state.
1175      *
1176      * @hide
1177      */
setMasterMute(boolean state)1178     public void setMasterMute(boolean state) {
1179         setMasterMute(state, FLAG_SHOW_UI);
1180     }
1181 
1182     /**
1183      * set master mute state with optional flags.
1184      *
1185      * @hide
1186      */
setMasterMute(boolean state, int flags)1187     public void setMasterMute(boolean state, int flags) {
1188         IAudioService service = getService();
1189         try {
1190             service.setMasterMute(state, flags, mContext.getOpPackageName(), mICallBack);
1191         } catch (RemoteException e) {
1192             Log.e(TAG, "Dead object in setMasterMute", e);
1193         }
1194     }
1195 
1196     /**
1197      * get master mute state.
1198      *
1199      * @hide
1200      */
isMasterMute()1201     public boolean isMasterMute() {
1202         IAudioService service = getService();
1203         try {
1204             return service.isMasterMute();
1205         } catch (RemoteException e) {
1206             Log.e(TAG, "Dead object in isMasterMute", e);
1207             return false;
1208         }
1209     }
1210 
1211     /**
1212      * forces the stream controlled by hard volume keys
1213      * specifying streamType == -1 releases control to the
1214      * logic.
1215      *
1216      * @hide
1217      */
forceVolumeControlStream(int streamType)1218     public void forceVolumeControlStream(int streamType) {
1219         IAudioService service = getService();
1220         try {
1221             service.forceVolumeControlStream(streamType, mICallBack);
1222         } catch (RemoteException e) {
1223             Log.e(TAG, "Dead object in forceVolumeControlStream", e);
1224         }
1225     }
1226 
1227     /**
1228      * Returns whether a particular type should vibrate according to user
1229      * settings and the current ringer mode.
1230      * <p>
1231      * This shouldn't be needed by most clients that use notifications to
1232      * vibrate. The notification manager will not vibrate if the policy doesn't
1233      * allow it, so the client should always set a vibrate pattern and let the
1234      * notification manager control whether or not to actually vibrate.
1235      *
1236      * @param vibrateType The type of vibrate. One of
1237      *            {@link #VIBRATE_TYPE_NOTIFICATION} or
1238      *            {@link #VIBRATE_TYPE_RINGER}.
1239      * @return Whether the type should vibrate at the instant this method is
1240      *         called.
1241      * @see #setVibrateSetting(int, int)
1242      * @see #getVibrateSetting(int)
1243      * @deprecated Applications should maintain their own vibrate policy based on
1244      * current ringer mode that can be queried via {@link #getRingerMode()}.
1245      */
shouldVibrate(int vibrateType)1246     public boolean shouldVibrate(int vibrateType) {
1247         IAudioService service = getService();
1248         try {
1249             return service.shouldVibrate(vibrateType);
1250         } catch (RemoteException e) {
1251             Log.e(TAG, "Dead object in shouldVibrate", e);
1252             return false;
1253         }
1254     }
1255 
1256     /**
1257      * Returns whether the user's vibrate setting for a vibrate type.
1258      * <p>
1259      * This shouldn't be needed by most clients that want to vibrate, instead
1260      * see {@link #shouldVibrate(int)}.
1261      *
1262      * @param vibrateType The type of vibrate. One of
1263      *            {@link #VIBRATE_TYPE_NOTIFICATION} or
1264      *            {@link #VIBRATE_TYPE_RINGER}.
1265      * @return The vibrate setting, one of {@link #VIBRATE_SETTING_ON},
1266      *         {@link #VIBRATE_SETTING_OFF}, or
1267      *         {@link #VIBRATE_SETTING_ONLY_SILENT}.
1268      * @see #setVibrateSetting(int, int)
1269      * @see #shouldVibrate(int)
1270      * @deprecated Applications should maintain their own vibrate policy based on
1271      * current ringer mode that can be queried via {@link #getRingerMode()}.
1272      */
getVibrateSetting(int vibrateType)1273     public int getVibrateSetting(int vibrateType) {
1274         IAudioService service = getService();
1275         try {
1276             return service.getVibrateSetting(vibrateType);
1277         } catch (RemoteException e) {
1278             Log.e(TAG, "Dead object in getVibrateSetting", e);
1279             return VIBRATE_SETTING_OFF;
1280         }
1281     }
1282 
1283     /**
1284      * Sets the setting for when the vibrate type should vibrate.
1285      * <p>
1286      * This method should only be used by applications that replace the platform-wide
1287      * management of audio settings or the main telephony application.
1288      *
1289      * @param vibrateType The type of vibrate. One of
1290      *            {@link #VIBRATE_TYPE_NOTIFICATION} or
1291      *            {@link #VIBRATE_TYPE_RINGER}.
1292      * @param vibrateSetting The vibrate setting, one of
1293      *            {@link #VIBRATE_SETTING_ON},
1294      *            {@link #VIBRATE_SETTING_OFF}, or
1295      *            {@link #VIBRATE_SETTING_ONLY_SILENT}.
1296      * @see #getVibrateSetting(int)
1297      * @see #shouldVibrate(int)
1298      * @deprecated Applications should maintain their own vibrate policy based on
1299      * current ringer mode that can be queried via {@link #getRingerMode()}.
1300      */
setVibrateSetting(int vibrateType, int vibrateSetting)1301     public void setVibrateSetting(int vibrateType, int vibrateSetting) {
1302         IAudioService service = getService();
1303         try {
1304             service.setVibrateSetting(vibrateType, vibrateSetting);
1305         } catch (RemoteException e) {
1306             Log.e(TAG, "Dead object in setVibrateSetting", e);
1307         }
1308     }
1309 
1310     /**
1311      * Sets the speakerphone on or off.
1312      * <p>
1313      * This method should only be used by applications that replace the platform-wide
1314      * management of audio settings or the main telephony application.
1315      *
1316      * @param on set <var>true</var> to turn on speakerphone;
1317      *           <var>false</var> to turn it off
1318      */
setSpeakerphoneOn(boolean on)1319     public void setSpeakerphoneOn(boolean on){
1320         IAudioService service = getService();
1321         try {
1322             service.setSpeakerphoneOn(on);
1323         } catch (RemoteException e) {
1324             Log.e(TAG, "Dead object in setSpeakerphoneOn", e);
1325         }
1326     }
1327 
1328     /**
1329      * Checks whether the speakerphone is on or off.
1330      *
1331      * @return true if speakerphone is on, false if it's off
1332      */
isSpeakerphoneOn()1333     public boolean isSpeakerphoneOn() {
1334         IAudioService service = getService();
1335         try {
1336             return service.isSpeakerphoneOn();
1337         } catch (RemoteException e) {
1338             Log.e(TAG, "Dead object in isSpeakerphoneOn", e);
1339             return false;
1340         }
1341      }
1342 
1343     //====================================================================
1344     // Bluetooth SCO control
1345     /**
1346      * Sticky broadcast intent action indicating that the bluetoooth SCO audio
1347      * connection state has changed. The intent contains on extra {@link #EXTRA_SCO_AUDIO_STATE}
1348      * indicating the new state which is either {@link #SCO_AUDIO_STATE_DISCONNECTED}
1349      * or {@link #SCO_AUDIO_STATE_CONNECTED}
1350      *
1351      * @see #startBluetoothSco()
1352      * @deprecated Use  {@link #ACTION_SCO_AUDIO_STATE_UPDATED} instead
1353      */
1354     @Deprecated
1355     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
1356     public static final String ACTION_SCO_AUDIO_STATE_CHANGED =
1357             "android.media.SCO_AUDIO_STATE_CHANGED";
1358 
1359      /**
1360      * Sticky broadcast intent action indicating that the bluetoooth SCO audio
1361      * connection state has been updated.
1362      * <p>This intent has two extras:
1363      * <ul>
1364      *   <li> {@link #EXTRA_SCO_AUDIO_STATE} - The new SCO audio state. </li>
1365      *   <li> {@link #EXTRA_SCO_AUDIO_PREVIOUS_STATE}- The previous SCO audio state. </li>
1366      * </ul>
1367      * <p> EXTRA_SCO_AUDIO_STATE or EXTRA_SCO_AUDIO_PREVIOUS_STATE can be any of:
1368      * <ul>
1369      *   <li> {@link #SCO_AUDIO_STATE_DISCONNECTED}, </li>
1370      *   <li> {@link #SCO_AUDIO_STATE_CONNECTING} or </li>
1371      *   <li> {@link #SCO_AUDIO_STATE_CONNECTED}, </li>
1372      * </ul>
1373      * @see #startBluetoothSco()
1374      */
1375     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
1376     public static final String ACTION_SCO_AUDIO_STATE_UPDATED =
1377             "android.media.ACTION_SCO_AUDIO_STATE_UPDATED";
1378 
1379     /**
1380      * Extra for intent {@link #ACTION_SCO_AUDIO_STATE_CHANGED} or
1381      * {@link #ACTION_SCO_AUDIO_STATE_UPDATED} containing the new bluetooth SCO connection state.
1382      */
1383     public static final String EXTRA_SCO_AUDIO_STATE =
1384             "android.media.extra.SCO_AUDIO_STATE";
1385 
1386     /**
1387      * Extra for intent {@link #ACTION_SCO_AUDIO_STATE_UPDATED} containing the previous
1388      * bluetooth SCO connection state.
1389      */
1390     public static final String EXTRA_SCO_AUDIO_PREVIOUS_STATE =
1391             "android.media.extra.SCO_AUDIO_PREVIOUS_STATE";
1392 
1393     /**
1394      * Value for extra EXTRA_SCO_AUDIO_STATE or EXTRA_SCO_AUDIO_PREVIOUS_STATE
1395      * indicating that the SCO audio channel is not established
1396      */
1397     public static final int SCO_AUDIO_STATE_DISCONNECTED = 0;
1398     /**
1399      * Value for extra {@link #EXTRA_SCO_AUDIO_STATE} or {@link #EXTRA_SCO_AUDIO_PREVIOUS_STATE}
1400      * indicating that the SCO audio channel is established
1401      */
1402     public static final int SCO_AUDIO_STATE_CONNECTED = 1;
1403     /**
1404      * Value for extra EXTRA_SCO_AUDIO_STATE or EXTRA_SCO_AUDIO_PREVIOUS_STATE
1405      * indicating that the SCO audio channel is being established
1406      */
1407     public static final int SCO_AUDIO_STATE_CONNECTING = 2;
1408     /**
1409      * Value for extra EXTRA_SCO_AUDIO_STATE indicating that
1410      * there was an error trying to obtain the state
1411      */
1412     public static final int SCO_AUDIO_STATE_ERROR = -1;
1413 
1414 
1415     /**
1416      * Indicates if current platform supports use of SCO for off call use cases.
1417      * Application wanted to use bluetooth SCO audio when the phone is not in call
1418      * must first call this method to make sure that the platform supports this
1419      * feature.
1420      * @return true if bluetooth SCO can be used for audio when not in call
1421      *         false otherwise
1422      * @see #startBluetoothSco()
1423     */
isBluetoothScoAvailableOffCall()1424     public boolean isBluetoothScoAvailableOffCall() {
1425         return mContext.getResources().getBoolean(
1426                com.android.internal.R.bool.config_bluetooth_sco_off_call);
1427     }
1428 
1429     /**
1430      * Start bluetooth SCO audio connection.
1431      * <p>Requires Permission:
1432      *   {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}.
1433      * <p>This method can be used by applications wanting to send and received audio
1434      * to/from a bluetooth SCO headset while the phone is not in call.
1435      * <p>As the SCO connection establishment can take several seconds,
1436      * applications should not rely on the connection to be available when the method
1437      * returns but instead register to receive the intent {@link #ACTION_SCO_AUDIO_STATE_UPDATED}
1438      * and wait for the state to be {@link #SCO_AUDIO_STATE_CONNECTED}.
1439      * <p>As the ACTION_SCO_AUDIO_STATE_UPDATED intent is sticky, the application can check the SCO
1440      * audio state before calling startBluetoothSco() by reading the intent returned by the receiver
1441      * registration. If the state is already CONNECTED, no state change will be received via the
1442      * intent after calling startBluetoothSco(). It is however useful to call startBluetoothSco()
1443      * so that the connection stays active in case the current initiator stops the connection.
1444      * <p>Unless the connection is already active as described above, the state will always
1445      * transition from DISCONNECTED to CONNECTING and then either to CONNECTED if the connection
1446      * succeeds or back to DISCONNECTED if the connection fails (e.g no headset is connected).
1447      * <p>When finished with the SCO connection or if the establishment fails, the application must
1448      * call {@link #stopBluetoothSco()} to clear the request and turn down the bluetooth connection.
1449      * <p>Even if a SCO connection is established, the following restrictions apply on audio
1450      * output streams so that they can be routed to SCO headset:
1451      * <ul>
1452      *   <li> the stream type must be {@link #STREAM_VOICE_CALL} </li>
1453      *   <li> the format must be mono </li>
1454      *   <li> the sampling must be 16kHz or 8kHz </li>
1455      * </ul>
1456      * <p>The following restrictions apply on input streams:
1457      * <ul>
1458      *   <li> the format must be mono </li>
1459      *   <li> the sampling must be 8kHz </li>
1460      * </ul>
1461      * <p>Note that the phone application always has the priority on the usage of the SCO
1462      * connection for telephony. If this method is called while the phone is in call
1463      * it will be ignored. Similarly, if a call is received or sent while an application
1464      * is using the SCO connection, the connection will be lost for the application and NOT
1465      * returned automatically when the call ends.
1466      * <p>NOTE: up to and including API version
1467      * {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}, this method initiates a virtual
1468      * voice call to the bluetooth headset.
1469      * After API version {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2} only a raw SCO audio
1470      * connection is established.
1471      * @see #stopBluetoothSco()
1472      * @see #ACTION_SCO_AUDIO_STATE_UPDATED
1473      */
startBluetoothSco()1474     public void startBluetoothSco(){
1475         IAudioService service = getService();
1476         try {
1477             service.startBluetoothSco(mICallBack, mContext.getApplicationInfo().targetSdkVersion);
1478         } catch (RemoteException e) {
1479             Log.e(TAG, "Dead object in startBluetoothSco", e);
1480         }
1481     }
1482 
1483     /**
1484      * @hide
1485      * Start bluetooth SCO audio connection in virtual call mode.
1486      * <p>Requires Permission:
1487      *   {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}.
1488      * <p>Similar to {@link #startBluetoothSco()} with explicit selection of virtual call mode.
1489      * Telephony and communication applications (VoIP, Video Chat) should preferably select
1490      * virtual call mode.
1491      * Applications using voice input for search or commands should first try raw audio connection
1492      * with {@link #startBluetoothSco()} and fall back to startBluetoothScoVirtualCall() in case of
1493      * failure.
1494      * @see #startBluetoothSco()
1495      * @see #stopBluetoothSco()
1496      * @see #ACTION_SCO_AUDIO_STATE_UPDATED
1497      */
startBluetoothScoVirtualCall()1498     public void startBluetoothScoVirtualCall() {
1499         IAudioService service = getService();
1500         try {
1501             service.startBluetoothScoVirtualCall(mICallBack);
1502         } catch (RemoteException e) {
1503             Log.e(TAG, "Dead object in startBluetoothScoVirtualCall", e);
1504         }
1505     }
1506 
1507     /**
1508      * Stop bluetooth SCO audio connection.
1509      * <p>Requires Permission:
1510      *   {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}.
1511      * <p>This method must be called by applications having requested the use of
1512      * bluetooth SCO audio with {@link #startBluetoothSco()} when finished with the SCO
1513      * connection or if connection fails.
1514      * @see #startBluetoothSco()
1515      */
1516     // Also used for connections started with {@link #startBluetoothScoVirtualCall()}
stopBluetoothSco()1517     public void stopBluetoothSco(){
1518         IAudioService service = getService();
1519         try {
1520             service.stopBluetoothSco(mICallBack);
1521         } catch (RemoteException e) {
1522             Log.e(TAG, "Dead object in stopBluetoothSco", e);
1523         }
1524     }
1525 
1526     /**
1527      * Request use of Bluetooth SCO headset for communications.
1528      * <p>
1529      * This method should only be used by applications that replace the platform-wide
1530      * management of audio settings or the main telephony application.
1531      *
1532      * @param on set <var>true</var> to use bluetooth SCO for communications;
1533      *               <var>false</var> to not use bluetooth SCO for communications
1534      */
setBluetoothScoOn(boolean on)1535     public void setBluetoothScoOn(boolean on){
1536         IAudioService service = getService();
1537         try {
1538             service.setBluetoothScoOn(on);
1539         } catch (RemoteException e) {
1540             Log.e(TAG, "Dead object in setBluetoothScoOn", e);
1541         }
1542     }
1543 
1544     /**
1545      * Checks whether communications use Bluetooth SCO.
1546      *
1547      * @return true if SCO is used for communications;
1548      *         false if otherwise
1549      */
isBluetoothScoOn()1550     public boolean isBluetoothScoOn() {
1551         IAudioService service = getService();
1552         try {
1553             return service.isBluetoothScoOn();
1554         } catch (RemoteException e) {
1555             Log.e(TAG, "Dead object in isBluetoothScoOn", e);
1556             return false;
1557         }
1558     }
1559 
1560     /**
1561      * @param on set <var>true</var> to route A2DP audio to/from Bluetooth
1562      *           headset; <var>false</var> disable A2DP audio
1563      * @deprecated Do not use.
1564      */
setBluetoothA2dpOn(boolean on)1565     @Deprecated public void setBluetoothA2dpOn(boolean on){
1566     }
1567 
1568     /**
1569      * Checks whether A2DP audio routing to the Bluetooth headset is on or off.
1570      *
1571      * @return true if A2DP audio is being routed to/from Bluetooth headset;
1572      *         false if otherwise
1573      */
isBluetoothA2dpOn()1574     public boolean isBluetoothA2dpOn() {
1575         if (AudioSystem.getDeviceConnectionState(DEVICE_OUT_BLUETOOTH_A2DP,"")
1576             == AudioSystem.DEVICE_STATE_UNAVAILABLE) {
1577             return false;
1578         } else {
1579             return true;
1580         }
1581     }
1582 
1583     /**
1584      * Sets audio routing to the wired headset on or off.
1585      *
1586      * @param on set <var>true</var> to route audio to/from wired
1587      *           headset; <var>false</var> disable wired headset audio
1588      * @deprecated Do not use.
1589      */
setWiredHeadsetOn(boolean on)1590     @Deprecated public void setWiredHeadsetOn(boolean on){
1591     }
1592 
1593     /**
1594      * Checks whether a wired headset is connected or not.
1595      * <p>This is not a valid indication that audio playback is
1596      * actually over the wired headset as audio routing depends on other conditions.
1597      *
1598      * @return true if a wired headset is connected.
1599      *         false if otherwise
1600      * @deprecated Use only to check is a headset is connected or not.
1601      */
isWiredHeadsetOn()1602     public boolean isWiredHeadsetOn() {
1603         if (AudioSystem.getDeviceConnectionState(DEVICE_OUT_WIRED_HEADSET,"")
1604                 == AudioSystem.DEVICE_STATE_UNAVAILABLE &&
1605             AudioSystem.getDeviceConnectionState(DEVICE_OUT_WIRED_HEADPHONE,"")
1606                 == AudioSystem.DEVICE_STATE_UNAVAILABLE) {
1607             return false;
1608         } else {
1609             return true;
1610         }
1611     }
1612 
1613     /**
1614      * Sets the microphone mute on or off.
1615      * <p>
1616      * This method should only be used by applications that replace the platform-wide
1617      * management of audio settings or the main telephony application.
1618      *
1619      * @param on set <var>true</var> to mute the microphone;
1620      *           <var>false</var> to turn mute off
1621      */
setMicrophoneMute(boolean on)1622     public void setMicrophoneMute(boolean on){
1623         IAudioService service = getService();
1624         try {
1625             service.setMicrophoneMute(on, mContext.getOpPackageName());
1626         } catch (RemoteException e) {
1627             Log.e(TAG, "Dead object in setMicrophoneMute", e);
1628         }
1629     }
1630 
1631     /**
1632      * Checks whether the microphone mute is on or off.
1633      *
1634      * @return true if microphone is muted, false if it's not
1635      */
isMicrophoneMute()1636     public boolean isMicrophoneMute() {
1637         return AudioSystem.isMicrophoneMuted();
1638     }
1639 
1640     /**
1641      * Sets the audio mode.
1642      * <p>
1643      * The audio mode encompasses audio routing AND the behavior of
1644      * the telephony layer. Therefore this method should only be used by applications that
1645      * replace the platform-wide management of audio settings or the main telephony application.
1646      * In particular, the {@link #MODE_IN_CALL} mode should only be used by the telephony
1647      * application when it places a phone call, as it will cause signals from the radio layer
1648      * to feed the platform mixer.
1649      *
1650      * @param mode  the requested audio mode ({@link #MODE_NORMAL}, {@link #MODE_RINGTONE},
1651      *              {@link #MODE_IN_CALL} or {@link #MODE_IN_COMMUNICATION}).
1652      *              Informs the HAL about the current audio state so that
1653      *              it can route the audio appropriately.
1654      */
setMode(int mode)1655     public void setMode(int mode) {
1656         IAudioService service = getService();
1657         try {
1658             service.setMode(mode, mICallBack);
1659         } catch (RemoteException e) {
1660             Log.e(TAG, "Dead object in setMode", e);
1661         }
1662     }
1663 
1664     /**
1665      * Returns the current audio mode.
1666      *
1667      * @return      the current audio mode ({@link #MODE_NORMAL}, {@link #MODE_RINGTONE},
1668      *              {@link #MODE_IN_CALL} or {@link #MODE_IN_COMMUNICATION}).
1669      *              Returns the current current audio state from the HAL.
1670      */
getMode()1671     public int getMode() {
1672         IAudioService service = getService();
1673         try {
1674             return service.getMode();
1675         } catch (RemoteException e) {
1676             Log.e(TAG, "Dead object in getMode", e);
1677             return MODE_INVALID;
1678         }
1679     }
1680 
1681     /* modes for setMode/getMode/setRoute/getRoute */
1682     /**
1683      * Audio harware modes.
1684      */
1685     /**
1686      * Invalid audio mode.
1687      */
1688     public static final int MODE_INVALID            = AudioSystem.MODE_INVALID;
1689     /**
1690      * Current audio mode. Used to apply audio routing to current mode.
1691      */
1692     public static final int MODE_CURRENT            = AudioSystem.MODE_CURRENT;
1693     /**
1694      * Normal audio mode: not ringing and no call established.
1695      */
1696     public static final int MODE_NORMAL             = AudioSystem.MODE_NORMAL;
1697     /**
1698      * Ringing audio mode. An incoming is being signaled.
1699      */
1700     public static final int MODE_RINGTONE           = AudioSystem.MODE_RINGTONE;
1701     /**
1702      * In call audio mode. A telephony call is established.
1703      */
1704     public static final int MODE_IN_CALL            = AudioSystem.MODE_IN_CALL;
1705     /**
1706      * In communication audio mode. An audio/video chat or VoIP call is established.
1707      */
1708     public static final int MODE_IN_COMMUNICATION   = AudioSystem.MODE_IN_COMMUNICATION;
1709 
1710     /* Routing bits for setRouting/getRouting API */
1711     /**
1712      * Routing audio output to earpiece
1713      * @deprecated   Do not set audio routing directly, use setSpeakerphoneOn(),
1714      * setBluetoothScoOn() methods instead.
1715      */
1716     @Deprecated public static final int ROUTE_EARPIECE          = AudioSystem.ROUTE_EARPIECE;
1717     /**
1718      * Routing audio output to speaker
1719      * @deprecated   Do not set audio routing directly, use setSpeakerphoneOn(),
1720      * setBluetoothScoOn() methods instead.
1721      */
1722     @Deprecated public static final int ROUTE_SPEAKER           = AudioSystem.ROUTE_SPEAKER;
1723     /**
1724      * @deprecated use {@link #ROUTE_BLUETOOTH_SCO}
1725      * @deprecated   Do not set audio routing directly, use setSpeakerphoneOn(),
1726      * setBluetoothScoOn() methods instead.
1727      */
1728     @Deprecated public static final int ROUTE_BLUETOOTH = AudioSystem.ROUTE_BLUETOOTH_SCO;
1729     /**
1730      * Routing audio output to bluetooth SCO
1731      * @deprecated   Do not set audio routing directly, use setSpeakerphoneOn(),
1732      * setBluetoothScoOn() methods instead.
1733      */
1734     @Deprecated public static final int ROUTE_BLUETOOTH_SCO     = AudioSystem.ROUTE_BLUETOOTH_SCO;
1735     /**
1736      * Routing audio output to headset
1737      * @deprecated   Do not set audio routing directly, use setSpeakerphoneOn(),
1738      * setBluetoothScoOn() methods instead.
1739      */
1740     @Deprecated public static final int ROUTE_HEADSET           = AudioSystem.ROUTE_HEADSET;
1741     /**
1742      * Routing audio output to bluetooth A2DP
1743      * @deprecated   Do not set audio routing directly, use setSpeakerphoneOn(),
1744      * setBluetoothScoOn() methods instead.
1745      */
1746     @Deprecated public static final int ROUTE_BLUETOOTH_A2DP    = AudioSystem.ROUTE_BLUETOOTH_A2DP;
1747     /**
1748      * Used for mask parameter of {@link #setRouting(int,int,int)}.
1749      * @deprecated   Do not set audio routing directly, use setSpeakerphoneOn(),
1750      * setBluetoothScoOn() methods instead.
1751      */
1752     @Deprecated public static final int ROUTE_ALL               = AudioSystem.ROUTE_ALL;
1753 
1754     /**
1755      * Sets the audio routing for a specified mode
1756      *
1757      * @param mode   audio mode to change route. E.g., MODE_RINGTONE.
1758      * @param routes bit vector of routes requested, created from one or
1759      *               more of ROUTE_xxx types. Set bits indicate that route should be on
1760      * @param mask   bit vector of routes to change, created from one or more of
1761      * ROUTE_xxx types. Unset bits indicate the route should be left unchanged
1762      *
1763      * @deprecated   Do not set audio routing directly, use setSpeakerphoneOn(),
1764      * setBluetoothScoOn() methods instead.
1765      */
1766     @Deprecated
setRouting(int mode, int routes, int mask)1767     public void setRouting(int mode, int routes, int mask) {
1768     }
1769 
1770     /**
1771      * Returns the current audio routing bit vector for a specified mode.
1772      *
1773      * @param mode audio mode to get route (e.g., MODE_RINGTONE)
1774      * @return an audio route bit vector that can be compared with ROUTE_xxx
1775      * bits
1776      * @deprecated   Do not query audio routing directly, use isSpeakerphoneOn(),
1777      * isBluetoothScoOn(), isBluetoothA2dpOn() and isWiredHeadsetOn() methods instead.
1778      */
1779     @Deprecated
getRouting(int mode)1780     public int getRouting(int mode) {
1781         return -1;
1782     }
1783 
1784     /**
1785      * Checks whether any music is active.
1786      *
1787      * @return true if any music tracks are active.
1788      */
isMusicActive()1789     public boolean isMusicActive() {
1790         return AudioSystem.isStreamActive(STREAM_MUSIC, 0);
1791     }
1792 
1793     /**
1794      * @hide
1795      * Checks whether any music or media is actively playing on a remote device (e.g. wireless
1796      *   display). Note that BT audio sinks are not considered remote devices.
1797      * @return true if {@link AudioManager#STREAM_MUSIC} is active on a remote device
1798      */
isMusicActiveRemotely()1799     public boolean isMusicActiveRemotely() {
1800         return AudioSystem.isStreamActiveRemotely(STREAM_MUSIC, 0);
1801     }
1802 
1803     /**
1804      * @hide
1805      * Checks whether the current audio focus is exclusive.
1806      * @return true if the top of the audio focus stack requested focus
1807      *     with {@link #AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE}
1808      */
isAudioFocusExclusive()1809     public boolean isAudioFocusExclusive() {
1810         IAudioService service = getService();
1811         try {
1812             return service.getCurrentAudioFocus() == AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE;
1813         } catch (RemoteException e) {
1814             Log.e(TAG, "Dead object in isAudioFocusExclusive()", e);
1815             return false;
1816         }
1817     }
1818 
1819     /**
1820      * Return a new audio session identifier not associated with any player or effect.
1821      * An audio session identifier is a system wide unique identifier for a set of audio streams
1822      * (one or more mixed together).
1823      * <p>The primary use of the audio session ID is to associate audio effects to audio players,
1824      * such as {@link MediaPlayer} or {@link AudioTrack}: all audio effects sharing the same audio
1825      * session ID will be applied to the mixed audio content of the players that share the same
1826      * audio session.
1827      * <p>This method can for instance be used when creating one of the
1828      * {@link android.media.audiofx.AudioEffect} objects to define the audio session of the effect,
1829      * or to specify a session for a speech synthesis utterance
1830      * in {@link android.speech.tts.TextToSpeech.Engine}.
1831      * @return a new unclaimed and unused audio session identifier, or {@link #ERROR} when the
1832      *   system failed to generate a new session, a condition in which audio playback or recording
1833      *   will subsequently fail as well.
1834      */
generateAudioSessionId()1835     public int generateAudioSessionId() {
1836         int session = AudioSystem.newAudioSessionId();
1837         if (session > 0) {
1838             return session;
1839         } else {
1840             Log.e(TAG, "Failure to generate a new audio session ID");
1841             return ERROR;
1842         }
1843     }
1844 
1845     /**
1846      * A special audio session ID to indicate that the audio session ID isn't known and the
1847      * framework should generate a new value. This can be used when building a new
1848      * {@link AudioTrack} instance with
1849      * {@link AudioTrack#AudioTrack(AudioAttributes, AudioFormat, int, int, int)}.
1850      */
1851     public static final int AUDIO_SESSION_ID_GENERATE = AudioSystem.AUDIO_SESSION_ALLOCATE;
1852 
1853 
1854     /*
1855      * Sets a generic audio configuration parameter. The use of these parameters
1856      * are platform dependant, see libaudio
1857      *
1858      * ** Temporary interface - DO NOT USE
1859      *
1860      * TODO: Replace with a more generic key:value get/set mechanism
1861      *
1862      * param key   name of parameter to set. Must not be null.
1863      * param value value of parameter. Must not be null.
1864      */
1865     /**
1866      * @hide
1867      * @deprecated Use {@link #setParameters(String)} instead
1868      */
setParameter(String key, String value)1869     @Deprecated public void setParameter(String key, String value) {
1870         setParameters(key+"="+value);
1871     }
1872 
1873     /**
1874      * Sets a variable number of parameter values to audio hardware.
1875      *
1876      * @param keyValuePairs list of parameters key value pairs in the form:
1877      *    key1=value1;key2=value2;...
1878      *
1879      */
setParameters(String keyValuePairs)1880     public void setParameters(String keyValuePairs) {
1881         AudioSystem.setParameters(keyValuePairs);
1882     }
1883 
1884     /**
1885      * Gets a variable number of parameter values from audio hardware.
1886      *
1887      * @param keys list of parameters
1888      * @return list of parameters key value pairs in the form:
1889      *    key1=value1;key2=value2;...
1890      */
getParameters(String keys)1891     public String getParameters(String keys) {
1892         return AudioSystem.getParameters(keys);
1893     }
1894 
1895     /* Sound effect identifiers */
1896     /**
1897      * Keyboard and direction pad click sound
1898      * @see #playSoundEffect(int)
1899      */
1900     public static final int FX_KEY_CLICK = 0;
1901     /**
1902      * Focus has moved up
1903      * @see #playSoundEffect(int)
1904      */
1905     public static final int FX_FOCUS_NAVIGATION_UP = 1;
1906     /**
1907      * Focus has moved down
1908      * @see #playSoundEffect(int)
1909      */
1910     public static final int FX_FOCUS_NAVIGATION_DOWN = 2;
1911     /**
1912      * Focus has moved left
1913      * @see #playSoundEffect(int)
1914      */
1915     public static final int FX_FOCUS_NAVIGATION_LEFT = 3;
1916     /**
1917      * Focus has moved right
1918      * @see #playSoundEffect(int)
1919      */
1920     public static final int FX_FOCUS_NAVIGATION_RIGHT = 4;
1921     /**
1922      * IME standard keypress sound
1923      * @see #playSoundEffect(int)
1924      */
1925     public static final int FX_KEYPRESS_STANDARD = 5;
1926     /**
1927      * IME spacebar keypress sound
1928      * @see #playSoundEffect(int)
1929      */
1930     public static final int FX_KEYPRESS_SPACEBAR = 6;
1931     /**
1932      * IME delete keypress sound
1933      * @see #playSoundEffect(int)
1934      */
1935     public static final int FX_KEYPRESS_DELETE = 7;
1936     /**
1937      * IME return_keypress sound
1938      * @see #playSoundEffect(int)
1939      */
1940     public static final int FX_KEYPRESS_RETURN = 8;
1941 
1942     /**
1943      * Invalid keypress sound
1944      * @see #playSoundEffect(int)
1945      */
1946     public static final int FX_KEYPRESS_INVALID = 9;
1947     /**
1948      * @hide Number of sound effects
1949      */
1950     public static final int NUM_SOUND_EFFECTS = 10;
1951 
1952     /**
1953      * Plays a sound effect (Key clicks, lid open/close...)
1954      * @param effectType The type of sound effect. One of
1955      *            {@link #FX_KEY_CLICK},
1956      *            {@link #FX_FOCUS_NAVIGATION_UP},
1957      *            {@link #FX_FOCUS_NAVIGATION_DOWN},
1958      *            {@link #FX_FOCUS_NAVIGATION_LEFT},
1959      *            {@link #FX_FOCUS_NAVIGATION_RIGHT},
1960      *            {@link #FX_KEYPRESS_STANDARD},
1961      *            {@link #FX_KEYPRESS_SPACEBAR},
1962      *            {@link #FX_KEYPRESS_DELETE},
1963      *            {@link #FX_KEYPRESS_RETURN},
1964      *            {@link #FX_KEYPRESS_INVALID},
1965      * NOTE: This version uses the UI settings to determine
1966      * whether sounds are heard or not.
1967      */
playSoundEffect(int effectType)1968     public void  playSoundEffect(int effectType) {
1969         if (effectType < 0 || effectType >= NUM_SOUND_EFFECTS) {
1970             return;
1971         }
1972 
1973         if (!querySoundEffectsEnabled(Process.myUserHandle().getIdentifier())) {
1974             return;
1975         }
1976 
1977         IAudioService service = getService();
1978         try {
1979             service.playSoundEffect(effectType);
1980         } catch (RemoteException e) {
1981             Log.e(TAG, "Dead object in playSoundEffect"+e);
1982         }
1983     }
1984 
1985     /**
1986      * Plays a sound effect (Key clicks, lid open/close...)
1987      * @param effectType The type of sound effect. One of
1988      *            {@link #FX_KEY_CLICK},
1989      *            {@link #FX_FOCUS_NAVIGATION_UP},
1990      *            {@link #FX_FOCUS_NAVIGATION_DOWN},
1991      *            {@link #FX_FOCUS_NAVIGATION_LEFT},
1992      *            {@link #FX_FOCUS_NAVIGATION_RIGHT},
1993      *            {@link #FX_KEYPRESS_STANDARD},
1994      *            {@link #FX_KEYPRESS_SPACEBAR},
1995      *            {@link #FX_KEYPRESS_DELETE},
1996      *            {@link #FX_KEYPRESS_RETURN},
1997      *            {@link #FX_KEYPRESS_INVALID},
1998      * @param userId The current user to pull sound settings from
1999      * NOTE: This version uses the UI settings to determine
2000      * whether sounds are heard or not.
2001      * @hide
2002      */
playSoundEffect(int effectType, int userId)2003     public void  playSoundEffect(int effectType, int userId) {
2004         if (effectType < 0 || effectType >= NUM_SOUND_EFFECTS) {
2005             return;
2006         }
2007 
2008         if (!querySoundEffectsEnabled(userId)) {
2009             return;
2010         }
2011 
2012         IAudioService service = getService();
2013         try {
2014             service.playSoundEffect(effectType);
2015         } catch (RemoteException e) {
2016             Log.e(TAG, "Dead object in playSoundEffect"+e);
2017         }
2018     }
2019 
2020     /**
2021      * Plays a sound effect (Key clicks, lid open/close...)
2022      * @param effectType The type of sound effect. One of
2023      *            {@link #FX_KEY_CLICK},
2024      *            {@link #FX_FOCUS_NAVIGATION_UP},
2025      *            {@link #FX_FOCUS_NAVIGATION_DOWN},
2026      *            {@link #FX_FOCUS_NAVIGATION_LEFT},
2027      *            {@link #FX_FOCUS_NAVIGATION_RIGHT},
2028      *            {@link #FX_KEYPRESS_STANDARD},
2029      *            {@link #FX_KEYPRESS_SPACEBAR},
2030      *            {@link #FX_KEYPRESS_DELETE},
2031      *            {@link #FX_KEYPRESS_RETURN},
2032      *            {@link #FX_KEYPRESS_INVALID},
2033      * @param volume Sound effect volume.
2034      * The volume value is a raw scalar so UI controls should be scaled logarithmically.
2035      * If a volume of -1 is specified, the AudioManager.STREAM_MUSIC stream volume minus 3dB will be used.
2036      * NOTE: This version is for applications that have their own
2037      * settings panel for enabling and controlling volume.
2038      */
playSoundEffect(int effectType, float volume)2039     public void  playSoundEffect(int effectType, float volume) {
2040         if (effectType < 0 || effectType >= NUM_SOUND_EFFECTS) {
2041             return;
2042         }
2043 
2044         IAudioService service = getService();
2045         try {
2046             service.playSoundEffectVolume(effectType, volume);
2047         } catch (RemoteException e) {
2048             Log.e(TAG, "Dead object in playSoundEffect"+e);
2049         }
2050     }
2051 
2052     /**
2053      * Settings has an in memory cache, so this is fast.
2054      */
querySoundEffectsEnabled(int user)2055     private boolean querySoundEffectsEnabled(int user) {
2056         return Settings.System.getIntForUser(mContext.getContentResolver(),
2057                 Settings.System.SOUND_EFFECTS_ENABLED, 0, user) != 0;
2058     }
2059 
2060 
2061     /**
2062      *  Load Sound effects.
2063      *  This method must be called when sound effects are enabled.
2064      */
loadSoundEffects()2065     public void loadSoundEffects() {
2066         IAudioService service = getService();
2067         try {
2068             service.loadSoundEffects();
2069         } catch (RemoteException e) {
2070             Log.e(TAG, "Dead object in loadSoundEffects"+e);
2071         }
2072     }
2073 
2074     /**
2075      *  Unload Sound effects.
2076      *  This method can be called to free some memory when
2077      *  sound effects are disabled.
2078      */
unloadSoundEffects()2079     public void unloadSoundEffects() {
2080         IAudioService service = getService();
2081         try {
2082             service.unloadSoundEffects();
2083         } catch (RemoteException e) {
2084             Log.e(TAG, "Dead object in unloadSoundEffects"+e);
2085         }
2086     }
2087 
2088     /**
2089      * @hide
2090      * Used to indicate no audio focus has been gained or lost.
2091      */
2092     public static final int AUDIOFOCUS_NONE = 0;
2093 
2094     /**
2095      * Used to indicate a gain of audio focus, or a request of audio focus, of unknown duration.
2096      * @see OnAudioFocusChangeListener#onAudioFocusChange(int)
2097      * @see #requestAudioFocus(OnAudioFocusChangeListener, int, int)
2098      */
2099     public static final int AUDIOFOCUS_GAIN = 1;
2100     /**
2101      * Used to indicate a temporary gain or request of audio focus, anticipated to last a short
2102      * amount of time. Examples of temporary changes are the playback of driving directions, or an
2103      * event notification.
2104      * @see OnAudioFocusChangeListener#onAudioFocusChange(int)
2105      * @see #requestAudioFocus(OnAudioFocusChangeListener, int, int)
2106      */
2107     public static final int AUDIOFOCUS_GAIN_TRANSIENT = 2;
2108     /**
2109      * Used to indicate a temporary request of audio focus, anticipated to last a short
2110      * amount of time, and where it is acceptable for other audio applications to keep playing
2111      * after having lowered their output level (also referred to as "ducking").
2112      * Examples of temporary changes are the playback of driving directions where playback of music
2113      * in the background is acceptable.
2114      * @see OnAudioFocusChangeListener#onAudioFocusChange(int)
2115      * @see #requestAudioFocus(OnAudioFocusChangeListener, int, int)
2116      */
2117     public static final int AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK = 3;
2118     /**
2119      * Used to indicate a temporary request of audio focus, anticipated to last a short
2120      * amount of time, during which no other applications, or system components, should play
2121      * anything. Examples of exclusive and transient audio focus requests are voice
2122      * memo recording and speech recognition, during which the system shouldn't play any
2123      * notifications, and media playback should have paused.
2124      * @see #requestAudioFocus(OnAudioFocusChangeListener, int, int)
2125      */
2126     public static final int AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE = 4;
2127     /**
2128      * Used to indicate a loss of audio focus of unknown duration.
2129      * @see OnAudioFocusChangeListener#onAudioFocusChange(int)
2130      */
2131     public static final int AUDIOFOCUS_LOSS = -1 * AUDIOFOCUS_GAIN;
2132     /**
2133      * Used to indicate a transient loss of audio focus.
2134      * @see OnAudioFocusChangeListener#onAudioFocusChange(int)
2135      */
2136     public static final int AUDIOFOCUS_LOSS_TRANSIENT = -1 * AUDIOFOCUS_GAIN_TRANSIENT;
2137     /**
2138      * Used to indicate a transient loss of audio focus where the loser of the audio focus can
2139      * lower its output volume if it wants to continue playing (also referred to as "ducking"), as
2140      * the new focus owner doesn't require others to be silent.
2141      * @see OnAudioFocusChangeListener#onAudioFocusChange(int)
2142      */
2143     public static final int AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK =
2144             -1 * AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK;
2145 
2146     /**
2147      * Interface definition for a callback to be invoked when the audio focus of the system is
2148      * updated.
2149      */
2150     public interface OnAudioFocusChangeListener {
2151         /**
2152          * Called on the listener to notify it the audio focus for this listener has been changed.
2153          * The focusChange value indicates whether the focus was gained,
2154          * whether the focus was lost, and whether that loss is transient, or whether the new focus
2155          * holder will hold it for an unknown amount of time.
2156          * When losing focus, listeners can use the focus change information to decide what
2157          * behavior to adopt when losing focus. A music player could for instance elect to lower
2158          * the volume of its music stream (duck) for transient focus losses, and pause otherwise.
2159          * @param focusChange the type of focus change, one of {@link AudioManager#AUDIOFOCUS_GAIN},
2160          *   {@link AudioManager#AUDIOFOCUS_LOSS}, {@link AudioManager#AUDIOFOCUS_LOSS_TRANSIENT}
2161          *   and {@link AudioManager#AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK}.
2162          */
onAudioFocusChange(int focusChange)2163         public void onAudioFocusChange(int focusChange);
2164     }
2165 
2166     /**
2167      * Map to convert focus event listener IDs, as used in the AudioService audio focus stack,
2168      * to actual listener objects.
2169      */
2170     private final HashMap<String, OnAudioFocusChangeListener> mAudioFocusIdListenerMap =
2171             new HashMap<String, OnAudioFocusChangeListener>();
2172     /**
2173      * Lock to prevent concurrent changes to the list of focus listeners for this AudioManager
2174      * instance.
2175      */
2176     private final Object mFocusListenerLock = new Object();
2177 
findFocusListener(String id)2178     private OnAudioFocusChangeListener findFocusListener(String id) {
2179         return mAudioFocusIdListenerMap.get(id);
2180     }
2181 
2182     /**
2183      * Handler for audio focus events coming from the audio service.
2184      */
2185     private final FocusEventHandlerDelegate mAudioFocusEventHandlerDelegate =
2186             new FocusEventHandlerDelegate();
2187 
2188     /**
2189      * Helper class to handle the forwarding of audio focus events to the appropriate listener
2190      */
2191     private class FocusEventHandlerDelegate {
2192         private final Handler mHandler;
2193 
FocusEventHandlerDelegate()2194         FocusEventHandlerDelegate() {
2195             Looper looper;
2196             if ((looper = Looper.myLooper()) == null) {
2197                 looper = Looper.getMainLooper();
2198             }
2199 
2200             if (looper != null) {
2201                 // implement the event handler delegate to receive audio focus events
2202                 mHandler = new Handler(looper) {
2203                     @Override
2204                     public void handleMessage(Message msg) {
2205                         OnAudioFocusChangeListener listener = null;
2206                         synchronized(mFocusListenerLock) {
2207                             listener = findFocusListener((String)msg.obj);
2208                         }
2209                         if (listener != null) {
2210                             listener.onAudioFocusChange(msg.what);
2211                         }
2212                     }
2213                 };
2214             } else {
2215                 mHandler = null;
2216             }
2217         }
2218 
getHandler()2219         Handler getHandler() {
2220             return mHandler;
2221         }
2222     }
2223 
2224     private final IAudioFocusDispatcher mAudioFocusDispatcher = new IAudioFocusDispatcher.Stub() {
2225 
2226         public void dispatchAudioFocusChange(int focusChange, String id) {
2227             Message m = mAudioFocusEventHandlerDelegate.getHandler().obtainMessage(focusChange, id);
2228             mAudioFocusEventHandlerDelegate.getHandler().sendMessage(m);
2229         }
2230 
2231     };
2232 
getIdForAudioFocusListener(OnAudioFocusChangeListener l)2233     private String getIdForAudioFocusListener(OnAudioFocusChangeListener l) {
2234         if (l == null) {
2235             return new String(this.toString());
2236         } else {
2237             return new String(this.toString() + l.toString());
2238         }
2239     }
2240 
2241     /**
2242      * @hide
2243      * Registers a listener to be called when audio focus changes. Calling this method is optional
2244      * before calling {@link #requestAudioFocus(OnAudioFocusChangeListener, int, int)}, as it
2245      * will register the listener as well if it wasn't registered already.
2246      * @param l the listener to be notified of audio focus changes.
2247      */
registerAudioFocusListener(OnAudioFocusChangeListener l)2248     public void registerAudioFocusListener(OnAudioFocusChangeListener l) {
2249         synchronized(mFocusListenerLock) {
2250             if (mAudioFocusIdListenerMap.containsKey(getIdForAudioFocusListener(l))) {
2251                 return;
2252             }
2253             mAudioFocusIdListenerMap.put(getIdForAudioFocusListener(l), l);
2254         }
2255     }
2256 
2257     /**
2258      * @hide
2259      * Causes the specified listener to not be called anymore when focus is gained or lost.
2260      * @param l the listener to unregister.
2261      */
unregisterAudioFocusListener(OnAudioFocusChangeListener l)2262     public void unregisterAudioFocusListener(OnAudioFocusChangeListener l) {
2263 
2264         // remove locally
2265         synchronized(mFocusListenerLock) {
2266             mAudioFocusIdListenerMap.remove(getIdForAudioFocusListener(l));
2267         }
2268     }
2269 
2270 
2271     /**
2272      * A failed focus change request.
2273      */
2274     public static final int AUDIOFOCUS_REQUEST_FAILED = 0;
2275     /**
2276      * A successful focus change request.
2277      */
2278     public static final int AUDIOFOCUS_REQUEST_GRANTED = 1;
2279 
2280 
2281     /**
2282      *  Request audio focus.
2283      *  Send a request to obtain the audio focus
2284      *  @param l the listener to be notified of audio focus changes
2285      *  @param streamType the main audio stream type affected by the focus request
2286      *  @param durationHint use {@link #AUDIOFOCUS_GAIN_TRANSIENT} to indicate this focus request
2287      *      is temporary, and focus will be abandonned shortly. Examples of transient requests are
2288      *      for the playback of driving directions, or notifications sounds.
2289      *      Use {@link #AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK} to indicate also that it's ok for
2290      *      the previous focus owner to keep playing if it ducks its audio output.
2291      *      Alternatively use {@link #AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE} for a temporary request
2292      *      that benefits from the system not playing disruptive sounds like notifications, for
2293      *      usecases such as voice memo recording, or speech recognition.
2294      *      Use {@link #AUDIOFOCUS_GAIN} for a focus request of unknown duration such
2295      *      as the playback of a song or a video.
2296      *  @return {@link #AUDIOFOCUS_REQUEST_FAILED} or {@link #AUDIOFOCUS_REQUEST_GRANTED}
2297      */
requestAudioFocus(OnAudioFocusChangeListener l, int streamType, int durationHint)2298     public int requestAudioFocus(OnAudioFocusChangeListener l, int streamType, int durationHint) {
2299         int status = AUDIOFOCUS_REQUEST_FAILED;
2300         if ((durationHint < AUDIOFOCUS_GAIN) ||
2301                 (durationHint > AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE)) {
2302             Log.e(TAG, "Invalid duration hint, audio focus request denied");
2303             return status;
2304         }
2305         registerAudioFocusListener(l);
2306         //TODO protect request by permission check?
2307         IAudioService service = getService();
2308         try {
2309             status = service.requestAudioFocus(streamType, durationHint, mICallBack,
2310                     mAudioFocusDispatcher, getIdForAudioFocusListener(l),
2311                     mContext.getOpPackageName() /* package name */);
2312         } catch (RemoteException e) {
2313             Log.e(TAG, "Can't call requestAudioFocus() on AudioService due to "+e);
2314         }
2315         return status;
2316     }
2317 
2318     /**
2319      * @hide
2320      * Used internally by telephony package to request audio focus. Will cause the focus request
2321      * to be associated with the "voice communication" identifier only used in AudioService
2322      * to identify this use case.
2323      * @param streamType use STREAM_RING for focus requests when ringing, VOICE_CALL for
2324      *    the establishment of the call
2325      * @param durationHint the type of focus request. AUDIOFOCUS_GAIN_TRANSIENT is recommended so
2326      *    media applications resume after a call
2327      */
requestAudioFocusForCall(int streamType, int durationHint)2328     public void requestAudioFocusForCall(int streamType, int durationHint) {
2329         IAudioService service = getService();
2330         try {
2331             service.requestAudioFocus(streamType, durationHint, mICallBack, null,
2332                     MediaFocusControl.IN_VOICE_COMM_FOCUS_ID,
2333                     mContext.getOpPackageName());
2334         } catch (RemoteException e) {
2335             Log.e(TAG, "Can't call requestAudioFocusForCall() on AudioService due to "+e);
2336         }
2337     }
2338 
2339     /**
2340      * @hide
2341      * Used internally by telephony package to abandon audio focus, typically after a call or
2342      * when ringing ends and the call is rejected or not answered.
2343      * Should match one or more calls to {@link #requestAudioFocusForCall(int, int)}.
2344      */
abandonAudioFocusForCall()2345     public void abandonAudioFocusForCall() {
2346         IAudioService service = getService();
2347         try {
2348             service.abandonAudioFocus(null, MediaFocusControl.IN_VOICE_COMM_FOCUS_ID);
2349         } catch (RemoteException e) {
2350             Log.e(TAG, "Can't call abandonAudioFocusForCall() on AudioService due to "+e);
2351         }
2352     }
2353 
2354     /**
2355      *  Abandon audio focus. Causes the previous focus owner, if any, to receive focus.
2356      *  @param l the listener with which focus was requested.
2357      *  @return {@link #AUDIOFOCUS_REQUEST_FAILED} or {@link #AUDIOFOCUS_REQUEST_GRANTED}
2358      */
abandonAudioFocus(OnAudioFocusChangeListener l)2359     public int abandonAudioFocus(OnAudioFocusChangeListener l) {
2360         int status = AUDIOFOCUS_REQUEST_FAILED;
2361         unregisterAudioFocusListener(l);
2362         IAudioService service = getService();
2363         try {
2364             status = service.abandonAudioFocus(mAudioFocusDispatcher,
2365                     getIdForAudioFocusListener(l));
2366         } catch (RemoteException e) {
2367             Log.e(TAG, "Can't call abandonAudioFocus() on AudioService due to "+e);
2368         }
2369         return status;
2370     }
2371 
2372 
2373     //====================================================================
2374     // Remote Control
2375     /**
2376      * Register a component to be the sole receiver of MEDIA_BUTTON intents.
2377      * @param eventReceiver identifier of a {@link android.content.BroadcastReceiver}
2378      *      that will receive the media button intent. This broadcast receiver must be declared
2379      *      in the application manifest. The package of the component must match that of
2380      *      the context you're registering from.
2381      * @deprecated Use {@link MediaSession#setMediaButtonReceiver(PendingIntent)} instead.
2382      */
2383     @Deprecated
registerMediaButtonEventReceiver(ComponentName eventReceiver)2384     public void registerMediaButtonEventReceiver(ComponentName eventReceiver) {
2385         if (eventReceiver == null) {
2386             return;
2387         }
2388         if (!eventReceiver.getPackageName().equals(mContext.getPackageName())) {
2389             Log.e(TAG, "registerMediaButtonEventReceiver() error: " +
2390                     "receiver and context package names don't match");
2391             return;
2392         }
2393         // construct a PendingIntent for the media button and register it
2394         Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
2395         //     the associated intent will be handled by the component being registered
2396         mediaButtonIntent.setComponent(eventReceiver);
2397         PendingIntent pi = PendingIntent.getBroadcast(mContext,
2398                 0/*requestCode, ignored*/, mediaButtonIntent, 0/*flags*/);
2399         registerMediaButtonIntent(pi, eventReceiver);
2400     }
2401 
2402     /**
2403      * Register a component to be the sole receiver of MEDIA_BUTTON intents.  This is like
2404      * {@link #registerMediaButtonEventReceiver(android.content.ComponentName)}, but allows
2405      * the buttons to go to any PendingIntent.  Note that you should only use this form if
2406      * you know you will continue running for the full time until unregistering the
2407      * PendingIntent.
2408      * @param eventReceiver target that will receive media button intents.  The PendingIntent
2409      * will be sent an {@link Intent#ACTION_MEDIA_BUTTON} event when a media button action
2410      * occurs, with {@link Intent#EXTRA_KEY_EVENT} added and holding the key code of the
2411      * media button that was pressed.
2412      * @deprecated Use {@link MediaSession#setMediaButtonReceiver(PendingIntent)} instead.
2413      */
2414     @Deprecated
registerMediaButtonEventReceiver(PendingIntent eventReceiver)2415     public void registerMediaButtonEventReceiver(PendingIntent eventReceiver) {
2416         if (eventReceiver == null) {
2417             return;
2418         }
2419         registerMediaButtonIntent(eventReceiver, null);
2420     }
2421 
2422     /**
2423      * @hide
2424      * no-op if (pi == null) or (eventReceiver == null)
2425      */
registerMediaButtonIntent(PendingIntent pi, ComponentName eventReceiver)2426     public void registerMediaButtonIntent(PendingIntent pi, ComponentName eventReceiver) {
2427         if (pi == null) {
2428             Log.e(TAG, "Cannot call registerMediaButtonIntent() with a null parameter");
2429             return;
2430         }
2431         MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mContext);
2432         helper.addMediaButtonListener(pi, eventReceiver, mContext);
2433     }
2434 
2435     /**
2436      * Unregister the receiver of MEDIA_BUTTON intents.
2437      * @param eventReceiver identifier of a {@link android.content.BroadcastReceiver}
2438      *      that was registered with {@link #registerMediaButtonEventReceiver(ComponentName)}.
2439      * @deprecated Use {@link MediaSession} instead.
2440      */
2441     @Deprecated
unregisterMediaButtonEventReceiver(ComponentName eventReceiver)2442     public void unregisterMediaButtonEventReceiver(ComponentName eventReceiver) {
2443         if (eventReceiver == null) {
2444             return;
2445         }
2446         // construct a PendingIntent for the media button and unregister it
2447         Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
2448         //     the associated intent will be handled by the component being registered
2449         mediaButtonIntent.setComponent(eventReceiver);
2450         PendingIntent pi = PendingIntent.getBroadcast(mContext,
2451                 0/*requestCode, ignored*/, mediaButtonIntent, 0/*flags*/);
2452         unregisterMediaButtonIntent(pi);
2453     }
2454 
2455     /**
2456      * Unregister the receiver of MEDIA_BUTTON intents.
2457      * @param eventReceiver same PendingIntent that was registed with
2458      *      {@link #registerMediaButtonEventReceiver(PendingIntent)}.
2459      * @deprecated Use {@link MediaSession} instead.
2460      */
2461     @Deprecated
unregisterMediaButtonEventReceiver(PendingIntent eventReceiver)2462     public void unregisterMediaButtonEventReceiver(PendingIntent eventReceiver) {
2463         if (eventReceiver == null) {
2464             return;
2465         }
2466         unregisterMediaButtonIntent(eventReceiver);
2467     }
2468 
2469     /**
2470      * @hide
2471      */
unregisterMediaButtonIntent(PendingIntent pi)2472     public void unregisterMediaButtonIntent(PendingIntent pi) {
2473         MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mContext);
2474         helper.removeMediaButtonListener(pi);
2475     }
2476 
2477     /**
2478      * Registers the remote control client for providing information to display on the remote
2479      * controls.
2480      * @param rcClient The remote control client from which remote controls will receive
2481      *      information to display.
2482      * @see RemoteControlClient
2483      * @deprecated Use {@link MediaSession} instead.
2484      */
2485     @Deprecated
registerRemoteControlClient(RemoteControlClient rcClient)2486     public void registerRemoteControlClient(RemoteControlClient rcClient) {
2487         if ((rcClient == null) || (rcClient.getRcMediaIntent() == null)) {
2488             return;
2489         }
2490         rcClient.registerWithSession(MediaSessionLegacyHelper.getHelper(mContext));
2491     }
2492 
2493     /**
2494      * Unregisters the remote control client that was providing information to display on the
2495      * remote controls.
2496      * @param rcClient The remote control client to unregister.
2497      * @see #registerRemoteControlClient(RemoteControlClient)
2498      * @deprecated Use {@link MediaSession} instead.
2499      */
2500     @Deprecated
unregisterRemoteControlClient(RemoteControlClient rcClient)2501     public void unregisterRemoteControlClient(RemoteControlClient rcClient) {
2502         if ((rcClient == null) || (rcClient.getRcMediaIntent() == null)) {
2503             return;
2504         }
2505         rcClient.unregisterWithSession(MediaSessionLegacyHelper.getHelper(mContext));
2506     }
2507 
2508     /**
2509      * Registers a {@link RemoteController} instance for it to receive media
2510      * metadata updates and playback state information from applications using
2511      * {@link RemoteControlClient}, and control their playback.
2512      * <p>
2513      * Registration requires the {@link OnClientUpdateListener} listener to be
2514      * one of the enabled notification listeners (see
2515      * {@link android.service.notification.NotificationListenerService}).
2516      *
2517      * @param rctlr the object to register.
2518      * @return true if the {@link RemoteController} was successfully registered,
2519      *         false if an error occurred, due to an internal system error, or
2520      *         insufficient permissions.
2521      * @deprecated Use
2522      *             {@link MediaSessionManager#addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, ComponentName)}
2523      *             and {@link MediaController} instead.
2524      */
2525     @Deprecated
registerRemoteController(RemoteController rctlr)2526     public boolean registerRemoteController(RemoteController rctlr) {
2527         if (rctlr == null) {
2528             return false;
2529         }
2530         rctlr.startListeningToSessions();
2531         return true;
2532     }
2533 
2534     /**
2535      * Unregisters a {@link RemoteController}, causing it to no longer receive
2536      * media metadata and playback state information, and no longer be capable
2537      * of controlling playback.
2538      *
2539      * @param rctlr the object to unregister.
2540      * @deprecated Use
2541      *             {@link MediaSessionManager#removeOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener)}
2542      *             instead.
2543      */
2544     @Deprecated
unregisterRemoteController(RemoteController rctlr)2545     public void unregisterRemoteController(RemoteController rctlr) {
2546         if (rctlr == null) {
2547             return;
2548         }
2549         rctlr.stopListeningToSessions();
2550     }
2551 
2552     /**
2553      * @hide
2554      * Registers a remote control display that will be sent information by remote control clients.
2555      * Use this method if your IRemoteControlDisplay is not going to display artwork, otherwise
2556      * use {@link #registerRemoteControlDisplay(IRemoteControlDisplay, int, int)} to pass the
2557      * artwork size directly, or
2558      * {@link #remoteControlDisplayUsesBitmapSize(IRemoteControlDisplay, int, int)} later if artwork
2559      * is not yet needed.
2560      * <p>Registration requires the {@link Manifest.permission#MEDIA_CONTENT_CONTROL} permission.
2561      * @param rcd the IRemoteControlDisplay
2562      */
registerRemoteControlDisplay(IRemoteControlDisplay rcd)2563     public void registerRemoteControlDisplay(IRemoteControlDisplay rcd) {
2564         // passing a negative value for art work width and height as they are unknown at this stage
2565         registerRemoteControlDisplay(rcd, /*w*/-1, /*h*/ -1);
2566     }
2567 
2568     /**
2569      * @hide
2570      * Registers a remote control display that will be sent information by remote control clients.
2571      * <p>Registration requires the {@link Manifest.permission#MEDIA_CONTENT_CONTROL} permission.
2572      * @param rcd
2573      * @param w the maximum width of the expected bitmap. Negative values indicate it is
2574      *   useless to send artwork.
2575      * @param h the maximum height of the expected bitmap. Negative values indicate it is
2576      *   useless to send artwork.
2577      */
registerRemoteControlDisplay(IRemoteControlDisplay rcd, int w, int h)2578     public void registerRemoteControlDisplay(IRemoteControlDisplay rcd, int w, int h) {
2579         if (rcd == null) {
2580             return;
2581         }
2582         IAudioService service = getService();
2583         try {
2584             service.registerRemoteControlDisplay(rcd, w, h);
2585         } catch (RemoteException e) {
2586             Log.e(TAG, "Dead object in registerRemoteControlDisplay " + e);
2587         }
2588     }
2589 
2590     /**
2591      * @hide
2592      * Unregisters a remote control display that was sent information by remote control clients.
2593      * @param rcd
2594      */
unregisterRemoteControlDisplay(IRemoteControlDisplay rcd)2595     public void unregisterRemoteControlDisplay(IRemoteControlDisplay rcd) {
2596         if (rcd == null) {
2597             return;
2598         }
2599         IAudioService service = getService();
2600         try {
2601             service.unregisterRemoteControlDisplay(rcd);
2602         } catch (RemoteException e) {
2603             Log.e(TAG, "Dead object in unregisterRemoteControlDisplay " + e);
2604         }
2605     }
2606 
2607     /**
2608      * @hide
2609      * Sets the artwork size a remote control display expects when receiving bitmaps.
2610      * @param rcd
2611      * @param w the maximum width of the expected bitmap. Negative values indicate it is
2612      *   useless to send artwork.
2613      * @param h the maximum height of the expected bitmap. Negative values indicate it is
2614      *   useless to send artwork.
2615      */
remoteControlDisplayUsesBitmapSize(IRemoteControlDisplay rcd, int w, int h)2616     public void remoteControlDisplayUsesBitmapSize(IRemoteControlDisplay rcd, int w, int h) {
2617         if (rcd == null) {
2618             return;
2619         }
2620         IAudioService service = getService();
2621         try {
2622             service.remoteControlDisplayUsesBitmapSize(rcd, w, h);
2623         } catch (RemoteException e) {
2624             Log.e(TAG, "Dead object in remoteControlDisplayUsesBitmapSize " + e);
2625         }
2626     }
2627 
2628     /**
2629      * @hide
2630      * Controls whether a remote control display needs periodic checks of the RemoteControlClient
2631      * playback position to verify that the estimated position has not drifted from the actual
2632      * position. By default the check is not performed.
2633      * The IRemoteControlDisplay must have been previously registered for this to have any effect.
2634      * @param rcd the IRemoteControlDisplay for which the anti-drift mechanism will be enabled
2635      *     or disabled. No effect is null.
2636      * @param wantsSync if true, RemoteControlClient instances which expose their playback position
2637      *     to the framework will regularly compare the estimated playback position with the actual
2638      *     position, and will update the IRemoteControlDisplay implementation whenever a drift is
2639      *     detected.
2640      */
remoteControlDisplayWantsPlaybackPositionSync(IRemoteControlDisplay rcd, boolean wantsSync)2641     public void remoteControlDisplayWantsPlaybackPositionSync(IRemoteControlDisplay rcd,
2642             boolean wantsSync) {
2643         if (rcd == null) {
2644             return;
2645         }
2646         IAudioService service = getService();
2647         try {
2648             service.remoteControlDisplayWantsPlaybackPositionSync(rcd, wantsSync);
2649         } catch (RemoteException e) {
2650             Log.e(TAG, "Dead object in remoteControlDisplayWantsPlaybackPositionSync " + e);
2651         }
2652     }
2653 
2654     /**
2655      * @hide
2656      * CANDIDATE FOR PUBLIC API
2657      * Register the given {@link AudioPolicy}.
2658      * This call is synchronous and blocks until the registration process successfully completed
2659      * or failed to complete.
2660      * @param policy the {@link AudioPolicy} to register.
2661      * @return {@link #ERROR} if there was an error communicating with the registration service
2662      *    or if the user doesn't have the required
2663      *    {@link android.Manifest.permission#MODIFY_AUDIO_ROUTING} permission,
2664      *    {@link #SUCCESS} otherwise.
2665      */
registerAudioPolicy(AudioPolicy policy)2666     public int registerAudioPolicy(AudioPolicy policy) {
2667         if (policy == null) {
2668             throw new IllegalArgumentException("Illegal null AudioPolicy argument");
2669         }
2670         IAudioService service = getService();
2671         try {
2672             if (!service.registerAudioPolicy(policy.getConfig(), policy.token())) {
2673                 return ERROR;
2674             }
2675         } catch (RemoteException e) {
2676             Log.e(TAG, "Dead object in registerAudioPolicyAsync()", e);
2677             return ERROR;
2678         }
2679         return SUCCESS;
2680     }
2681 
2682     /**
2683      * @hide
2684      * CANDIDATE FOR PUBLIC API
2685      * @param policy the {@link AudioPolicy} to unregister.
2686      */
unregisterAudioPolicyAsync(AudioPolicy policy)2687     public void unregisterAudioPolicyAsync(AudioPolicy policy) {
2688         if (policy == null) {
2689             throw new IllegalArgumentException("Illegal null AudioPolicy argument");
2690         }
2691         IAudioService service = getService();
2692         try {
2693             service.unregisterAudioPolicyAsync(policy.token());
2694         } catch (RemoteException e) {
2695             Log.e(TAG, "Dead object in unregisterAudioPolicyAsync()", e);
2696         }
2697     }
2698 
2699 
2700     /**
2701      *  @hide
2702      *  Reload audio settings. This method is called by Settings backup
2703      *  agent when audio settings are restored and causes the AudioService
2704      *  to read and apply restored settings.
2705      */
reloadAudioSettings()2706     public void reloadAudioSettings() {
2707         IAudioService service = getService();
2708         try {
2709             service.reloadAudioSettings();
2710         } catch (RemoteException e) {
2711             Log.e(TAG, "Dead object in reloadAudioSettings"+e);
2712         }
2713     }
2714 
2715     /**
2716      * @hide
2717      * Notifies AudioService that it is connected to an A2DP device that supports absolute volume,
2718      * so that AudioService can send volume change events to the A2DP device, rather than handling
2719      * them.
2720      */
avrcpSupportsAbsoluteVolume(String address, boolean support)2721     public void avrcpSupportsAbsoluteVolume(String address, boolean support) {
2722         IAudioService service = getService();
2723         try {
2724             service.avrcpSupportsAbsoluteVolume(address, support);
2725         } catch (RemoteException e) {
2726             Log.e(TAG, "Dead object in avrcpSupportsAbsoluteVolume", e);
2727         }
2728     }
2729 
2730      /**
2731       * {@hide}
2732       */
2733      private final IBinder mICallBack = new Binder();
2734 
2735     /**
2736      * Checks whether the phone is in silent mode, with or without vibrate.
2737      *
2738      * @return true if phone is in silent mode, with or without vibrate.
2739      *
2740      * @see #getRingerMode()
2741      *
2742      * @hide pending API Council approval
2743      */
isSilentMode()2744     public boolean isSilentMode() {
2745         int ringerMode = getRingerMode();
2746         boolean silentMode =
2747             (ringerMode == RINGER_MODE_SILENT) ||
2748             (ringerMode == RINGER_MODE_VIBRATE);
2749         return silentMode;
2750     }
2751 
2752     // This section re-defines new output device constants from AudioSystem, because the AudioSystem
2753     // class is not used by other parts of the framework, which instead use definitions and methods
2754     // from AudioManager. AudioSystem is an internal class used by AudioManager and AudioService.
2755 
2756     /** @hide
2757      * The audio device code for representing "no device." */
2758     public static final int DEVICE_NONE = AudioSystem.DEVICE_NONE;
2759     /** @hide
2760      *  The audio output device code for the small speaker at the front of the device used
2761      *  when placing calls.  Does not refer to an in-ear headphone without attached microphone,
2762      *  such as earbuds, earphones, or in-ear monitors (IEM). Those would be handled as a
2763      *  {@link #DEVICE_OUT_WIRED_HEADPHONE}.
2764      */
2765     public static final int DEVICE_OUT_EARPIECE = AudioSystem.DEVICE_OUT_EARPIECE;
2766     /** @hide
2767      *  The audio output device code for the built-in speaker */
2768     public static final int DEVICE_OUT_SPEAKER = AudioSystem.DEVICE_OUT_SPEAKER;
2769     /** @hide
2770      * The audio output device code for a wired headset with attached microphone */
2771     public static final int DEVICE_OUT_WIRED_HEADSET = AudioSystem.DEVICE_OUT_WIRED_HEADSET;
2772     /** @hide
2773      * The audio output device code for a wired headphone without attached microphone */
2774     public static final int DEVICE_OUT_WIRED_HEADPHONE = AudioSystem.DEVICE_OUT_WIRED_HEADPHONE;
2775     /** @hide
2776      * The audio output device code for generic Bluetooth SCO, for voice */
2777     public static final int DEVICE_OUT_BLUETOOTH_SCO = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO;
2778     /** @hide
2779      * The audio output device code for Bluetooth SCO Headset Profile (HSP) and
2780      * Hands-Free Profile (HFP), for voice
2781      */
2782     public static final int DEVICE_OUT_BLUETOOTH_SCO_HEADSET =
2783             AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
2784     /** @hide
2785      * The audio output device code for Bluetooth SCO car audio, for voice */
2786     public static final int DEVICE_OUT_BLUETOOTH_SCO_CARKIT =
2787             AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
2788     /** @hide
2789      * The audio output device code for generic Bluetooth A2DP, for music */
2790     public static final int DEVICE_OUT_BLUETOOTH_A2DP = AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP;
2791     /** @hide
2792      * The audio output device code for Bluetooth A2DP headphones, for music */
2793     public static final int DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES =
2794             AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
2795     /** @hide
2796      * The audio output device code for Bluetooth A2DP external speaker, for music */
2797     public static final int DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER =
2798             AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
2799     /** @hide
2800      * The audio output device code for S/PDIF (legacy) or HDMI
2801      * Deprecated: replaced by {@link #DEVICE_OUT_HDMI} */
2802     public static final int DEVICE_OUT_AUX_DIGITAL = AudioSystem.DEVICE_OUT_AUX_DIGITAL;
2803     /** @hide
2804      * The audio output device code for HDMI */
2805     public static final int DEVICE_OUT_HDMI = AudioSystem.DEVICE_OUT_HDMI;
2806     /** @hide
2807      * The audio output device code for an analog wired headset attached via a
2808      *  docking station
2809      */
2810     public static final int DEVICE_OUT_ANLG_DOCK_HEADSET = AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET;
2811     /** @hide
2812      * The audio output device code for a digital wired headset attached via a
2813      *  docking station
2814      */
2815     public static final int DEVICE_OUT_DGTL_DOCK_HEADSET = AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET;
2816     /** @hide
2817      * The audio output device code for a USB audio accessory. The accessory is in USB host
2818      * mode and the Android device in USB device mode
2819      */
2820     public static final int DEVICE_OUT_USB_ACCESSORY = AudioSystem.DEVICE_OUT_USB_ACCESSORY;
2821     /** @hide
2822      * The audio output device code for a USB audio device. The device is in USB device
2823      * mode and the Android device in USB host mode
2824      */
2825     public static final int DEVICE_OUT_USB_DEVICE = AudioSystem.DEVICE_OUT_USB_DEVICE;
2826     /** @hide
2827      * The audio output device code for projection output.
2828      */
2829     public static final int DEVICE_OUT_REMOTE_SUBMIX = AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
2830     /** @hide
2831      * The audio output device code the telephony voice TX path.
2832      */
2833     public static final int DEVICE_OUT_TELEPHONY_TX = AudioSystem.DEVICE_OUT_TELEPHONY_TX;
2834     /** @hide
2835      * The audio output device code for an analog jack with line impedance detected.
2836      */
2837     public static final int DEVICE_OUT_LINE = AudioSystem.DEVICE_OUT_LINE;
2838     /** @hide
2839      * The audio output device code for HDMI Audio Return Channel.
2840      */
2841     public static final int DEVICE_OUT_HDMI_ARC = AudioSystem.DEVICE_OUT_HDMI_ARC;
2842     /** @hide
2843      * The audio output device code for S/PDIF digital connection.
2844      */
2845     public static final int DEVICE_OUT_SPDIF = AudioSystem.DEVICE_OUT_SPDIF;
2846     /** @hide
2847      * The audio output device code for built-in FM transmitter.
2848      */
2849     public static final int DEVICE_OUT_FM = AudioSystem.DEVICE_OUT_FM;
2850     /** @hide
2851      * This is not used as a returned value from {@link #getDevicesForStream}, but could be
2852      *  used in the future in a set method to select whatever default device is chosen by the
2853      *  platform-specific implementation.
2854      */
2855     public static final int DEVICE_OUT_DEFAULT = AudioSystem.DEVICE_OUT_DEFAULT;
2856 
2857     /** @hide
2858      * The audio input device code for default built-in microphone
2859      */
2860     public static final int DEVICE_IN_BUILTIN_MIC = AudioSystem.DEVICE_IN_BUILTIN_MIC;
2861     /** @hide
2862      * The audio input device code for a Bluetooth SCO headset
2863      */
2864     public static final int DEVICE_IN_BLUETOOTH_SCO_HEADSET =
2865                                     AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET;
2866     /** @hide
2867      * The audio input device code for wired headset microphone
2868      */
2869     public static final int DEVICE_IN_WIRED_HEADSET =
2870                                     AudioSystem.DEVICE_IN_WIRED_HEADSET;
2871     /** @hide
2872      * The audio input device code for HDMI
2873      */
2874     public static final int DEVICE_IN_HDMI =
2875                                     AudioSystem.DEVICE_IN_HDMI;
2876     /** @hide
2877      * The audio input device code for telephony voice RX path
2878      */
2879     public static final int DEVICE_IN_TELEPHONY_RX =
2880                                     AudioSystem.DEVICE_IN_TELEPHONY_RX;
2881     /** @hide
2882      * The audio input device code for built-in microphone pointing to the back
2883      */
2884     public static final int DEVICE_IN_BACK_MIC =
2885                                     AudioSystem.DEVICE_IN_BACK_MIC;
2886     /** @hide
2887      * The audio input device code for analog from a docking station
2888      */
2889     public static final int DEVICE_IN_ANLG_DOCK_HEADSET =
2890                                     AudioSystem.DEVICE_IN_ANLG_DOCK_HEADSET;
2891     /** @hide
2892      * The audio input device code for digital from a docking station
2893      */
2894     public static final int DEVICE_IN_DGTL_DOCK_HEADSET =
2895                                     AudioSystem.DEVICE_IN_DGTL_DOCK_HEADSET;
2896     /** @hide
2897      * The audio input device code for a USB audio accessory. The accessory is in USB host
2898      * mode and the Android device in USB device mode
2899      */
2900     public static final int DEVICE_IN_USB_ACCESSORY =
2901                                     AudioSystem.DEVICE_IN_USB_ACCESSORY;
2902     /** @hide
2903      * The audio input device code for a USB audio device. The device is in USB device
2904      * mode and the Android device in USB host mode
2905      */
2906     public static final int DEVICE_IN_USB_DEVICE =
2907                                     AudioSystem.DEVICE_IN_USB_DEVICE;
2908     /** @hide
2909      * The audio input device code for a FM radio tuner
2910      */
2911     public static final int DEVICE_IN_FM_TUNER = AudioSystem.DEVICE_IN_FM_TUNER;
2912     /** @hide
2913      * The audio input device code for a TV tuner
2914      */
2915     public static final int DEVICE_IN_TV_TUNER = AudioSystem.DEVICE_IN_TV_TUNER;
2916     /** @hide
2917      * The audio input device code for an analog jack with line impedance detected
2918      */
2919     public static final int DEVICE_IN_LINE = AudioSystem.DEVICE_IN_LINE;
2920     /** @hide
2921      * The audio input device code for a S/PDIF digital connection
2922      */
2923     public static final int DEVICE_IN_SPDIF = AudioSystem.DEVICE_IN_SPDIF;
2924     /** @hide
2925      * The audio input device code for audio loopback
2926      */
2927     public static final int DEVICE_IN_LOOPBACK = AudioSystem.DEVICE_IN_LOOPBACK;
2928 
2929     /**
2930      * Return true if the device code corresponds to an output device.
2931      * @hide
2932      */
isOutputDevice(int device)2933     public static boolean isOutputDevice(int device)
2934     {
2935         return (device & AudioSystem.DEVICE_BIT_IN) == 0;
2936     }
2937 
2938     /**
2939      * Return true if the device code corresponds to an input device.
2940      * @hide
2941      */
isInputDevice(int device)2942     public static boolean isInputDevice(int device)
2943     {
2944         return (device & AudioSystem.DEVICE_BIT_IN) == AudioSystem.DEVICE_BIT_IN;
2945     }
2946 
2947 
2948     /**
2949      * Return the enabled devices for the specified output stream type.
2950      *
2951      * @param streamType The stream type to query. One of
2952      *            {@link #STREAM_VOICE_CALL},
2953      *            {@link #STREAM_SYSTEM},
2954      *            {@link #STREAM_RING},
2955      *            {@link #STREAM_MUSIC},
2956      *            {@link #STREAM_ALARM},
2957      *            {@link #STREAM_NOTIFICATION},
2958      *            {@link #STREAM_DTMF}.
2959      *
2960      * @return The bit-mask "or" of audio output device codes for all enabled devices on this
2961      *         stream. Zero or more of
2962      *            {@link #DEVICE_OUT_EARPIECE},
2963      *            {@link #DEVICE_OUT_SPEAKER},
2964      *            {@link #DEVICE_OUT_WIRED_HEADSET},
2965      *            {@link #DEVICE_OUT_WIRED_HEADPHONE},
2966      *            {@link #DEVICE_OUT_BLUETOOTH_SCO},
2967      *            {@link #DEVICE_OUT_BLUETOOTH_SCO_HEADSET},
2968      *            {@link #DEVICE_OUT_BLUETOOTH_SCO_CARKIT},
2969      *            {@link #DEVICE_OUT_BLUETOOTH_A2DP},
2970      *            {@link #DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES},
2971      *            {@link #DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER},
2972      *            {@link #DEVICE_OUT_HDMI},
2973      *            {@link #DEVICE_OUT_ANLG_DOCK_HEADSET},
2974      *            {@link #DEVICE_OUT_DGTL_DOCK_HEADSET}.
2975      *            {@link #DEVICE_OUT_USB_ACCESSORY}.
2976      *            {@link #DEVICE_OUT_USB_DEVICE}.
2977      *            {@link #DEVICE_OUT_REMOTE_SUBMIX}.
2978      *            {@link #DEVICE_OUT_TELEPHONY_TX}.
2979      *            {@link #DEVICE_OUT_LINE}.
2980      *            {@link #DEVICE_OUT_HDMI_ARC}.
2981      *            {@link #DEVICE_OUT_SPDIF}.
2982      *            {@link #DEVICE_OUT_FM}.
2983      *            {@link #DEVICE_OUT_DEFAULT} is not used here.
2984      *
2985      * The implementation may support additional device codes beyond those listed, so
2986      * the application should ignore any bits which it does not recognize.
2987      * Note that the information may be imprecise when the implementation
2988      * cannot distinguish whether a particular device is enabled.
2989      *
2990      * {@hide}
2991      */
getDevicesForStream(int streamType)2992     public int getDevicesForStream(int streamType) {
2993         switch (streamType) {
2994         case STREAM_VOICE_CALL:
2995         case STREAM_SYSTEM:
2996         case STREAM_RING:
2997         case STREAM_MUSIC:
2998         case STREAM_ALARM:
2999         case STREAM_NOTIFICATION:
3000         case STREAM_DTMF:
3001             return AudioSystem.getDevicesForStream(streamType);
3002         default:
3003             return 0;
3004         }
3005     }
3006 
3007      /**
3008      * Indicate wired accessory connection state change.
3009      * @param device type of device connected/disconnected (AudioManager.DEVICE_OUT_xxx)
3010      * @param state  new connection state: 1 connected, 0 disconnected
3011      * @param name   device name
3012      * {@hide}
3013      */
setWiredDeviceConnectionState(int device, int state, String name)3014     public void setWiredDeviceConnectionState(int device, int state, String name) {
3015         IAudioService service = getService();
3016         try {
3017             service.setWiredDeviceConnectionState(device, state, name);
3018         } catch (RemoteException e) {
3019             Log.e(TAG, "Dead object in setWiredDeviceConnectionState "+e);
3020         }
3021     }
3022 
3023      /**
3024      * Indicate A2DP source or sink connection state change.
3025      * @param device Bluetooth device connected/disconnected
3026      * @param state  new connection state (BluetoothProfile.STATE_xxx)
3027      * @param profile profile for the A2DP device
3028      * (either {@link android.bluetooth.BluetoothProfile.A2DP} or
3029      * {@link android.bluetooth.BluetoothProfile.A2DP_SINK})
3030      * @return a delay in ms that the caller should wait before broadcasting
3031      * BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED intent.
3032      * {@hide}
3033      */
setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state, int profile)3034     public int setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state,
3035             int profile) {
3036         IAudioService service = getService();
3037         int delay = 0;
3038         try {
3039             delay = service.setBluetoothA2dpDeviceConnectionState(device, state, profile);
3040         } catch (RemoteException e) {
3041             Log.e(TAG, "Dead object in setBluetoothA2dpDeviceConnectionState "+e);
3042         } finally {
3043             return delay;
3044         }
3045     }
3046 
3047     /** {@hide} */
getRingtonePlayer()3048     public IRingtonePlayer getRingtonePlayer() {
3049         try {
3050             return getService().getRingtonePlayer();
3051         } catch (RemoteException e) {
3052             return null;
3053         }
3054     }
3055 
3056     /**
3057      * Used as a key for {@link #getProperty} to request the native or optimal output sample rate
3058      * for this device's primary output stream, in decimal Hz.
3059      */
3060     public static final String PROPERTY_OUTPUT_SAMPLE_RATE =
3061             "android.media.property.OUTPUT_SAMPLE_RATE";
3062 
3063     /**
3064      * Used as a key for {@link #getProperty} to request the native or optimal output buffer size
3065      * for this device's primary output stream, in decimal PCM frames.
3066      */
3067     public static final String PROPERTY_OUTPUT_FRAMES_PER_BUFFER =
3068             "android.media.property.OUTPUT_FRAMES_PER_BUFFER";
3069 
3070     /**
3071      * Returns the value of the property with the specified key.
3072      * @param key One of the strings corresponding to a property key: either
3073      *            {@link #PROPERTY_OUTPUT_SAMPLE_RATE} or
3074      *            {@link #PROPERTY_OUTPUT_FRAMES_PER_BUFFER}
3075      * @return A string representing the associated value for that property key,
3076      *         or null if there is no value for that key.
3077      */
getProperty(String key)3078     public String getProperty(String key) {
3079         if (PROPERTY_OUTPUT_SAMPLE_RATE.equals(key)) {
3080             int outputSampleRate = AudioSystem.getPrimaryOutputSamplingRate();
3081             return outputSampleRate > 0 ? Integer.toString(outputSampleRate) : null;
3082         } else if (PROPERTY_OUTPUT_FRAMES_PER_BUFFER.equals(key)) {
3083             int outputFramesPerBuffer = AudioSystem.getPrimaryOutputFrameCount();
3084             return outputFramesPerBuffer > 0 ? Integer.toString(outputFramesPerBuffer) : null;
3085         } else {
3086             // null or unknown key
3087             return null;
3088         }
3089     }
3090 
3091     /**
3092      * Returns the estimated latency for the given stream type in milliseconds.
3093      *
3094      * DO NOT UNHIDE. The existing approach for doing A/V sync has too many problems. We need
3095      * a better solution.
3096      * @hide
3097      */
getOutputLatency(int streamType)3098     public int getOutputLatency(int streamType) {
3099         return AudioSystem.getOutputLatency(streamType);
3100     }
3101 
3102     /**
3103      * Registers a global volume controller interface.  Currently limited to SystemUI.
3104      *
3105      * @hide
3106      */
setVolumeController(IVolumeController controller)3107     public void setVolumeController(IVolumeController controller) {
3108         try {
3109             getService().setVolumeController(controller);
3110         } catch (RemoteException e) {
3111             Log.w(TAG, "Error setting volume controller", e);
3112         }
3113     }
3114 
3115     /**
3116      * Notify audio manager about volume controller visibility changes.
3117      * Currently limited to SystemUI.
3118      *
3119      * @hide
3120      */
notifyVolumeControllerVisible(IVolumeController controller, boolean visible)3121     public void notifyVolumeControllerVisible(IVolumeController controller, boolean visible) {
3122         try {
3123             getService().notifyVolumeControllerVisible(controller, visible);
3124         } catch (RemoteException e) {
3125             Log.w(TAG, "Error notifying about volume controller visibility", e);
3126         }
3127     }
3128 
3129     /**
3130      * Only useful for volume controllers.
3131      * @hide
3132      */
isStreamAffectedByRingerMode(int streamType)3133     public boolean isStreamAffectedByRingerMode(int streamType) {
3134         try {
3135             return getService().isStreamAffectedByRingerMode(streamType);
3136         } catch (RemoteException e) {
3137             Log.w(TAG, "Error calling isStreamAffectedByRingerMode", e);
3138             return false;
3139         }
3140     }
3141 
3142     /**
3143      * Only useful for volume controllers.
3144      * @hide
3145      */
disableSafeMediaVolume()3146     public void disableSafeMediaVolume() {
3147         try {
3148             getService().disableSafeMediaVolume();
3149         } catch (RemoteException e) {
3150             Log.w(TAG, "Error disabling safe media volume", e);
3151         }
3152     }
3153 
3154     /**
3155      * Set Hdmi Cec system audio mode.
3156      *
3157      * @param on whether to be on system audio mode
3158      * @return output device type. 0 (DEVICE_NONE) if failed to set device.
3159      * @hide
3160      */
setHdmiSystemAudioSupported(boolean on)3161     public int setHdmiSystemAudioSupported(boolean on) {
3162         try {
3163             return getService().setHdmiSystemAudioSupported(on);
3164         } catch (RemoteException e) {
3165             Log.w(TAG, "Error setting system audio mode", e);
3166             return AudioSystem.DEVICE_NONE;
3167         }
3168     }
3169 
3170     /**
3171      * Returns true if Hdmi Cec system audio mode is supported.
3172      *
3173      * @hide
3174      */
3175     @SystemApi
isHdmiSystemAudioSupported()3176     public boolean isHdmiSystemAudioSupported() {
3177         try {
3178             return getService().isHdmiSystemAudioSupported();
3179         } catch (RemoteException e) {
3180             Log.w(TAG, "Error querying system audio mode", e);
3181             return false;
3182         }
3183     }
3184 
3185     /**
3186      * Return codes for listAudioPorts(), createAudioPatch() ...
3187      */
3188 
3189     /** @hide
3190      * CANDIDATE FOR PUBLIC API
3191      */
3192     public static final int SUCCESS = AudioSystem.SUCCESS;
3193     /**
3194      * A default error code.
3195      */
3196     public static final int ERROR = AudioSystem.ERROR;
3197     /** @hide
3198      * CANDIDATE FOR PUBLIC API
3199      */
3200     public static final int ERROR_BAD_VALUE = AudioSystem.BAD_VALUE;
3201     /** @hide
3202      */
3203     public static final int ERROR_INVALID_OPERATION = AudioSystem.INVALID_OPERATION;
3204     /** @hide
3205      */
3206     public static final int ERROR_PERMISSION_DENIED = AudioSystem.PERMISSION_DENIED;
3207     /** @hide
3208      */
3209     public static final int ERROR_NO_INIT = AudioSystem.NO_INIT;
3210     /**
3211      * An error code indicating that the object reporting it is no longer valid and needs to
3212      * be recreated.
3213      */
3214     public static final int ERROR_DEAD_OBJECT = AudioSystem.DEAD_OBJECT;
3215 
3216     /**
3217      * Returns a list of descriptors for all audio ports managed by the audio framework.
3218      * Audio ports are nodes in the audio framework or audio hardware that can be configured
3219      * or connected and disconnected with createAudioPatch() or releaseAudioPatch().
3220      * See AudioPort for a list of attributes of each audio port.
3221      * @param ports An AudioPort ArrayList where the list will be returned.
3222      * @hide
3223      */
listAudioPorts(ArrayList<AudioPort> ports)3224     public int listAudioPorts(ArrayList<AudioPort> ports) {
3225         return updateAudioPortCache(ports, null);
3226     }
3227 
3228     /**
3229      * Specialized version of listAudioPorts() listing only audio devices (AudioDevicePort)
3230      * @see listAudioPorts(ArrayList<AudioPort>)
3231      * @hide
3232      */
listAudioDevicePorts(ArrayList<AudioPort> devices)3233     public int listAudioDevicePorts(ArrayList<AudioPort> devices) {
3234         ArrayList<AudioPort> ports = new ArrayList<AudioPort>();
3235         int status = updateAudioPortCache(ports, null);
3236         if (status == SUCCESS) {
3237             devices.clear();
3238             for (int i = 0; i < ports.size(); i++) {
3239                 if (ports.get(i) instanceof AudioDevicePort) {
3240                     devices.add(ports.get(i));
3241                 }
3242             }
3243         }
3244         return status;
3245     }
3246 
3247     /**
3248      * Create a connection between two or more devices. The framework will reject the request if
3249      * device types are not compatible or the implementation does not support the requested
3250      * configuration.
3251      * NOTE: current implementation is limited to one source and one sink per patch.
3252      * @param patch AudioPatch array where the newly created patch will be returned.
3253      *              As input, if patch[0] is not null, the specified patch will be replaced by the
3254      *              new patch created. This avoids calling releaseAudioPatch() when modifying a
3255      *              patch and allows the implementation to optimize transitions.
3256      * @param sources List of source audio ports. All must be AudioPort.ROLE_SOURCE.
3257      * @param sinks   List of sink audio ports. All must be AudioPort.ROLE_SINK.
3258      *
3259      * @return - {@link #SUCCESS} if connection is successful.
3260      *         - {@link #ERROR_BAD_VALUE} if incompatible device types are passed.
3261      *         - {@link #ERROR_INVALID_OPERATION} if the requested connection is not supported.
3262      *         - {@link #ERROR_PERMISSION_DENIED} if the client does not have permission to create
3263      *         a patch.
3264      *         - {@link #ERROR_DEAD_OBJECT} if the server process is dead
3265      *         - {@link #ERROR} if patch cannot be connected for any other reason.
3266      *
3267      *         patch[0] contains the newly created patch
3268      * @hide
3269      */
createAudioPatch(AudioPatch[] patch, AudioPortConfig[] sources, AudioPortConfig[] sinks)3270     public int createAudioPatch(AudioPatch[] patch,
3271                                  AudioPortConfig[] sources,
3272                                  AudioPortConfig[] sinks) {
3273         return AudioSystem.createAudioPatch(patch, sources, sinks);
3274     }
3275 
3276     /**
3277      * Releases an existing audio patch connection.
3278      * @param patch The audio patch to disconnect.
3279      * @return - {@link #SUCCESS} if disconnection is successful.
3280      *         - {@link #ERROR_BAD_VALUE} if the specified patch does not exist.
3281      *         - {@link #ERROR_PERMISSION_DENIED} if the client does not have permission to release
3282      *         a patch.
3283      *         - {@link #ERROR_DEAD_OBJECT} if the server process is dead
3284      *         - {@link #ERROR} if patch cannot be released for any other reason.
3285      * @hide
3286      */
releaseAudioPatch(AudioPatch patch)3287     public int releaseAudioPatch(AudioPatch patch) {
3288         return AudioSystem.releaseAudioPatch(patch);
3289     }
3290 
3291     /**
3292      * List all existing connections between audio ports.
3293      * @param patches An AudioPatch array where the list will be returned.
3294      * @hide
3295      */
listAudioPatches(ArrayList<AudioPatch> patches)3296     public int listAudioPatches(ArrayList<AudioPatch> patches) {
3297         return updateAudioPortCache(null, patches);
3298     }
3299 
3300     /**
3301      * Set the gain on the specified AudioPort. The AudioGainConfig config is build by
3302      * AudioGain.buildConfig()
3303      * @hide
3304      */
setAudioPortGain(AudioPort port, AudioGainConfig gain)3305     public int setAudioPortGain(AudioPort port, AudioGainConfig gain) {
3306         if (port == null || gain == null) {
3307             return ERROR_BAD_VALUE;
3308         }
3309         AudioPortConfig activeConfig = port.activeConfig();
3310         AudioPortConfig config = new AudioPortConfig(port, activeConfig.samplingRate(),
3311                                         activeConfig.channelMask(), activeConfig.format(), gain);
3312         config.mConfigMask = AudioPortConfig.GAIN;
3313         return AudioSystem.setAudioPortConfig(config);
3314     }
3315 
3316     /**
3317      * Listener registered by client to be notified upon new audio port connections,
3318      * disconnections or attributes update.
3319      * @hide
3320      */
3321     public interface OnAudioPortUpdateListener {
3322         /**
3323          * Callback method called upon audio port list update.
3324          * @param portList the updated list of audio ports
3325          */
onAudioPortListUpdate(AudioPort[] portList)3326         public void onAudioPortListUpdate(AudioPort[] portList);
3327 
3328         /**
3329          * Callback method called upon audio patch list update.
3330          * @param patchList the updated list of audio patches
3331          */
onAudioPatchListUpdate(AudioPatch[] patchList)3332         public void onAudioPatchListUpdate(AudioPatch[] patchList);
3333 
3334         /**
3335          * Callback method called when the mediaserver dies
3336          */
onServiceDied()3337         public void onServiceDied();
3338     }
3339 
3340     /**
3341      * Register an audio port list update listener.
3342      * @hide
3343      */
registerAudioPortUpdateListener(OnAudioPortUpdateListener l)3344     public void registerAudioPortUpdateListener(OnAudioPortUpdateListener l) {
3345         mAudioPortEventHandler.registerListener(l);
3346     }
3347 
3348     /**
3349      * Unregister an audio port list update listener.
3350      * @hide
3351      */
unregisterAudioPortUpdateListener(OnAudioPortUpdateListener l)3352     public void unregisterAudioPortUpdateListener(OnAudioPortUpdateListener l) {
3353         mAudioPortEventHandler.unregisterListener(l);
3354     }
3355 
3356     //
3357     // AudioPort implementation
3358     //
3359 
3360     static final int AUDIOPORT_GENERATION_INIT = 0;
3361     Integer mAudioPortGeneration = new Integer(AUDIOPORT_GENERATION_INIT);
3362     ArrayList<AudioPort> mAudioPortsCached = new ArrayList<AudioPort>();
3363     ArrayList<AudioPatch> mAudioPatchesCached = new ArrayList<AudioPatch>();
3364 
resetAudioPortGeneration()3365     int resetAudioPortGeneration() {
3366         int generation;
3367         synchronized (mAudioPortGeneration) {
3368             generation = mAudioPortGeneration;
3369             mAudioPortGeneration = AUDIOPORT_GENERATION_INIT;
3370         }
3371         return generation;
3372     }
3373 
updateAudioPortCache(ArrayList<AudioPort> ports, ArrayList<AudioPatch> patches)3374     int updateAudioPortCache(ArrayList<AudioPort> ports, ArrayList<AudioPatch> patches) {
3375         synchronized (mAudioPortGeneration) {
3376 
3377             if (mAudioPortGeneration == AUDIOPORT_GENERATION_INIT) {
3378                 int[] patchGeneration = new int[1];
3379                 int[] portGeneration = new int[1];
3380                 int status;
3381                 ArrayList<AudioPort> newPorts = new ArrayList<AudioPort>();
3382                 ArrayList<AudioPatch> newPatches = new ArrayList<AudioPatch>();
3383 
3384                 do {
3385                     newPorts.clear();
3386                     status = AudioSystem.listAudioPorts(newPorts, portGeneration);
3387                     if (status != SUCCESS) {
3388                         return status;
3389                     }
3390                     newPatches.clear();
3391                     status = AudioSystem.listAudioPatches(newPatches, patchGeneration);
3392                     if (status != SUCCESS) {
3393                         return status;
3394                     }
3395                 } while (patchGeneration[0] != portGeneration[0]);
3396 
3397                 for (int i = 0; i < newPatches.size(); i++) {
3398                     for (int j = 0; j < newPatches.get(i).sources().length; j++) {
3399                         AudioPortConfig portCfg = updatePortConfig(newPatches.get(i).sources()[j],
3400                                                                    newPorts);
3401                         if (portCfg == null) {
3402                             return ERROR;
3403                         }
3404                         newPatches.get(i).sources()[j] = portCfg;
3405                     }
3406                     for (int j = 0; j < newPatches.get(i).sinks().length; j++) {
3407                         AudioPortConfig portCfg = updatePortConfig(newPatches.get(i).sinks()[j],
3408                                                                    newPorts);
3409                         if (portCfg == null) {
3410                             return ERROR;
3411                         }
3412                         newPatches.get(i).sinks()[j] = portCfg;
3413                     }
3414                 }
3415 
3416                 mAudioPortsCached = newPorts;
3417                 mAudioPatchesCached = newPatches;
3418                 mAudioPortGeneration = portGeneration[0];
3419             }
3420             if (ports != null) {
3421                 ports.clear();
3422                 ports.addAll(mAudioPortsCached);
3423             }
3424             if (patches != null) {
3425                 patches.clear();
3426                 patches.addAll(mAudioPatchesCached);
3427             }
3428         }
3429         return SUCCESS;
3430     }
3431 
updatePortConfig(AudioPortConfig portCfg, ArrayList<AudioPort> ports)3432     AudioPortConfig updatePortConfig(AudioPortConfig portCfg, ArrayList<AudioPort> ports) {
3433         AudioPort port = portCfg.port();
3434         int k;
3435         for (k = 0; k < ports.size(); k++) {
3436             // compare handles because the port returned by JNI is not of the correct
3437             // subclass
3438             if (ports.get(k).handle().equals(port.handle())) {
3439                 port = ports.get(k);
3440                 break;
3441             }
3442         }
3443         if (k == ports.size()) {
3444             // this hould never happen
3445             Log.e(TAG, "updatePortConfig port not found for handle: "+port.handle().id());
3446             return null;
3447         }
3448         AudioGainConfig gainCfg = portCfg.gain();
3449         if (gainCfg != null) {
3450             AudioGain gain = port.gain(gainCfg.index());
3451             gainCfg = gain.buildConfig(gainCfg.mode(),
3452                                        gainCfg.channelMask(),
3453                                        gainCfg.values(),
3454                                        gainCfg.rampDurationMs());
3455         }
3456         return port.buildConfig(portCfg.samplingRate(),
3457                                                  portCfg.channelMask(),
3458                                                  portCfg.format(),
3459                                                  gainCfg);
3460     }
3461 }
3462