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