Home | History | Annotate | Download | only in media
      1 /*
      2  * Copyright (C) 2006 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 static android.Manifest.permission.REMOTE_AUDIO_PLAYBACK;
     20 import static android.media.AudioManager.RINGER_MODE_NORMAL;
     21 import static android.media.AudioManager.RINGER_MODE_SILENT;
     22 import static android.media.AudioManager.RINGER_MODE_VIBRATE;
     23 
     24 import android.app.ActivityManager;
     25 import android.app.ActivityManagerNative;
     26 import android.app.AppOpsManager;
     27 import android.app.KeyguardManager;
     28 import android.bluetooth.BluetoothA2dp;
     29 import android.bluetooth.BluetoothAdapter;
     30 import android.bluetooth.BluetoothClass;
     31 import android.bluetooth.BluetoothDevice;
     32 import android.bluetooth.BluetoothHeadset;
     33 import android.bluetooth.BluetoothProfile;
     34 import android.content.BroadcastReceiver;
     35 import android.content.ComponentName;
     36 import android.content.ContentResolver;
     37 import android.content.Context;
     38 import android.content.Intent;
     39 import android.content.IntentFilter;
     40 import android.content.pm.PackageManager;
     41 import android.content.res.Configuration;
     42 import android.content.res.Resources;
     43 import android.content.res.XmlResourceParser;
     44 import android.database.ContentObserver;
     45 import android.hardware.hdmi.HdmiControlManager;
     46 import android.hardware.hdmi.HdmiPlaybackClient;
     47 import android.hardware.hdmi.HdmiTvClient;
     48 import android.hardware.usb.UsbManager;
     49 import android.media.MediaPlayer.OnCompletionListener;
     50 import android.media.MediaPlayer.OnErrorListener;
     51 import android.media.audiopolicy.AudioMix;
     52 import android.media.audiopolicy.AudioPolicy;
     53 import android.media.audiopolicy.AudioPolicyConfig;
     54 import android.media.audiopolicy.IAudioPolicyCallback;
     55 import android.os.Binder;
     56 import android.os.Build;
     57 import android.os.Environment;
     58 import android.os.Handler;
     59 import android.os.IBinder;
     60 import android.os.Looper;
     61 import android.os.Message;
     62 import android.os.PowerManager;
     63 import android.os.RemoteCallbackList;
     64 import android.os.RemoteException;
     65 import android.os.SystemClock;
     66 import android.os.SystemProperties;
     67 import android.os.UserHandle;
     68 import android.os.Vibrator;
     69 import android.provider.Settings;
     70 import android.provider.Settings.System;
     71 import android.telecom.TelecomManager;
     72 import android.text.TextUtils;
     73 import android.util.Log;
     74 import android.util.MathUtils;
     75 import android.util.Slog;
     76 import android.view.KeyEvent;
     77 import android.view.OrientationEventListener;
     78 import android.view.Surface;
     79 import android.view.WindowManager;
     80 import android.view.accessibility.AccessibilityManager;
     81 
     82 import com.android.internal.util.XmlUtils;
     83 import com.android.server.LocalServices;
     84 
     85 import org.xmlpull.v1.XmlPullParserException;
     86 
     87 import java.io.FileDescriptor;
     88 import java.io.IOException;
     89 import java.io.PrintWriter;
     90 import java.lang.reflect.Field;
     91 import java.util.ArrayList;
     92 import java.util.HashMap;
     93 import java.util.Iterator;
     94 import java.util.List;
     95 import java.util.Map;
     96 import java.util.NoSuchElementException;
     97 import java.util.Objects;
     98 import java.util.Set;
     99 import java.util.concurrent.ConcurrentHashMap;
    100 
    101 /**
    102  * The implementation of the volume manager service.
    103  * <p>
    104  * This implementation focuses on delivering a responsive UI. Most methods are
    105  * asynchronous to external calls. For example, the task of setting a volume
    106  * will update our internal state, but in a separate thread will set the system
    107  * volume and later persist to the database. Similarly, setting the ringer mode
    108  * will update the state and broadcast a change and in a separate thread later
    109  * persist the ringer mode.
    110  *
    111  * @hide
    112  */
    113 public class AudioService extends IAudioService.Stub {
    114 
    115     private static final String TAG = "AudioService";
    116 
    117     /** Debug audio mode */
    118     protected static final boolean DEBUG_MODE = Log.isLoggable(TAG + ".MOD", Log.DEBUG);
    119 
    120     /** Debug audio policy feature */
    121     protected static final boolean DEBUG_AP = Log.isLoggable(TAG + ".AP", Log.DEBUG);
    122 
    123     /** Debug volumes */
    124     protected static final boolean DEBUG_VOL = Log.isLoggable(TAG + ".VOL", Log.DEBUG);
    125 
    126     /** debug calls to media session apis */
    127     private static final boolean DEBUG_SESSIONS = Log.isLoggable(TAG + ".SESSIONS", Log.DEBUG);
    128 
    129     /** Allow volume changes to set ringer mode to silent? */
    130     private static final boolean VOLUME_SETS_RINGER_MODE_SILENT = false;
    131 
    132     /** In silent mode, are volume adjustments (raises) prevented? */
    133     private static final boolean PREVENT_VOLUME_ADJUSTMENT_IF_SILENT = true;
    134 
    135     /** How long to delay before persisting a change in volume/ringer mode. */
    136     private static final int PERSIST_DELAY = 500;
    137 
    138     /**
    139      * The delay before playing a sound. This small period exists so the user
    140      * can press another key (non-volume keys, too) to have it NOT be audible.
    141      * <p>
    142      * PhoneWindow will implement this part.
    143      */
    144     public static final int PLAY_SOUND_DELAY = 300;
    145 
    146     /**
    147      * Only used in the result from {@link #checkForRingerModeChange(int, int, int)}
    148      */
    149     private static final int FLAG_ADJUST_VOLUME = 1;
    150 
    151     private final Context mContext;
    152     private final ContentResolver mContentResolver;
    153     private final AppOpsManager mAppOps;
    154 
    155     // the platform has no specific capabilities
    156     private static final int PLATFORM_DEFAULT = 0;
    157     // the platform is voice call capable (a phone)
    158     private static final int PLATFORM_VOICE = 1;
    159     // the platform is a television or a set-top box
    160     private static final int PLATFORM_TELEVISION = 2;
    161     // the platform type affects volume and silent mode behavior
    162     private final int mPlatformType;
    163 
    164     private boolean isPlatformVoice() {
    165         return mPlatformType == PLATFORM_VOICE;
    166     }
    167 
    168     private boolean isPlatformTelevision() {
    169         return mPlatformType == PLATFORM_TELEVISION;
    170     }
    171 
    172     /** The controller for the volume UI. */
    173     private final VolumeController mVolumeController = new VolumeController();
    174 
    175     // sendMsg() flags
    176     /** If the msg is already queued, replace it with this one. */
    177     private static final int SENDMSG_REPLACE = 0;
    178     /** If the msg is already queued, ignore this one and leave the old. */
    179     private static final int SENDMSG_NOOP = 1;
    180     /** If the msg is already queued, queue this one and leave the old. */
    181     private static final int SENDMSG_QUEUE = 2;
    182 
    183     // AudioHandler messages
    184     private static final int MSG_SET_DEVICE_VOLUME = 0;
    185     private static final int MSG_PERSIST_VOLUME = 1;
    186     private static final int MSG_PERSIST_MASTER_VOLUME = 2;
    187     private static final int MSG_PERSIST_RINGER_MODE = 3;
    188     private static final int MSG_MEDIA_SERVER_DIED = 4;
    189     private static final int MSG_PLAY_SOUND_EFFECT = 5;
    190     private static final int MSG_BTA2DP_DOCK_TIMEOUT = 6;
    191     private static final int MSG_LOAD_SOUND_EFFECTS = 7;
    192     private static final int MSG_SET_FORCE_USE = 8;
    193     private static final int MSG_BT_HEADSET_CNCT_FAILED = 9;
    194     private static final int MSG_SET_ALL_VOLUMES = 10;
    195     private static final int MSG_PERSIST_MASTER_VOLUME_MUTE = 11;
    196     private static final int MSG_REPORT_NEW_ROUTES = 12;
    197     private static final int MSG_SET_FORCE_BT_A2DP_USE = 13;
    198     private static final int MSG_CHECK_MUSIC_ACTIVE = 14;
    199     private static final int MSG_BROADCAST_AUDIO_BECOMING_NOISY = 15;
    200     private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME = 16;
    201     private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED = 17;
    202     private static final int MSG_PERSIST_SAFE_VOLUME_STATE = 18;
    203     private static final int MSG_BROADCAST_BT_CONNECTION_STATE = 19;
    204     private static final int MSG_UNLOAD_SOUND_EFFECTS = 20;
    205     private static final int MSG_SYSTEM_READY = 21;
    206     private static final int MSG_PERSIST_MUSIC_ACTIVE_MS = 22;
    207     private static final int MSG_PERSIST_MICROPHONE_MUTE = 23;
    208     // start of messages handled under wakelock
    209     //   these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(),
    210     //   and not with sendMsg(..., ..., SENDMSG_QUEUE, ...)
    211     private static final int MSG_SET_WIRED_DEVICE_CONNECTION_STATE = 100;
    212     private static final int MSG_SET_A2DP_SRC_CONNECTION_STATE = 101;
    213     private static final int MSG_SET_A2DP_SINK_CONNECTION_STATE = 102;
    214     // end of messages handled under wakelock
    215 
    216     private static final int BTA2DP_DOCK_TIMEOUT_MILLIS = 8000;
    217     // Timeout for connection to bluetooth headset service
    218     private static final int BT_HEADSET_CNCT_TIMEOUT_MS = 3000;
    219 
    220     /** @see AudioSystemThread */
    221     private AudioSystemThread mAudioSystemThread;
    222     /** @see AudioHandler */
    223     private AudioHandler mAudioHandler;
    224     /** @see VolumeStreamState */
    225     private VolumeStreamState[] mStreamStates;
    226     private SettingsObserver mSettingsObserver;
    227 
    228     private int mMode = AudioSystem.MODE_NORMAL;
    229     // protects mRingerMode
    230     private final Object mSettingsLock = new Object();
    231 
    232     private SoundPool mSoundPool;
    233     private final Object mSoundEffectsLock = new Object();
    234     private static final int NUM_SOUNDPOOL_CHANNELS = 4;
    235 
    236     // Internally master volume is a float in the 0.0 - 1.0 range,
    237     // but to support integer based AudioManager API we translate it to 0 - 100
    238     private static final int MAX_MASTER_VOLUME = 100;
    239 
    240     // Maximum volume adjust steps allowed in a single batch call.
    241     private static final int MAX_BATCH_VOLUME_ADJUST_STEPS = 4;
    242 
    243     /* Sound effect file names  */
    244     private static final String SOUND_EFFECTS_PATH = "/media/audio/ui/";
    245     private static final List<String> SOUND_EFFECT_FILES = new ArrayList<String>();
    246 
    247     /* Sound effect file name mapping sound effect id (AudioManager.FX_xxx) to
    248      * file index in SOUND_EFFECT_FILES[] (first column) and indicating if effect
    249      * uses soundpool (second column) */
    250     private final int[][] SOUND_EFFECT_FILES_MAP = new int[AudioManager.NUM_SOUND_EFFECTS][2];
    251 
    252    /** @hide Maximum volume index values for audio streams */
    253     private static int[] MAX_STREAM_VOLUME = new int[] {
    254         5,  // STREAM_VOICE_CALL
    255         7,  // STREAM_SYSTEM
    256         7,  // STREAM_RING
    257         15, // STREAM_MUSIC
    258         7,  // STREAM_ALARM
    259         7,  // STREAM_NOTIFICATION
    260         15, // STREAM_BLUETOOTH_SCO
    261         7,  // STREAM_SYSTEM_ENFORCED
    262         15, // STREAM_DTMF
    263         15  // STREAM_TTS
    264     };
    265 
    266     private static int[] DEFAULT_STREAM_VOLUME = new int[] {
    267         4,  // STREAM_VOICE_CALL
    268         7,  // STREAM_SYSTEM
    269         5,  // STREAM_RING
    270         11, // STREAM_MUSIC
    271         6,  // STREAM_ALARM
    272         5,  // STREAM_NOTIFICATION
    273         7,  // STREAM_BLUETOOTH_SCO
    274         7,  // STREAM_SYSTEM_ENFORCED
    275         11, // STREAM_DTMF
    276         11  // STREAM_TTS
    277     };
    278 
    279     /* mStreamVolumeAlias[] indicates for each stream if it uses the volume settings
    280      * of another stream: This avoids multiplying the volume settings for hidden
    281      * stream types that follow other stream behavior for volume settings
    282      * NOTE: do not create loops in aliases!
    283      * Some streams alias to different streams according to device category (phone or tablet) or
    284      * use case (in call vs off call...). See updateStreamVolumeAlias() for more details.
    285      *  mStreamVolumeAlias contains STREAM_VOLUME_ALIAS_VOICE aliases for a voice capable device
    286      *  (phone), STREAM_VOLUME_ALIAS_TELEVISION for a television or set-top box and
    287      *  STREAM_VOLUME_ALIAS_DEFAULT for other devices (e.g. tablets).*/
    288     private final int[] STREAM_VOLUME_ALIAS_VOICE = new int[] {
    289         AudioSystem.STREAM_VOICE_CALL,      // STREAM_VOICE_CALL
    290         AudioSystem.STREAM_RING,            // STREAM_SYSTEM
    291         AudioSystem.STREAM_RING,            // STREAM_RING
    292         AudioSystem.STREAM_MUSIC,           // STREAM_MUSIC
    293         AudioSystem.STREAM_ALARM,           // STREAM_ALARM
    294         AudioSystem.STREAM_RING,            // STREAM_NOTIFICATION
    295         AudioSystem.STREAM_BLUETOOTH_SCO,   // STREAM_BLUETOOTH_SCO
    296         AudioSystem.STREAM_RING,            // STREAM_SYSTEM_ENFORCED
    297         AudioSystem.STREAM_RING,            // STREAM_DTMF
    298         AudioSystem.STREAM_MUSIC            // STREAM_TTS
    299     };
    300     private final int[] STREAM_VOLUME_ALIAS_TELEVISION = new int[] {
    301         AudioSystem.STREAM_MUSIC,       // STREAM_VOICE_CALL
    302         AudioSystem.STREAM_MUSIC,       // STREAM_SYSTEM
    303         AudioSystem.STREAM_MUSIC,       // STREAM_RING
    304         AudioSystem.STREAM_MUSIC,       // STREAM_MUSIC
    305         AudioSystem.STREAM_MUSIC,       // STREAM_ALARM
    306         AudioSystem.STREAM_MUSIC,       // STREAM_NOTIFICATION
    307         AudioSystem.STREAM_MUSIC,       // STREAM_BLUETOOTH_SCO
    308         AudioSystem.STREAM_MUSIC,       // STREAM_SYSTEM_ENFORCED
    309         AudioSystem.STREAM_MUSIC,       // STREAM_DTMF
    310         AudioSystem.STREAM_MUSIC        // STREAM_TTS
    311     };
    312     private final int[] STREAM_VOLUME_ALIAS_DEFAULT = new int[] {
    313         AudioSystem.STREAM_VOICE_CALL,      // STREAM_VOICE_CALL
    314         AudioSystem.STREAM_RING,            // STREAM_SYSTEM
    315         AudioSystem.STREAM_RING,            // STREAM_RING
    316         AudioSystem.STREAM_MUSIC,           // STREAM_MUSIC
    317         AudioSystem.STREAM_ALARM,           // STREAM_ALARM
    318         AudioSystem.STREAM_RING,            // STREAM_NOTIFICATION
    319         AudioSystem.STREAM_BLUETOOTH_SCO,   // STREAM_BLUETOOTH_SCO
    320         AudioSystem.STREAM_RING,            // STREAM_SYSTEM_ENFORCED
    321         AudioSystem.STREAM_RING,            // STREAM_DTMF
    322         AudioSystem.STREAM_MUSIC            // STREAM_TTS
    323     };
    324     private int[] mStreamVolumeAlias;
    325 
    326     /**
    327      * Map AudioSystem.STREAM_* constants to app ops.  This should be used
    328      * after mapping through mStreamVolumeAlias.
    329      */
    330     private static final int[] STEAM_VOLUME_OPS = new int[] {
    331         AppOpsManager.OP_AUDIO_VOICE_VOLUME,            // STREAM_VOICE_CALL
    332         AppOpsManager.OP_AUDIO_MEDIA_VOLUME,            // STREAM_SYSTEM
    333         AppOpsManager.OP_AUDIO_RING_VOLUME,             // STREAM_RING
    334         AppOpsManager.OP_AUDIO_MEDIA_VOLUME,            // STREAM_MUSIC
    335         AppOpsManager.OP_AUDIO_ALARM_VOLUME,            // STREAM_ALARM
    336         AppOpsManager.OP_AUDIO_NOTIFICATION_VOLUME,     // STREAM_NOTIFICATION
    337         AppOpsManager.OP_AUDIO_BLUETOOTH_VOLUME,        // STREAM_BLUETOOTH_SCO
    338         AppOpsManager.OP_AUDIO_MEDIA_VOLUME,            // STREAM_SYSTEM_ENFORCED
    339         AppOpsManager.OP_AUDIO_MEDIA_VOLUME,            // STREAM_DTMF
    340         AppOpsManager.OP_AUDIO_MEDIA_VOLUME,            // STREAM_TTS
    341     };
    342 
    343     private final boolean mUseFixedVolume;
    344 
    345     // stream names used by dumpStreamStates()
    346     private static final String[] STREAM_NAMES = new String[] {
    347             "STREAM_VOICE_CALL",
    348             "STREAM_SYSTEM",
    349             "STREAM_RING",
    350             "STREAM_MUSIC",
    351             "STREAM_ALARM",
    352             "STREAM_NOTIFICATION",
    353             "STREAM_BLUETOOTH_SCO",
    354             "STREAM_SYSTEM_ENFORCED",
    355             "STREAM_DTMF",
    356             "STREAM_TTS"
    357     };
    358 
    359     private final AudioSystem.ErrorCallback mAudioSystemCallback = new AudioSystem.ErrorCallback() {
    360         public void onError(int error) {
    361             switch (error) {
    362             case AudioSystem.AUDIO_STATUS_SERVER_DIED:
    363                 sendMsg(mAudioHandler, MSG_MEDIA_SERVER_DIED,
    364                         SENDMSG_NOOP, 0, 0, null, 0);
    365                 break;
    366             default:
    367                 break;
    368             }
    369         }
    370     };
    371 
    372     /**
    373      * Current ringer mode from one of {@link AudioManager#RINGER_MODE_NORMAL},
    374      * {@link AudioManager#RINGER_MODE_SILENT}, or
    375      * {@link AudioManager#RINGER_MODE_VIBRATE}.
    376      */
    377     // protected by mSettingsLock
    378     private int mRingerMode;  // internal ringer mode, affects muting of underlying streams
    379     private int mRingerModeExternal = -1;  // reported ringer mode to outside clients (AudioManager)
    380 
    381     /** @see System#MODE_RINGER_STREAMS_AFFECTED */
    382     private int mRingerModeAffectedStreams = 0;
    383 
    384     // Streams currently muted by ringer mode
    385     private int mRingerModeMutedStreams;
    386 
    387     /** @see System#MUTE_STREAMS_AFFECTED */
    388     private int mMuteAffectedStreams;
    389 
    390     /**
    391      * NOTE: setVibrateSetting(), getVibrateSetting(), shouldVibrate() are deprecated.
    392      * mVibrateSetting is just maintained during deprecation period but vibration policy is
    393      * now only controlled by mHasVibrator and mRingerMode
    394      */
    395     private int mVibrateSetting;
    396 
    397     // Is there a vibrator
    398     private final boolean mHasVibrator;
    399 
    400     // Broadcast receiver for device connections intent broadcasts
    401     private final BroadcastReceiver mReceiver = new AudioServiceBroadcastReceiver();
    402 
    403     // Devices currently connected
    404     private final HashMap <Integer, String> mConnectedDevices = new HashMap <Integer, String>();
    405 
    406     // Forced device usage for communications
    407     private int mForcedUseForComm;
    408 
    409     // True if we have master volume support
    410     private final boolean mUseMasterVolume;
    411 
    412     private final int[] mMasterVolumeRamp;
    413 
    414     // List of binder death handlers for setMode() client processes.
    415     // The last process to have called setMode() is at the top of the list.
    416     private final ArrayList <SetModeDeathHandler> mSetModeDeathHandlers = new ArrayList <SetModeDeathHandler>();
    417 
    418     // List of clients having issued a SCO start request
    419     private final ArrayList <ScoClient> mScoClients = new ArrayList <ScoClient>();
    420 
    421     // BluetoothHeadset API to control SCO connection
    422     private BluetoothHeadset mBluetoothHeadset;
    423 
    424     // Bluetooth headset device
    425     private BluetoothDevice mBluetoothHeadsetDevice;
    426 
    427     // Indicate if SCO audio connection is currently active and if the initiator is
    428     // audio service (internal) or bluetooth headset (external)
    429     private int mScoAudioState;
    430     // SCO audio state is not active
    431     private static final int SCO_STATE_INACTIVE = 0;
    432     // SCO audio activation request waiting for headset service to connect
    433     private static final int SCO_STATE_ACTIVATE_REQ = 1;
    434     // SCO audio state is active or starting due to a request from AudioManager API
    435     private static final int SCO_STATE_ACTIVE_INTERNAL = 3;
    436     // SCO audio deactivation request waiting for headset service to connect
    437     private static final int SCO_STATE_DEACTIVATE_REQ = 5;
    438 
    439     // SCO audio state is active due to an action in BT handsfree (either voice recognition or
    440     // in call audio)
    441     private static final int SCO_STATE_ACTIVE_EXTERNAL = 2;
    442     // Deactivation request for all SCO connections (initiated by audio mode change)
    443     // waiting for headset service to connect
    444     private static final int SCO_STATE_DEACTIVATE_EXT_REQ = 4;
    445 
    446     // Indicates the mode used for SCO audio connection. The mode is virtual call if the request
    447     // originated from an app targeting an API version before JB MR2 and raw audio after that.
    448     private int mScoAudioMode;
    449     // SCO audio mode is undefined
    450     private static final int SCO_MODE_UNDEFINED = -1;
    451     // SCO audio mode is virtual voice call (BluetoothHeadset.startScoUsingVirtualVoiceCall())
    452     private static final int SCO_MODE_VIRTUAL_CALL = 0;
    453     // SCO audio mode is raw audio (BluetoothHeadset.connectAudio())
    454     private static final int SCO_MODE_RAW = 1;
    455     // SCO audio mode is Voice Recognition (BluetoothHeadset.startVoiceRecognition())
    456     private static final int SCO_MODE_VR = 2;
    457 
    458     private static final int SCO_MODE_MAX = 2;
    459 
    460     // Current connection state indicated by bluetooth headset
    461     private int mScoConnectionState;
    462 
    463     // true if boot sequence has been completed
    464     private boolean mSystemReady;
    465     // listener for SoundPool sample load completion indication
    466     private SoundPoolCallback mSoundPoolCallBack;
    467     // thread for SoundPool listener
    468     private SoundPoolListenerThread mSoundPoolListenerThread;
    469     // message looper for SoundPool listener
    470     private Looper mSoundPoolLooper = null;
    471     // volume applied to sound played with playSoundEffect()
    472     private static int sSoundEffectVolumeDb;
    473     // previous volume adjustment direction received by checkForRingerModeChange()
    474     private int mPrevVolDirection = AudioManager.ADJUST_SAME;
    475     // Keyguard manager proxy
    476     private KeyguardManager mKeyguardManager;
    477     // mVolumeControlStream is set by VolumePanel to temporarily force the stream type which volume
    478     // is controlled by Vol keys.
    479     private int  mVolumeControlStream = -1;
    480     private final Object mForceControlStreamLock = new Object();
    481     // VolumePanel is currently the only client of forceVolumeControlStream() and runs in system
    482     // server process so in theory it is not necessary to monitor the client death.
    483     // However it is good to be ready for future evolutions.
    484     private ForceControlStreamClient mForceControlStreamClient = null;
    485     // Used to play ringtones outside system_server
    486     private volatile IRingtonePlayer mRingtonePlayer;
    487 
    488     private int mDeviceOrientation = Configuration.ORIENTATION_UNDEFINED;
    489     private int mDeviceRotation = Surface.ROTATION_0;
    490 
    491     // Request to override default use of A2DP for media.
    492     private boolean mBluetoothA2dpEnabled;
    493     private final Object mBluetoothA2dpEnabledLock = new Object();
    494 
    495     // Monitoring of audio routes.  Protected by mCurAudioRoutes.
    496     final AudioRoutesInfo mCurAudioRoutes = new AudioRoutesInfo();
    497     final RemoteCallbackList<IAudioRoutesObserver> mRoutesObservers
    498             = new RemoteCallbackList<IAudioRoutesObserver>();
    499 
    500     // Devices for which the volume is fixed and VolumePanel slider should be disabled
    501     int mFixedVolumeDevices = AudioSystem.DEVICE_OUT_HDMI |
    502             AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET |
    503             AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET |
    504             AudioSystem.DEVICE_OUT_HDMI_ARC |
    505             AudioSystem.DEVICE_OUT_SPDIF |
    506             AudioSystem.DEVICE_OUT_AUX_LINE;
    507     int mFullVolumeDevices = 0;
    508 
    509     // TODO merge orientation and rotation
    510     private final boolean mMonitorOrientation;
    511     private final boolean mMonitorRotation;
    512 
    513     private boolean mDockAudioMediaEnabled = true;
    514 
    515     private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
    516 
    517     // Used when safe volume warning message display is requested by setStreamVolume(). In this
    518     // case, the new requested volume, stream type and device are stored in mPendingVolumeCommand
    519     // and used later when/if disableSafeMediaVolume() is called.
    520     private StreamVolumeCommand mPendingVolumeCommand;
    521 
    522     private PowerManager.WakeLock mAudioEventWakeLock;
    523 
    524     private final MediaFocusControl mMediaFocusControl;
    525 
    526     // Reference to BluetoothA2dp to query for AbsoluteVolume.
    527     private BluetoothA2dp mA2dp;
    528     private final Object mA2dpAvrcpLock = new Object();
    529     // If absolute volume is supported in AVRCP device
    530     private boolean mAvrcpAbsVolSupported = false;
    531 
    532     private AudioOrientationEventListener mOrientationListener;
    533 
    534     private static Long mLastDeviceConnectMsgTime = new Long(0);
    535 
    536     private AudioManagerInternal.RingerModeDelegate mRingerModeDelegate;
    537 
    538     ///////////////////////////////////////////////////////////////////////////
    539     // Construction
    540     ///////////////////////////////////////////////////////////////////////////
    541 
    542     /** @hide */
    543     public AudioService(Context context) {
    544         mContext = context;
    545         mContentResolver = context.getContentResolver();
    546         mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
    547 
    548         if (mContext.getResources().getBoolean(
    549                 com.android.internal.R.bool.config_voice_capable)) {
    550             mPlatformType = PLATFORM_VOICE;
    551         } else if (context.getPackageManager().hasSystemFeature(
    552                                                             PackageManager.FEATURE_LEANBACK)) {
    553             mPlatformType = PLATFORM_TELEVISION;
    554         } else {
    555             mPlatformType = PLATFORM_DEFAULT;
    556         }
    557 
    558         PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
    559         mAudioEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "handleAudioEvent");
    560 
    561         Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
    562         mHasVibrator = vibrator == null ? false : vibrator.hasVibrator();
    563 
    564        // Intialized volume
    565         int maxVolume = SystemProperties.getInt("ro.config.vc_call_vol_steps",
    566                 MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL]);
    567         if (maxVolume != MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL]) {
    568             MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] = maxVolume;
    569             DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] = (maxVolume * 3) / 4;
    570         }
    571         maxVolume = SystemProperties.getInt("ro.config.media_vol_steps",
    572                 MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC]);
    573         if (maxVolume != MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC]) {
    574             MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] = maxVolume;
    575             DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] = (maxVolume * 3) / 4;
    576         }
    577 
    578         sSoundEffectVolumeDb = context.getResources().getInteger(
    579                 com.android.internal.R.integer.config_soundEffectVolumeDb);
    580 
    581         mForcedUseForComm = AudioSystem.FORCE_NONE;
    582 
    583         createAudioSystemThread();
    584 
    585         mMediaFocusControl = new MediaFocusControl(mAudioHandler.getLooper(),
    586                 mContext, mVolumeController, this);
    587 
    588         AudioSystem.setErrorCallback(mAudioSystemCallback);
    589 
    590         boolean cameraSoundForced = mContext.getResources().getBoolean(
    591                 com.android.internal.R.bool.config_camera_sound_forced);
    592         mCameraSoundForced = new Boolean(cameraSoundForced);
    593         sendMsg(mAudioHandler,
    594                 MSG_SET_FORCE_USE,
    595                 SENDMSG_QUEUE,
    596                 AudioSystem.FOR_SYSTEM,
    597                 cameraSoundForced ?
    598                         AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE,
    599                 null,
    600                 0);
    601 
    602         mSafeMediaVolumeState = new Integer(Settings.Global.getInt(mContentResolver,
    603                                                         Settings.Global.AUDIO_SAFE_VOLUME_STATE,
    604                                                         SAFE_MEDIA_VOLUME_NOT_CONFIGURED));
    605         // The default safe volume index read here will be replaced by the actual value when
    606         // the mcc is read by onConfigureSafeVolume()
    607         mSafeMediaVolumeIndex = mContext.getResources().getInteger(
    608                 com.android.internal.R.integer.config_safe_media_volume_index) * 10;
    609 
    610         mUseFixedVolume = mContext.getResources().getBoolean(
    611                 com.android.internal.R.bool.config_useFixedVolume);
    612         mUseMasterVolume = context.getResources().getBoolean(
    613                 com.android.internal.R.bool.config_useMasterVolume);
    614         mMasterVolumeRamp = context.getResources().getIntArray(
    615                 com.android.internal.R.array.config_masterVolumeRamp);
    616 
    617         // must be called before readPersistedSettings() which needs a valid mStreamVolumeAlias[]
    618         // array initialized by updateStreamVolumeAlias()
    619         updateStreamVolumeAlias(false /*updateVolumes*/);
    620         readPersistedSettings();
    621         mSettingsObserver = new SettingsObserver();
    622         createStreamStates();
    623 
    624         readAndSetLowRamDevice();
    625 
    626         // Call setRingerModeInt() to apply correct mute
    627         // state on streams affected by ringer mode.
    628         mRingerModeMutedStreams = 0;
    629         setRingerModeInt(getRingerModeInternal(), false);
    630 
    631         // Register for device connection intent broadcasts.
    632         IntentFilter intentFilter =
    633                 new IntentFilter(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
    634         intentFilter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
    635         intentFilter.addAction(Intent.ACTION_DOCK_EVENT);
    636         intentFilter.addAction(AudioManager.ACTION_USB_AUDIO_ACCESSORY_PLUG);
    637         intentFilter.addAction(AudioManager.ACTION_USB_AUDIO_DEVICE_PLUG);
    638         intentFilter.addAction(Intent.ACTION_SCREEN_ON);
    639         intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
    640         intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
    641         intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
    642 
    643         intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
    644         // TODO merge orientation and rotation
    645         mMonitorOrientation = SystemProperties.getBoolean("ro.audio.monitorOrientation", false);
    646         if (mMonitorOrientation) {
    647             Log.v(TAG, "monitoring device orientation");
    648             // initialize orientation in AudioSystem
    649             setOrientationForAudioSystem();
    650         }
    651         mMonitorRotation = SystemProperties.getBoolean("ro.audio.monitorRotation", false);
    652         if (mMonitorRotation) {
    653             mDeviceRotation = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE))
    654                     .getDefaultDisplay().getRotation();
    655             Log.v(TAG, "monitoring device rotation, initial=" + mDeviceRotation);
    656 
    657             mOrientationListener = new AudioOrientationEventListener(mContext);
    658             mOrientationListener.enable();
    659 
    660             // initialize rotation in AudioSystem
    661             setRotationForAudioSystem();
    662         }
    663 
    664         context.registerReceiver(mReceiver, intentFilter);
    665 
    666         restoreMasterVolume();
    667 
    668         LocalServices.addService(AudioManagerInternal.class, new AudioServiceInternal());
    669     }
    670 
    671     public void systemReady() {
    672         sendMsg(mAudioHandler, MSG_SYSTEM_READY, SENDMSG_QUEUE,
    673                 0, 0, null, 0);
    674     }
    675 
    676     public void onSystemReady() {
    677         mSystemReady = true;
    678         sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE,
    679                 0, 0, null, 0);
    680 
    681         mKeyguardManager =
    682                 (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
    683         mScoConnectionState = AudioManager.SCO_AUDIO_STATE_ERROR;
    684         resetBluetoothSco();
    685         getBluetoothHeadset();
    686         //FIXME: this is to maintain compatibility with deprecated intent
    687         // AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. Remove when appropriate.
    688         Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED);
    689         newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE,
    690                 AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
    691         sendStickyBroadcastToAll(newIntent);
    692 
    693         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
    694         if (adapter != null) {
    695             adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
    696                                     BluetoothProfile.A2DP);
    697         }
    698 
    699         mHdmiManager =
    700                 (HdmiControlManager) mContext.getSystemService(Context.HDMI_CONTROL_SERVICE);
    701         if (mHdmiManager != null) {
    702             synchronized (mHdmiManager) {
    703                 mHdmiTvClient = mHdmiManager.getTvClient();
    704                 if (mHdmiTvClient != null) {
    705                     mFixedVolumeDevices &= ~AudioSystem.DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER;
    706                 }
    707                 mHdmiPlaybackClient = mHdmiManager.getPlaybackClient();
    708                 mHdmiCecSink = false;
    709             }
    710         }
    711 
    712         sendMsg(mAudioHandler,
    713                 MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED,
    714                 SENDMSG_REPLACE,
    715                 0,
    716                 0,
    717                 null,
    718                 SAFE_VOLUME_CONFIGURE_TIMEOUT_MS);
    719 
    720         StreamOverride.init(mContext);
    721     }
    722 
    723     private void createAudioSystemThread() {
    724         mAudioSystemThread = new AudioSystemThread();
    725         mAudioSystemThread.start();
    726         waitForAudioHandlerCreation();
    727     }
    728 
    729     /** Waits for the volume handler to be created by the other thread. */
    730     private void waitForAudioHandlerCreation() {
    731         synchronized(this) {
    732             while (mAudioHandler == null) {
    733                 try {
    734                     // Wait for mAudioHandler to be set by the other thread
    735                     wait();
    736                 } catch (InterruptedException e) {
    737                     Log.e(TAG, "Interrupted while waiting on volume handler.");
    738                 }
    739             }
    740         }
    741     }
    742 
    743     private void checkAllAliasStreamVolumes() {
    744         synchronized (VolumeStreamState.class) {
    745             int numStreamTypes = AudioSystem.getNumStreamTypes();
    746             for (int streamType = 0; streamType < numStreamTypes; streamType++) {
    747                 if (streamType != mStreamVolumeAlias[streamType]) {
    748                     mStreamStates[streamType].
    749                                     setAllIndexes(mStreamStates[mStreamVolumeAlias[streamType]]);
    750                 }
    751                 // apply stream volume
    752                 if (!mStreamStates[streamType].isMuted_syncVSS()) {
    753                     mStreamStates[streamType].applyAllVolumes();
    754                 }
    755             }
    756         }
    757     }
    758 
    759     private void checkAllFixedVolumeDevices()
    760     {
    761         int numStreamTypes = AudioSystem.getNumStreamTypes();
    762         for (int streamType = 0; streamType < numStreamTypes; streamType++) {
    763             mStreamStates[streamType].checkFixedVolumeDevices();
    764         }
    765     }
    766 
    767     private void checkAllFixedVolumeDevices(int streamType) {
    768         mStreamStates[streamType].checkFixedVolumeDevices();
    769     }
    770 
    771     private void createStreamStates() {
    772         int numStreamTypes = AudioSystem.getNumStreamTypes();
    773         VolumeStreamState[] streams = mStreamStates = new VolumeStreamState[numStreamTypes];
    774 
    775         for (int i = 0; i < numStreamTypes; i++) {
    776             streams[i] = new VolumeStreamState(System.VOLUME_SETTINGS[mStreamVolumeAlias[i]], i);
    777         }
    778 
    779         checkAllFixedVolumeDevices();
    780         checkAllAliasStreamVolumes();
    781     }
    782 
    783     private void dumpStreamStates(PrintWriter pw) {
    784         pw.println("\nStream volumes (device: index)");
    785         int numStreamTypes = AudioSystem.getNumStreamTypes();
    786         for (int i = 0; i < numStreamTypes; i++) {
    787             pw.println("- "+STREAM_NAMES[i]+":");
    788             mStreamStates[i].dump(pw);
    789             pw.println("");
    790         }
    791         pw.print("\n- mute affected streams = 0x");
    792         pw.println(Integer.toHexString(mMuteAffectedStreams));
    793     }
    794 
    795     /** @hide */
    796     public static String streamToString(int stream) {
    797         if (stream >= 0 && stream < STREAM_NAMES.length) return STREAM_NAMES[stream];
    798         if (stream == AudioManager.USE_DEFAULT_STREAM_TYPE) return "USE_DEFAULT_STREAM_TYPE";
    799         return "UNKNOWN_STREAM_" + stream;
    800     }
    801 
    802     private void updateStreamVolumeAlias(boolean updateVolumes) {
    803         int dtmfStreamAlias;
    804 
    805         switch (mPlatformType) {
    806         case PLATFORM_VOICE:
    807             mStreamVolumeAlias = STREAM_VOLUME_ALIAS_VOICE;
    808             dtmfStreamAlias = AudioSystem.STREAM_RING;
    809             break;
    810         case PLATFORM_TELEVISION:
    811             mStreamVolumeAlias = STREAM_VOLUME_ALIAS_TELEVISION;
    812             dtmfStreamAlias = AudioSystem.STREAM_MUSIC;
    813             break;
    814         default:
    815             mStreamVolumeAlias = STREAM_VOLUME_ALIAS_DEFAULT;
    816             dtmfStreamAlias = AudioSystem.STREAM_MUSIC;
    817         }
    818 
    819         if (isPlatformTelevision()) {
    820             mRingerModeAffectedStreams = 0;
    821         } else {
    822             if (isInCommunication()) {
    823                 dtmfStreamAlias = AudioSystem.STREAM_VOICE_CALL;
    824                 mRingerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_DTMF);
    825             } else {
    826                 mRingerModeAffectedStreams |= (1 << AudioSystem.STREAM_DTMF);
    827             }
    828         }
    829 
    830         mStreamVolumeAlias[AudioSystem.STREAM_DTMF] = dtmfStreamAlias;
    831         if (updateVolumes) {
    832             mStreamStates[AudioSystem.STREAM_DTMF].setAllIndexes(mStreamStates[dtmfStreamAlias]);
    833             // apply stream mute states according to new value of mRingerModeAffectedStreams
    834             setRingerModeInt(getRingerModeInternal(), false);
    835             sendMsg(mAudioHandler,
    836                     MSG_SET_ALL_VOLUMES,
    837                     SENDMSG_QUEUE,
    838                     0,
    839                     0,
    840                     mStreamStates[AudioSystem.STREAM_DTMF], 0);
    841         }
    842     }
    843 
    844     private void readDockAudioSettings(ContentResolver cr)
    845     {
    846         mDockAudioMediaEnabled = Settings.Global.getInt(
    847                                         cr, Settings.Global.DOCK_AUDIO_MEDIA_ENABLED, 0) == 1;
    848 
    849         if (mDockAudioMediaEnabled) {
    850             mBecomingNoisyIntentDevices |= AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET;
    851         } else {
    852             mBecomingNoisyIntentDevices &= ~AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET;
    853         }
    854 
    855         sendMsg(mAudioHandler,
    856                 MSG_SET_FORCE_USE,
    857                 SENDMSG_QUEUE,
    858                 AudioSystem.FOR_DOCK,
    859                 mDockAudioMediaEnabled ?
    860                         AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE,
    861                 null,
    862                 0);
    863     }
    864 
    865     private void readPersistedSettings() {
    866         final ContentResolver cr = mContentResolver;
    867 
    868         int ringerModeFromSettings =
    869                 Settings.Global.getInt(
    870                         cr, Settings.Global.MODE_RINGER, AudioManager.RINGER_MODE_NORMAL);
    871         int ringerMode = ringerModeFromSettings;
    872         // sanity check in case the settings are restored from a device with incompatible
    873         // ringer modes
    874         if (!isValidRingerMode(ringerMode)) {
    875             ringerMode = AudioManager.RINGER_MODE_NORMAL;
    876         }
    877         if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) {
    878             ringerMode = AudioManager.RINGER_MODE_SILENT;
    879         }
    880         if (ringerMode != ringerModeFromSettings) {
    881             Settings.Global.putInt(cr, Settings.Global.MODE_RINGER, ringerMode);
    882         }
    883         if (mUseFixedVolume || isPlatformTelevision()) {
    884             ringerMode = AudioManager.RINGER_MODE_NORMAL;
    885         }
    886         synchronized(mSettingsLock) {
    887             mRingerMode = ringerMode;
    888             if (mRingerModeExternal == -1) {
    889                 mRingerModeExternal = mRingerMode;
    890             }
    891 
    892             // System.VIBRATE_ON is not used any more but defaults for mVibrateSetting
    893             // are still needed while setVibrateSetting() and getVibrateSetting() are being
    894             // deprecated.
    895             mVibrateSetting = getValueForVibrateSetting(0,
    896                                             AudioManager.VIBRATE_TYPE_NOTIFICATION,
    897                                             mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT
    898                                                             : AudioManager.VIBRATE_SETTING_OFF);
    899             mVibrateSetting = getValueForVibrateSetting(mVibrateSetting,
    900                                             AudioManager.VIBRATE_TYPE_RINGER,
    901                                             mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT
    902                                                             : AudioManager.VIBRATE_SETTING_OFF);
    903 
    904             updateRingerModeAffectedStreams();
    905             readDockAudioSettings(cr);
    906         }
    907 
    908         mMuteAffectedStreams = System.getIntForUser(cr,
    909                 System.MUTE_STREAMS_AFFECTED,
    910                 ((1 << AudioSystem.STREAM_MUSIC)|
    911                  (1 << AudioSystem.STREAM_RING)|
    912                  (1 << AudioSystem.STREAM_SYSTEM)),
    913                  UserHandle.USER_CURRENT);
    914 
    915         boolean masterMute = System.getIntForUser(cr, System.VOLUME_MASTER_MUTE,
    916                                                   0, UserHandle.USER_CURRENT) == 1;
    917         if (mUseFixedVolume) {
    918             masterMute = false;
    919             AudioSystem.setMasterVolume(1.0f);
    920         }
    921         AudioSystem.setMasterMute(masterMute);
    922         broadcastMasterMuteStatus(masterMute);
    923 
    924         boolean microphoneMute =
    925                 System.getIntForUser(cr, System.MICROPHONE_MUTE, 0, UserHandle.USER_CURRENT) == 1;
    926         AudioSystem.muteMicrophone(microphoneMute);
    927 
    928         // Each stream will read its own persisted settings
    929 
    930         // Broadcast the sticky intents
    931         broadcastRingerMode(AudioManager.RINGER_MODE_CHANGED_ACTION, mRingerModeExternal);
    932         broadcastRingerMode(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION, mRingerMode);
    933 
    934         // Broadcast vibrate settings
    935         broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER);
    936         broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION);
    937 
    938         // Load settings for the volume controller
    939         mVolumeController.loadSettings(cr);
    940     }
    941 
    942     private int rescaleIndex(int index, int srcStream, int dstStream) {
    943         return (index * mStreamStates[dstStream].getMaxIndex() + mStreamStates[srcStream].getMaxIndex() / 2) / mStreamStates[srcStream].getMaxIndex();
    944     }
    945 
    946     private class AudioOrientationEventListener
    947             extends OrientationEventListener {
    948         public AudioOrientationEventListener(Context context) {
    949             super(context);
    950         }
    951 
    952         @Override
    953         public void onOrientationChanged(int orientation) {
    954             //Even though we're responding to phone orientation events,
    955             //use display rotation so audio stays in sync with video/dialogs
    956             int newRotation = ((WindowManager) mContext.getSystemService(
    957                     Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
    958             if (newRotation != mDeviceRotation) {
    959                 mDeviceRotation = newRotation;
    960                 setRotationForAudioSystem();
    961             }
    962         }
    963     }
    964 
    965     ///////////////////////////////////////////////////////////////////////////
    966     // IPC methods
    967     ///////////////////////////////////////////////////////////////////////////
    968     /** @see AudioManager#adjustVolume(int, int) */
    969     public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
    970             String callingPackage) {
    971         adjustSuggestedStreamVolume(direction, suggestedStreamType, flags, callingPackage,
    972                 Binder.getCallingUid());
    973     }
    974 
    975     private void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
    976             String callingPackage, int uid) {
    977         if (DEBUG_VOL) Log.d(TAG, "adjustSuggestedStreamVolume() stream="+suggestedStreamType
    978                 + ", flags=" + flags);
    979         int streamType;
    980         if (mVolumeControlStream != -1) {
    981             streamType = mVolumeControlStream;
    982         } else {
    983             streamType = getActiveStreamType(suggestedStreamType);
    984         }
    985         final int resolvedStream = mStreamVolumeAlias[streamType];
    986 
    987         // Play sounds on STREAM_RING only.
    988         if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0 &&
    989                 resolvedStream != AudioSystem.STREAM_RING) {
    990             flags &= ~AudioManager.FLAG_PLAY_SOUND;
    991         }
    992 
    993         // For notifications/ring, show the ui before making any adjustments
    994         if (mVolumeController.suppressAdjustment(resolvedStream, flags)) {
    995             direction = 0;
    996             flags &= ~AudioManager.FLAG_PLAY_SOUND;
    997             flags &= ~AudioManager.FLAG_VIBRATE;
    998             if (DEBUG_VOL) Log.d(TAG, "Volume controller suppressed adjustment");
    999         }
   1000 
   1001         adjustStreamVolume(streamType, direction, flags, callingPackage, uid);
   1002     }
   1003 
   1004     /** @see AudioManager#adjustStreamVolume(int, int, int) */
   1005     public void adjustStreamVolume(int streamType, int direction, int flags,
   1006             String callingPackage) {
   1007         adjustStreamVolume(streamType, direction, flags, callingPackage, Binder.getCallingUid());
   1008     }
   1009 
   1010     private void adjustStreamVolume(int streamType, int direction, int flags,
   1011             String callingPackage, int uid) {
   1012         if (mUseFixedVolume) {
   1013             return;
   1014         }
   1015         if (DEBUG_VOL) Log.d(TAG, "adjustStreamVolume() stream="+streamType+", dir="+direction
   1016                 + ", flags="+flags);
   1017 
   1018         ensureValidDirection(direction);
   1019         ensureValidStreamType(streamType);
   1020 
   1021         // use stream type alias here so that streams with same alias have the same behavior,
   1022         // including with regard to silent mode control (e.g the use of STREAM_RING below and in
   1023         // checkForRingerModeChange() in place of STREAM_RING or STREAM_NOTIFICATION)
   1024         int streamTypeAlias = mStreamVolumeAlias[streamType];
   1025         VolumeStreamState streamState = mStreamStates[streamTypeAlias];
   1026 
   1027         final int device = getDeviceForStream(streamTypeAlias);
   1028 
   1029         int aliasIndex = streamState.getIndex(device);
   1030         boolean adjustVolume = true;
   1031         int step;
   1032 
   1033         // skip a2dp absolute volume control request when the device
   1034         // is not an a2dp device
   1035         if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 &&
   1036             (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
   1037             return;
   1038         }
   1039 
   1040         if (mAppOps.noteOp(STEAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage)
   1041                 != AppOpsManager.MODE_ALLOWED) {
   1042             return;
   1043         }
   1044 
   1045         // reset any pending volume command
   1046         synchronized (mSafeMediaVolumeState) {
   1047             mPendingVolumeCommand = null;
   1048         }
   1049 
   1050         flags &= ~AudioManager.FLAG_FIXED_VOLUME;
   1051         if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
   1052                ((device & mFixedVolumeDevices) != 0)) {
   1053             flags |= AudioManager.FLAG_FIXED_VOLUME;
   1054 
   1055             // Always toggle between max safe volume and 0 for fixed volume devices where safe
   1056             // volume is enforced, and max and 0 for the others.
   1057             // This is simulated by stepping by the full allowed volume range
   1058             if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE &&
   1059                     (device & mSafeMediaVolumeDevices) != 0) {
   1060                 step = mSafeMediaVolumeIndex;
   1061             } else {
   1062                 step = streamState.getMaxIndex();
   1063             }
   1064             if (aliasIndex != 0) {
   1065                 aliasIndex = step;
   1066             }
   1067         } else {
   1068             // convert one UI step (+/-1) into a number of internal units on the stream alias
   1069             step = rescaleIndex(10, streamType, streamTypeAlias);
   1070         }
   1071 
   1072         // If either the client forces allowing ringer modes for this adjustment,
   1073         // or the stream type is one that is affected by ringer modes
   1074         if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
   1075                 (streamTypeAlias == getMasterStreamType())) {
   1076             int ringerMode = getRingerModeInternal();
   1077             // do not vibrate if already in vibrate mode
   1078             if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
   1079                 flags &= ~AudioManager.FLAG_VIBRATE;
   1080             }
   1081             // Check if the ringer mode changes with this volume adjustment. If
   1082             // it does, it will handle adjusting the volume, so we won't below
   1083             final int result = checkForRingerModeChange(aliasIndex, direction, step);
   1084             adjustVolume = (result & FLAG_ADJUST_VOLUME) != 0;
   1085             // If suppressing a volume adjustment in silent mode, display the UI hint
   1086             if ((result & AudioManager.FLAG_SHOW_SILENT_HINT) != 0) {
   1087                 flags |= AudioManager.FLAG_SHOW_SILENT_HINT;
   1088             }
   1089             // If suppressing a volume down adjustment in vibrate mode, display the UI hint
   1090             if ((result & AudioManager.FLAG_SHOW_VIBRATE_HINT) != 0) {
   1091                 flags |= AudioManager.FLAG_SHOW_VIBRATE_HINT;
   1092             }
   1093         }
   1094 
   1095         int oldIndex = mStreamStates[streamType].getIndex(device);
   1096 
   1097         if (adjustVolume && (direction != AudioManager.ADJUST_SAME)) {
   1098 
   1099             // Check if volume update should be send to AVRCP
   1100             if (streamTypeAlias == AudioSystem.STREAM_MUSIC &&
   1101                 (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
   1102                 (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
   1103                 synchronized (mA2dpAvrcpLock) {
   1104                     if (mA2dp != null && mAvrcpAbsVolSupported) {
   1105                         mA2dp.adjustAvrcpAbsoluteVolume(direction);
   1106                     }
   1107                 }
   1108             }
   1109 
   1110             if ((direction == AudioManager.ADJUST_RAISE) &&
   1111                     !checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) {
   1112                 Log.e(TAG, "adjustStreamVolume() safe volume index = "+oldIndex);
   1113                 mVolumeController.postDisplaySafeVolumeWarning(flags);
   1114             } else if (streamState.adjustIndex(direction * step, device)) {
   1115                 // Post message to set system volume (it in turn will post a message
   1116                 // to persist). Do not change volume if stream is muted.
   1117                 sendMsg(mAudioHandler,
   1118                         MSG_SET_DEVICE_VOLUME,
   1119                         SENDMSG_QUEUE,
   1120                         device,
   1121                         0,
   1122                         streamState,
   1123                         0);
   1124             }
   1125 
   1126             // Check if volume update should be send to Hdmi system audio.
   1127             int newIndex = mStreamStates[streamType].getIndex(device);
   1128             if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
   1129                 setSystemAudioVolume(oldIndex, newIndex, getStreamMaxVolume(streamType), flags);
   1130             }
   1131             if (mHdmiManager != null) {
   1132                 synchronized (mHdmiManager) {
   1133                     // mHdmiCecSink true => mHdmiPlaybackClient != null
   1134                     if (mHdmiCecSink &&
   1135                             streamTypeAlias == AudioSystem.STREAM_MUSIC &&
   1136                             oldIndex != newIndex) {
   1137                         synchronized (mHdmiPlaybackClient) {
   1138                             int keyCode = (direction == -1) ? KeyEvent.KEYCODE_VOLUME_DOWN :
   1139                                                                KeyEvent.KEYCODE_VOLUME_UP;
   1140                             mHdmiPlaybackClient.sendKeyEvent(keyCode, true);
   1141                             mHdmiPlaybackClient.sendKeyEvent(keyCode, false);
   1142                         }
   1143                     }
   1144                 }
   1145             }
   1146         }
   1147         int index = mStreamStates[streamType].getIndex(device);
   1148         sendVolumeUpdate(streamType, oldIndex, index, flags);
   1149     }
   1150 
   1151     private void setSystemAudioVolume(int oldVolume, int newVolume, int maxVolume, int flags) {
   1152         if (mHdmiManager == null
   1153                 || mHdmiTvClient == null
   1154                 || oldVolume == newVolume
   1155                 || (flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) != 0) return;
   1156 
   1157         // Sets the audio volume of AVR when we are in system audio mode. The new volume info
   1158         // is tranformed to HDMI-CEC commands and passed through CEC bus.
   1159         synchronized (mHdmiManager) {
   1160             if (!mHdmiSystemAudioSupported) return;
   1161             synchronized (mHdmiTvClient) {
   1162                 final long token = Binder.clearCallingIdentity();
   1163                 try {
   1164                     mHdmiTvClient.setSystemAudioVolume(
   1165                             (oldVolume + 5) / 10, (newVolume + 5) / 10, maxVolume);
   1166                 } finally {
   1167                     Binder.restoreCallingIdentity(token);
   1168                 }
   1169             }
   1170         }
   1171     }
   1172 
   1173     /** @see AudioManager#adjustMasterVolume(int, int) */
   1174     public void adjustMasterVolume(int steps, int flags, String callingPackage) {
   1175         adjustMasterVolume(steps, flags, callingPackage, Binder.getCallingUid());
   1176     }
   1177 
   1178     public void adjustMasterVolume(int steps, int flags, String callingPackage, int uid) {
   1179         if (mUseFixedVolume) {
   1180             return;
   1181         }
   1182         ensureValidSteps(steps);
   1183         int volume = Math.round(AudioSystem.getMasterVolume() * MAX_MASTER_VOLUME);
   1184         int delta = 0;
   1185         int numSteps = Math.abs(steps);
   1186         int direction = steps > 0 ? AudioManager.ADJUST_RAISE : AudioManager.ADJUST_LOWER;
   1187         for (int i = 0; i < numSteps; ++i) {
   1188             delta = findVolumeDelta(direction, volume);
   1189             volume += delta;
   1190         }
   1191 
   1192         //Log.d(TAG, "adjustMasterVolume volume: " + volume + " steps: " + steps);
   1193         setMasterVolume(volume, flags, callingPackage, uid);
   1194     }
   1195 
   1196     // StreamVolumeCommand contains the information needed to defer the process of
   1197     // setStreamVolume() in case the user has to acknowledge the safe volume warning message.
   1198     class StreamVolumeCommand {
   1199         public final int mStreamType;
   1200         public final int mIndex;
   1201         public final int mFlags;
   1202         public final int mDevice;
   1203 
   1204         StreamVolumeCommand(int streamType, int index, int flags, int device) {
   1205             mStreamType = streamType;
   1206             mIndex = index;
   1207             mFlags = flags;
   1208             mDevice = device;
   1209         }
   1210 
   1211         @Override
   1212         public String toString() {
   1213             return new StringBuilder().append("{streamType=").append(mStreamType).append(",index=")
   1214                     .append(mIndex).append(",flags=").append(mFlags).append(",device=")
   1215                     .append(mDevice).append('}').toString();
   1216         }
   1217     };
   1218 
   1219     private void onSetStreamVolume(int streamType, int index, int flags, int device) {
   1220         setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, false);
   1221         // setting volume on master stream type also controls silent mode
   1222         if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
   1223                 (mStreamVolumeAlias[streamType] == getMasterStreamType())) {
   1224             int newRingerMode;
   1225             if (index == 0) {
   1226                 newRingerMode = mHasVibrator ? AudioManager.RINGER_MODE_VIBRATE
   1227                         : VOLUME_SETS_RINGER_MODE_SILENT ? AudioManager.RINGER_MODE_SILENT
   1228                         : AudioManager.RINGER_MODE_NORMAL;
   1229             } else {
   1230                 newRingerMode = AudioManager.RINGER_MODE_NORMAL;
   1231             }
   1232             setRingerMode(newRingerMode, TAG + ".onSetStreamVolume", false /*external*/);
   1233         }
   1234     }
   1235 
   1236     /** @see AudioManager#setStreamVolume(int, int, int) */
   1237     public void setStreamVolume(int streamType, int index, int flags, String callingPackage) {
   1238         setStreamVolume(streamType, index, flags, callingPackage, Binder.getCallingUid());
   1239     }
   1240 
   1241     private void setStreamVolume(int streamType, int index, int flags, String callingPackage,
   1242             int uid) {
   1243         if (mUseFixedVolume) {
   1244             return;
   1245         }
   1246 
   1247         ensureValidStreamType(streamType);
   1248         int streamTypeAlias = mStreamVolumeAlias[streamType];
   1249         VolumeStreamState streamState = mStreamStates[streamTypeAlias];
   1250 
   1251         final int device = getDeviceForStream(streamType);
   1252         int oldIndex;
   1253 
   1254         // skip a2dp absolute volume control request when the device
   1255         // is not an a2dp device
   1256         if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 &&
   1257             (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
   1258             return;
   1259         }
   1260 
   1261         if (mAppOps.noteOp(STEAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage)
   1262                 != AppOpsManager.MODE_ALLOWED) {
   1263             return;
   1264         }
   1265 
   1266         synchronized (mSafeMediaVolumeState) {
   1267             // reset any pending volume command
   1268             mPendingVolumeCommand = null;
   1269 
   1270             oldIndex = streamState.getIndex(device);
   1271 
   1272             index = rescaleIndex(index * 10, streamType, streamTypeAlias);
   1273 
   1274             if (streamTypeAlias == AudioSystem.STREAM_MUSIC &&
   1275                 (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
   1276                 (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
   1277                 synchronized (mA2dpAvrcpLock) {
   1278                     if (mA2dp != null && mAvrcpAbsVolSupported) {
   1279                         mA2dp.setAvrcpAbsoluteVolume(index / 10);
   1280                     }
   1281                 }
   1282             }
   1283 
   1284             if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
   1285                 setSystemAudioVolume(oldIndex, index, getStreamMaxVolume(streamType), flags);
   1286             }
   1287 
   1288             flags &= ~AudioManager.FLAG_FIXED_VOLUME;
   1289             if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
   1290                     ((device & mFixedVolumeDevices) != 0)) {
   1291                 flags |= AudioManager.FLAG_FIXED_VOLUME;
   1292 
   1293                 // volume is either 0 or max allowed for fixed volume devices
   1294                 if (index != 0) {
   1295                     if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE &&
   1296                             (device & mSafeMediaVolumeDevices) != 0) {
   1297                         index = mSafeMediaVolumeIndex;
   1298                     } else {
   1299                         index = streamState.getMaxIndex();
   1300                     }
   1301                 }
   1302             }
   1303 
   1304             if (!checkSafeMediaVolume(streamTypeAlias, index, device)) {
   1305                 mVolumeController.postDisplaySafeVolumeWarning(flags);
   1306                 mPendingVolumeCommand = new StreamVolumeCommand(
   1307                                                     streamType, index, flags, device);
   1308             } else {
   1309                 onSetStreamVolume(streamType, index, flags, device);
   1310                 index = mStreamStates[streamType].getIndex(device);
   1311             }
   1312         }
   1313         sendVolumeUpdate(streamType, oldIndex, index, flags);
   1314     }
   1315 
   1316     /** @see AudioManager#forceVolumeControlStream(int) */
   1317     public void forceVolumeControlStream(int streamType, IBinder cb) {
   1318         synchronized(mForceControlStreamLock) {
   1319             mVolumeControlStream = streamType;
   1320             if (mVolumeControlStream == -1) {
   1321                 if (mForceControlStreamClient != null) {
   1322                     mForceControlStreamClient.release();
   1323                     mForceControlStreamClient = null;
   1324                 }
   1325             } else {
   1326                 mForceControlStreamClient = new ForceControlStreamClient(cb);
   1327             }
   1328         }
   1329     }
   1330 
   1331     private class ForceControlStreamClient implements IBinder.DeathRecipient {
   1332         private IBinder mCb; // To be notified of client's death
   1333 
   1334         ForceControlStreamClient(IBinder cb) {
   1335             if (cb != null) {
   1336                 try {
   1337                     cb.linkToDeath(this, 0);
   1338                 } catch (RemoteException e) {
   1339                     // Client has died!
   1340                     Log.w(TAG, "ForceControlStreamClient() could not link to "+cb+" binder death");
   1341                     cb = null;
   1342                 }
   1343             }
   1344             mCb = cb;
   1345         }
   1346 
   1347         public void binderDied() {
   1348             synchronized(mForceControlStreamLock) {
   1349                 Log.w(TAG, "SCO client died");
   1350                 if (mForceControlStreamClient != this) {
   1351                     Log.w(TAG, "unregistered control stream client died");
   1352                 } else {
   1353                     mForceControlStreamClient = null;
   1354                     mVolumeControlStream = -1;
   1355                 }
   1356             }
   1357         }
   1358 
   1359         public void release() {
   1360             if (mCb != null) {
   1361                 mCb.unlinkToDeath(this, 0);
   1362                 mCb = null;
   1363             }
   1364         }
   1365     }
   1366 
   1367     private int findVolumeDelta(int direction, int volume) {
   1368         int delta = 0;
   1369         if (direction == AudioManager.ADJUST_RAISE) {
   1370             if (volume == MAX_MASTER_VOLUME) {
   1371                 return 0;
   1372             }
   1373             // This is the default value if we make it to the end
   1374             delta = mMasterVolumeRamp[1];
   1375             // If we're raising the volume move down the ramp array until we
   1376             // find the volume we're above and use that groups delta.
   1377             for (int i = mMasterVolumeRamp.length - 1; i > 1; i -= 2) {
   1378                 if (volume >= mMasterVolumeRamp[i - 1]) {
   1379                     delta = mMasterVolumeRamp[i];
   1380                     break;
   1381                 }
   1382             }
   1383         } else if (direction == AudioManager.ADJUST_LOWER){
   1384             if (volume == 0) {
   1385                 return 0;
   1386             }
   1387             int length = mMasterVolumeRamp.length;
   1388             // This is the default value if we make it to the end
   1389             delta = -mMasterVolumeRamp[length - 1];
   1390             // If we're lowering the volume move up the ramp array until we
   1391             // find the volume we're below and use the group below it's delta
   1392             for (int i = 2; i < length; i += 2) {
   1393                 if (volume <= mMasterVolumeRamp[i]) {
   1394                     delta = -mMasterVolumeRamp[i - 1];
   1395                     break;
   1396                 }
   1397             }
   1398         }
   1399         return delta;
   1400     }
   1401 
   1402     private void sendBroadcastToAll(Intent intent) {
   1403         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
   1404         final long ident = Binder.clearCallingIdentity();
   1405         try {
   1406             mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
   1407         } finally {
   1408             Binder.restoreCallingIdentity(ident);
   1409         }
   1410     }
   1411 
   1412     private void sendStickyBroadcastToAll(Intent intent) {
   1413         final long ident = Binder.clearCallingIdentity();
   1414         try {
   1415             mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
   1416         } finally {
   1417             Binder.restoreCallingIdentity(ident);
   1418         }
   1419     }
   1420 
   1421     // UI update and Broadcast Intent
   1422     private void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags) {
   1423         if (!isPlatformVoice() && (streamType == AudioSystem.STREAM_RING)) {
   1424             streamType = AudioSystem.STREAM_NOTIFICATION;
   1425         }
   1426 
   1427         if (streamType == AudioSystem.STREAM_MUSIC) {
   1428             flags = updateFlagsForSystemAudio(flags);
   1429         }
   1430         mVolumeController.postVolumeChanged(streamType, flags);
   1431 
   1432         if ((flags & AudioManager.FLAG_FIXED_VOLUME) == 0) {
   1433             oldIndex = (oldIndex + 5) / 10;
   1434             index = (index + 5) / 10;
   1435             Intent intent = new Intent(AudioManager.VOLUME_CHANGED_ACTION);
   1436             intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, streamType);
   1437             intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, index);
   1438             intent.putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, oldIndex);
   1439             sendBroadcastToAll(intent);
   1440         }
   1441     }
   1442 
   1443     // If Hdmi-CEC system audio mode is on, we show volume bar only when TV
   1444     // receives volume notification from Audio Receiver.
   1445     private int updateFlagsForSystemAudio(int flags) {
   1446         if (mHdmiTvClient != null) {
   1447             synchronized (mHdmiTvClient) {
   1448                 if (mHdmiSystemAudioSupported &&
   1449                         ((flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) == 0)) {
   1450                     flags &= ~AudioManager.FLAG_SHOW_UI;
   1451                 }
   1452             }
   1453         }
   1454         return flags;
   1455     }
   1456 
   1457     // UI update and Broadcast Intent
   1458     private void sendMasterVolumeUpdate(int flags, int oldVolume, int newVolume) {
   1459         mVolumeController.postMasterVolumeChanged(updateFlagsForSystemAudio(flags));
   1460 
   1461         Intent intent = new Intent(AudioManager.MASTER_VOLUME_CHANGED_ACTION);
   1462         intent.putExtra(AudioManager.EXTRA_PREV_MASTER_VOLUME_VALUE, oldVolume);
   1463         intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_VALUE, newVolume);
   1464         sendBroadcastToAll(intent);
   1465     }
   1466 
   1467     // UI update and Broadcast Intent
   1468     private void sendMasterMuteUpdate(boolean muted, int flags) {
   1469         mVolumeController.postMasterMuteChanged(updateFlagsForSystemAudio(flags));
   1470         broadcastMasterMuteStatus(muted);
   1471     }
   1472 
   1473     private void broadcastMasterMuteStatus(boolean muted) {
   1474         Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION);
   1475         intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, muted);
   1476         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
   1477                 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
   1478         sendStickyBroadcastToAll(intent);
   1479     }
   1480 
   1481     /**
   1482      * Sets the stream state's index, and posts a message to set system volume.
   1483      * This will not call out to the UI. Assumes a valid stream type.
   1484      *
   1485      * @param streamType Type of the stream
   1486      * @param index Desired volume index of the stream
   1487      * @param device the device whose volume must be changed
   1488      * @param force If true, set the volume even if the desired volume is same
   1489      * as the current volume.
   1490      */
   1491     private void setStreamVolumeInt(int streamType,
   1492                                     int index,
   1493                                     int device,
   1494                                     boolean force) {
   1495         VolumeStreamState streamState = mStreamStates[streamType];
   1496 
   1497         if (streamState.setIndex(index, device) || force) {
   1498             // Post message to set system volume (it in turn will post a message
   1499             // to persist).
   1500             sendMsg(mAudioHandler,
   1501                     MSG_SET_DEVICE_VOLUME,
   1502                     SENDMSG_QUEUE,
   1503                     device,
   1504                     0,
   1505                     streamState,
   1506                     0);
   1507         }
   1508     }
   1509 
   1510     /** @see AudioManager#setStreamSolo(int, boolean) */
   1511     public void setStreamSolo(int streamType, boolean state, IBinder cb) {
   1512         if (mUseFixedVolume) {
   1513             return;
   1514         }
   1515         int streamAlias = mStreamVolumeAlias[streamType];
   1516         for (int stream = 0; stream < mStreamStates.length; stream++) {
   1517             if (!isStreamAffectedByMute(streamAlias) || streamAlias == mStreamVolumeAlias[stream]) {
   1518                 continue;
   1519             }
   1520             mStreamStates[stream].mute(cb, state);
   1521          }
   1522     }
   1523 
   1524     /** @see AudioManager#setStreamMute(int, boolean) */
   1525     public void setStreamMute(int streamType, boolean state, IBinder cb) {
   1526         if (mUseFixedVolume) {
   1527             return;
   1528         }
   1529         if (streamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
   1530             streamType = getActiveStreamType(streamType);
   1531         }
   1532         int streamAlias = mStreamVolumeAlias[streamType];
   1533         if (isStreamAffectedByMute(streamAlias)) {
   1534             if (streamAlias == AudioSystem.STREAM_MUSIC) {
   1535                 setSystemAudioMute(state);
   1536             }
   1537             for (int stream = 0; stream < mStreamStates.length; stream++) {
   1538                 if (streamAlias == mStreamVolumeAlias[stream]) {
   1539                     mStreamStates[stream].mute(cb, state);
   1540 
   1541                     Intent intent = new Intent(AudioManager.STREAM_MUTE_CHANGED_ACTION);
   1542                     intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, stream);
   1543                     intent.putExtra(AudioManager.EXTRA_STREAM_VOLUME_MUTED, state);
   1544                     sendBroadcastToAll(intent);
   1545                 }
   1546             }
   1547         }
   1548     }
   1549 
   1550     private void setSystemAudioMute(boolean state) {
   1551         if (mHdmiManager == null || mHdmiTvClient == null) return;
   1552         synchronized (mHdmiManager) {
   1553             if (!mHdmiSystemAudioSupported) return;
   1554             synchronized (mHdmiTvClient) {
   1555                 final long token = Binder.clearCallingIdentity();
   1556                 try {
   1557                     mHdmiTvClient.setSystemAudioMute(state);
   1558                 } finally {
   1559                     Binder.restoreCallingIdentity(token);
   1560                 }
   1561             }
   1562         }
   1563     }
   1564 
   1565     /** get stream mute state. */
   1566     public boolean isStreamMute(int streamType) {
   1567         if (streamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
   1568             streamType = getActiveStreamType(streamType);
   1569         }
   1570         synchronized (VolumeStreamState.class) {
   1571             return mStreamStates[streamType].isMuted_syncVSS();
   1572         }
   1573     }
   1574 
   1575     private class RmtSbmxFullVolDeathHandler implements IBinder.DeathRecipient {
   1576         private IBinder mICallback; // To be notified of client's death
   1577 
   1578         RmtSbmxFullVolDeathHandler(IBinder cb) {
   1579             mICallback = cb;
   1580             try {
   1581                 cb.linkToDeath(this, 0/*flags*/);
   1582             } catch (RemoteException e) {
   1583                 Log.e(TAG, "can't link to death", e);
   1584             }
   1585         }
   1586 
   1587         boolean isHandlerFor(IBinder cb) {
   1588             return mICallback.equals(cb);
   1589         }
   1590 
   1591         void forget() {
   1592             try {
   1593                 mICallback.unlinkToDeath(this, 0/*flags*/);
   1594             } catch (NoSuchElementException e) {
   1595                 Log.e(TAG, "error unlinking to death", e);
   1596             }
   1597         }
   1598 
   1599         public void binderDied() {
   1600             Log.w(TAG, "Recorder with remote submix at full volume died " + mICallback);
   1601             forceRemoteSubmixFullVolume(false, mICallback);
   1602         }
   1603     }
   1604 
   1605     /**
   1606      * call must be synchronized on mRmtSbmxFullVolDeathHandlers
   1607      * @return true if there is a registered death handler, false otherwise */
   1608     private boolean discardRmtSbmxFullVolDeathHandlerFor(IBinder cb) {
   1609         Iterator<RmtSbmxFullVolDeathHandler> it = mRmtSbmxFullVolDeathHandlers.iterator();
   1610         while (it.hasNext()) {
   1611             final RmtSbmxFullVolDeathHandler handler = it.next();
   1612             if (handler.isHandlerFor(cb)) {
   1613                 handler.forget();
   1614                 mRmtSbmxFullVolDeathHandlers.remove(handler);
   1615                 return true;
   1616             }
   1617         }
   1618         return false;
   1619     }
   1620 
   1621     /** call synchronized on mRmtSbmxFullVolDeathHandlers */
   1622     private boolean hasRmtSbmxFullVolDeathHandlerFor(IBinder cb) {
   1623         Iterator<RmtSbmxFullVolDeathHandler> it = mRmtSbmxFullVolDeathHandlers.iterator();
   1624         while (it.hasNext()) {
   1625             if (it.next().isHandlerFor(cb)) {
   1626                 return true;
   1627             }
   1628         }
   1629         return false;
   1630     }
   1631 
   1632     private int mRmtSbmxFullVolRefCount = 0;
   1633     private ArrayList<RmtSbmxFullVolDeathHandler> mRmtSbmxFullVolDeathHandlers =
   1634             new ArrayList<RmtSbmxFullVolDeathHandler>();
   1635 
   1636     public void forceRemoteSubmixFullVolume(boolean startForcing, IBinder cb) {
   1637         if (cb == null) {
   1638             return;
   1639         }
   1640         if ((PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission(
   1641                         android.Manifest.permission.CAPTURE_AUDIO_OUTPUT))) {
   1642             Log.w(TAG, "Trying to call forceRemoteSubmixFullVolume() without CAPTURE_AUDIO_OUTPUT");
   1643             return;
   1644         }
   1645         synchronized(mRmtSbmxFullVolDeathHandlers) {
   1646             boolean applyRequired = false;
   1647             if (startForcing) {
   1648                 if (!hasRmtSbmxFullVolDeathHandlerFor(cb)) {
   1649                     mRmtSbmxFullVolDeathHandlers.add(new RmtSbmxFullVolDeathHandler(cb));
   1650                     if (mRmtSbmxFullVolRefCount == 0) {
   1651                         mFullVolumeDevices |= AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
   1652                         mFixedVolumeDevices |= AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
   1653                         applyRequired = true;
   1654                     }
   1655                     mRmtSbmxFullVolRefCount++;
   1656                 }
   1657             } else {
   1658                 if (discardRmtSbmxFullVolDeathHandlerFor(cb) && (mRmtSbmxFullVolRefCount > 0)) {
   1659                     mRmtSbmxFullVolRefCount--;
   1660                     if (mRmtSbmxFullVolRefCount == 0) {
   1661                         mFullVolumeDevices &= ~AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
   1662                         mFixedVolumeDevices &= ~AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
   1663                         applyRequired = true;
   1664                     }
   1665                 }
   1666             }
   1667             if (applyRequired) {
   1668                 // Assumes only STREAM_MUSIC going through DEVICE_OUT_REMOTE_SUBMIX
   1669                 checkAllFixedVolumeDevices(AudioSystem.STREAM_MUSIC);
   1670                 mStreamStates[AudioSystem.STREAM_MUSIC].applyAllVolumes();
   1671             }
   1672         }
   1673     }
   1674 
   1675     /** @see AudioManager#setMasterMute(boolean, int) */
   1676     public void setMasterMute(boolean state, int flags, String callingPackage, IBinder cb) {
   1677         setMasterMuteInternal(state, flags, callingPackage, cb, Binder.getCallingUid());
   1678     }
   1679 
   1680     private void setMasterMuteInternal(boolean state, int flags, String callingPackage, IBinder cb,
   1681             int uid) {
   1682         if (mUseFixedVolume) {
   1683             return;
   1684         }
   1685         if (mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, uid, callingPackage)
   1686                 != AppOpsManager.MODE_ALLOWED) {
   1687             return;
   1688         }
   1689         if (state != AudioSystem.getMasterMute()) {
   1690             setSystemAudioMute(state);
   1691             AudioSystem.setMasterMute(state);
   1692             // Post a persist master volume msg
   1693             sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME_MUTE, SENDMSG_REPLACE, state ? 1
   1694                     : 0, UserHandle.getCallingUserId(), null, PERSIST_DELAY);
   1695             sendMasterMuteUpdate(state, flags);
   1696 
   1697             Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION);
   1698             intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, state);
   1699             sendBroadcastToAll(intent);
   1700         }
   1701     }
   1702 
   1703     /** get master mute state. */
   1704     public boolean isMasterMute() {
   1705         return AudioSystem.getMasterMute();
   1706     }
   1707 
   1708     protected static int getMaxStreamVolume(int streamType) {
   1709         return MAX_STREAM_VOLUME[streamType];
   1710     }
   1711 
   1712     public static int getDefaultStreamVolume(int streamType) {
   1713         return DEFAULT_STREAM_VOLUME[streamType];
   1714     }
   1715 
   1716     /** @see AudioManager#getStreamVolume(int) */
   1717     public int getStreamVolume(int streamType) {
   1718         ensureValidStreamType(streamType);
   1719         int device = getDeviceForStream(streamType);
   1720         synchronized (VolumeStreamState.class) {
   1721             int index = mStreamStates[streamType].getIndex(device);
   1722 
   1723             // by convention getStreamVolume() returns 0 when a stream is muted.
   1724             if (mStreamStates[streamType].isMuted_syncVSS()) {
   1725                 index = 0;
   1726             }
   1727             if (index != 0 && (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
   1728                     (device & mFixedVolumeDevices) != 0) {
   1729                 index = mStreamStates[streamType].getMaxIndex();
   1730             }
   1731             return (index + 5) / 10;
   1732         }
   1733     }
   1734 
   1735     @Override
   1736     public int getMasterVolume() {
   1737         if (isMasterMute()) return 0;
   1738         return getLastAudibleMasterVolume();
   1739     }
   1740 
   1741     @Override
   1742     public void setMasterVolume(int volume, int flags, String callingPackage) {
   1743         setMasterVolume(volume, flags, callingPackage, Binder.getCallingUid());
   1744     }
   1745 
   1746     public void setMasterVolume(int volume, int flags, String callingPackage, int uid) {
   1747         if (mUseFixedVolume) {
   1748             return;
   1749         }
   1750 
   1751         if (mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, uid, callingPackage)
   1752                 != AppOpsManager.MODE_ALLOWED) {
   1753             return;
   1754         }
   1755 
   1756         if (volume < 0) {
   1757             volume = 0;
   1758         } else if (volume > MAX_MASTER_VOLUME) {
   1759             volume = MAX_MASTER_VOLUME;
   1760         }
   1761         doSetMasterVolume((float)volume / MAX_MASTER_VOLUME, flags);
   1762     }
   1763 
   1764     private void doSetMasterVolume(float volume, int flags) {
   1765         // don't allow changing master volume when muted
   1766         if (!AudioSystem.getMasterMute()) {
   1767             int oldVolume = getMasterVolume();
   1768             AudioSystem.setMasterVolume(volume);
   1769 
   1770             int newVolume = getMasterVolume();
   1771             if (newVolume != oldVolume) {
   1772                 // Post a persist master volume msg
   1773                 sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME, SENDMSG_REPLACE,
   1774                         Math.round(volume * (float)1000.0), 0, null, PERSIST_DELAY);
   1775                 setSystemAudioVolume(oldVolume, newVolume, getMasterMaxVolume(), flags);
   1776             }
   1777             // Send the volume update regardless whether there was a change.
   1778             sendMasterVolumeUpdate(flags, oldVolume, newVolume);
   1779         }
   1780     }
   1781 
   1782     /** @see AudioManager#getStreamMaxVolume(int) */
   1783     public int getStreamMaxVolume(int streamType) {
   1784         ensureValidStreamType(streamType);
   1785         return (mStreamStates[streamType].getMaxIndex() + 5) / 10;
   1786     }
   1787 
   1788     public int getMasterMaxVolume() {
   1789         return MAX_MASTER_VOLUME;
   1790     }
   1791 
   1792     /** Get last audible volume before stream was muted. */
   1793     public int getLastAudibleStreamVolume(int streamType) {
   1794         ensureValidStreamType(streamType);
   1795         int device = getDeviceForStream(streamType);
   1796         return (mStreamStates[streamType].getIndex(device) + 5) / 10;
   1797     }
   1798 
   1799     /** Get last audible master volume before it was muted. */
   1800     public int getLastAudibleMasterVolume() {
   1801         return Math.round(AudioSystem.getMasterVolume() * MAX_MASTER_VOLUME);
   1802     }
   1803 
   1804     /** @see AudioManager#getMasterStreamType()  */
   1805     public int getMasterStreamType() {
   1806         return mStreamVolumeAlias[AudioSystem.STREAM_SYSTEM];
   1807     }
   1808 
   1809     /** @see AudioManager#setMicrophoneMute(boolean) */
   1810     public void setMicrophoneMute(boolean on, String callingPackage) {
   1811         if (mAppOps.noteOp(AppOpsManager.OP_MUTE_MICROPHONE, Binder.getCallingUid(),
   1812                 callingPackage) != AppOpsManager.MODE_ALLOWED) {
   1813             return;
   1814         }
   1815         if (!checkAudioSettingsPermission("setMicrophoneMute()")) {
   1816             return;
   1817         }
   1818 
   1819         AudioSystem.muteMicrophone(on);
   1820         // Post a persist microphone msg.
   1821         sendMsg(mAudioHandler, MSG_PERSIST_MICROPHONE_MUTE, SENDMSG_REPLACE, on ? 1
   1822                 : 0, UserHandle.getCallingUserId(), null, PERSIST_DELAY);
   1823     }
   1824 
   1825     @Override
   1826     public int getRingerModeExternal() {
   1827         synchronized(mSettingsLock) {
   1828             return mRingerModeExternal;
   1829         }
   1830     }
   1831 
   1832     @Override
   1833     public int getRingerModeInternal() {
   1834         synchronized(mSettingsLock) {
   1835             return mRingerMode;
   1836         }
   1837     }
   1838 
   1839     private void ensureValidRingerMode(int ringerMode) {
   1840         if (!isValidRingerMode(ringerMode)) {
   1841             throw new IllegalArgumentException("Bad ringer mode " + ringerMode);
   1842         }
   1843     }
   1844 
   1845     /** @see AudioManager#isValidRingerMode(int) */
   1846     public boolean isValidRingerMode(int ringerMode) {
   1847         return ringerMode >= 0 && ringerMode <= AudioManager.RINGER_MODE_MAX;
   1848     }
   1849 
   1850     public void setRingerModeExternal(int ringerMode, String caller) {
   1851         setRingerMode(ringerMode, caller, true /*external*/);
   1852     }
   1853 
   1854     public void setRingerModeInternal(int ringerMode, String caller) {
   1855         enforceSelfOrSystemUI("setRingerModeInternal");
   1856         setRingerMode(ringerMode, caller, false /*external*/);
   1857     }
   1858 
   1859     private void setRingerMode(int ringerMode, String caller, boolean external) {
   1860         if (mUseFixedVolume || isPlatformTelevision()) {
   1861             return;
   1862         }
   1863         if (caller == null || caller.length() == 0) {
   1864             throw new IllegalArgumentException("Bad caller: " + caller);
   1865         }
   1866         ensureValidRingerMode(ringerMode);
   1867         if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) {
   1868             ringerMode = AudioManager.RINGER_MODE_SILENT;
   1869         }
   1870         final long identity = Binder.clearCallingIdentity();
   1871         try {
   1872             synchronized (mSettingsLock) {
   1873                 final int ringerModeInternal = getRingerModeInternal();
   1874                 final int ringerModeExternal = getRingerModeExternal();
   1875                 if (external) {
   1876                     setRingerModeExt(ringerMode);
   1877                     if (mRingerModeDelegate != null) {
   1878                         ringerMode = mRingerModeDelegate.onSetRingerModeExternal(ringerModeExternal,
   1879                                 ringerMode, caller, ringerModeInternal);
   1880                     }
   1881                     if (ringerMode != ringerModeInternal) {
   1882                         setRingerModeInt(ringerMode, true /*persist*/);
   1883                     }
   1884                 } else /*internal*/ {
   1885                     if (ringerMode != ringerModeInternal) {
   1886                         setRingerModeInt(ringerMode, true /*persist*/);
   1887                     }
   1888                     if (mRingerModeDelegate != null) {
   1889                         ringerMode = mRingerModeDelegate.onSetRingerModeInternal(ringerModeInternal,
   1890                                 ringerMode, caller, ringerModeExternal);
   1891                     }
   1892                     setRingerModeExt(ringerMode);
   1893                 }
   1894             }
   1895         } finally {
   1896             Binder.restoreCallingIdentity(identity);
   1897         }
   1898     }
   1899 
   1900     private void setRingerModeExt(int ringerMode) {
   1901         synchronized(mSettingsLock) {
   1902             if (ringerMode == mRingerModeExternal) return;
   1903             mRingerModeExternal = ringerMode;
   1904         }
   1905         // Send sticky broadcast
   1906         broadcastRingerMode(AudioManager.RINGER_MODE_CHANGED_ACTION, ringerMode);
   1907     }
   1908 
   1909     private void setRingerModeInt(int ringerMode, boolean persist) {
   1910         final boolean change;
   1911         synchronized(mSettingsLock) {
   1912             change = mRingerMode != ringerMode;
   1913             mRingerMode = ringerMode;
   1914         }
   1915 
   1916         // Mute stream if not previously muted by ringer mode and ringer mode
   1917         // is not RINGER_MODE_NORMAL and stream is affected by ringer mode.
   1918         // Unmute stream if previously muted by ringer mode and ringer mode
   1919         // is RINGER_MODE_NORMAL or stream is not affected by ringer mode.
   1920         int numStreamTypes = AudioSystem.getNumStreamTypes();
   1921         final boolean ringerModeMute = ringerMode == AudioManager.RINGER_MODE_VIBRATE
   1922                 || ringerMode == AudioManager.RINGER_MODE_SILENT;
   1923         for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
   1924             final boolean isMuted = isStreamMutedByRingerMode(streamType);
   1925             final boolean shouldMute = ringerModeMute && isStreamAffectedByRingerMode(streamType);
   1926             if (isMuted == shouldMute) continue;
   1927             if (!shouldMute) {
   1928                 // unmute
   1929                 // ring and notifications volume should never be 0 when not silenced
   1930                 // on voice capable devices or devices that support vibration
   1931                 if ((isPlatformVoice() || mHasVibrator) &&
   1932                         mStreamVolumeAlias[streamType] == AudioSystem.STREAM_RING) {
   1933                     synchronized (VolumeStreamState.class) {
   1934                         Set set = mStreamStates[streamType].mIndex.entrySet();
   1935                         Iterator i = set.iterator();
   1936                         while (i.hasNext()) {
   1937                             Map.Entry entry = (Map.Entry)i.next();
   1938                             if ((Integer)entry.getValue() == 0) {
   1939                                 entry.setValue(10);
   1940                             }
   1941                         }
   1942                     }
   1943                 }
   1944                 mStreamStates[streamType].mute(null, false);
   1945                 mRingerModeMutedStreams &= ~(1 << streamType);
   1946             } else {
   1947                 // mute
   1948                 mStreamStates[streamType].mute(null, true);
   1949                 mRingerModeMutedStreams |= (1 << streamType);
   1950             }
   1951         }
   1952 
   1953         // Post a persist ringer mode msg
   1954         if (persist) {
   1955             sendMsg(mAudioHandler, MSG_PERSIST_RINGER_MODE,
   1956                     SENDMSG_REPLACE, 0, 0, null, PERSIST_DELAY);
   1957         }
   1958         if (change) {
   1959             // Send sticky broadcast
   1960             broadcastRingerMode(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION, ringerMode);
   1961         }
   1962     }
   1963 
   1964     private void restoreMasterVolume() {
   1965         if (mUseFixedVolume) {
   1966             AudioSystem.setMasterVolume(1.0f);
   1967             return;
   1968         }
   1969         if (mUseMasterVolume) {
   1970             float volume = Settings.System.getFloatForUser(mContentResolver,
   1971                     Settings.System.VOLUME_MASTER, -1.0f, UserHandle.USER_CURRENT);
   1972             if (volume >= 0.0f) {
   1973                 AudioSystem.setMasterVolume(volume);
   1974             }
   1975         }
   1976     }
   1977 
   1978     /** @see AudioManager#shouldVibrate(int) */
   1979     public boolean shouldVibrate(int vibrateType) {
   1980         if (!mHasVibrator) return false;
   1981 
   1982         switch (getVibrateSetting(vibrateType)) {
   1983 
   1984             case AudioManager.VIBRATE_SETTING_ON:
   1985                 return getRingerModeExternal() != AudioManager.RINGER_MODE_SILENT;
   1986 
   1987             case AudioManager.VIBRATE_SETTING_ONLY_SILENT:
   1988                 return getRingerModeExternal() == AudioManager.RINGER_MODE_VIBRATE;
   1989 
   1990             case AudioManager.VIBRATE_SETTING_OFF:
   1991                 // return false, even for incoming calls
   1992                 return false;
   1993 
   1994             default:
   1995                 return false;
   1996         }
   1997     }
   1998 
   1999     /** @see AudioManager#getVibrateSetting(int) */
   2000     public int getVibrateSetting(int vibrateType) {
   2001         if (!mHasVibrator) return AudioManager.VIBRATE_SETTING_OFF;
   2002         return (mVibrateSetting >> (vibrateType * 2)) & 3;
   2003     }
   2004 
   2005     /** @see AudioManager#setVibrateSetting(int, int) */
   2006     public void setVibrateSetting(int vibrateType, int vibrateSetting) {
   2007 
   2008         if (!mHasVibrator) return;
   2009 
   2010         mVibrateSetting = getValueForVibrateSetting(mVibrateSetting, vibrateType, vibrateSetting);
   2011 
   2012         // Broadcast change
   2013         broadcastVibrateSetting(vibrateType);
   2014 
   2015     }
   2016 
   2017     /**
   2018      * @see #setVibrateSetting(int, int)
   2019      */
   2020     public static int getValueForVibrateSetting(int existingValue, int vibrateType,
   2021             int vibrateSetting) {
   2022 
   2023         // First clear the existing setting. Each vibrate type has two bits in
   2024         // the value. Note '3' is '11' in binary.
   2025         existingValue &= ~(3 << (vibrateType * 2));
   2026 
   2027         // Set into the old value
   2028         existingValue |= (vibrateSetting & 3) << (vibrateType * 2);
   2029 
   2030         return existingValue;
   2031     }
   2032 
   2033     private class SetModeDeathHandler implements IBinder.DeathRecipient {
   2034         private IBinder mCb; // To be notified of client's death
   2035         private int mPid;
   2036         private int mMode = AudioSystem.MODE_NORMAL; // Current mode set by this client
   2037 
   2038         SetModeDeathHandler(IBinder cb, int pid) {
   2039             mCb = cb;
   2040             mPid = pid;
   2041         }
   2042 
   2043         public void binderDied() {
   2044             int newModeOwnerPid = 0;
   2045             synchronized(mSetModeDeathHandlers) {
   2046                 Log.w(TAG, "setMode() client died");
   2047                 int index = mSetModeDeathHandlers.indexOf(this);
   2048                 if (index < 0) {
   2049                     Log.w(TAG, "unregistered setMode() client died");
   2050                 } else {
   2051                     newModeOwnerPid = setModeInt(AudioSystem.MODE_NORMAL, mCb, mPid);
   2052                 }
   2053             }
   2054             // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
   2055             // SCO connections not started by the application changing the mode
   2056             if (newModeOwnerPid != 0) {
   2057                 final long ident = Binder.clearCallingIdentity();
   2058                 disconnectBluetoothSco(newModeOwnerPid);
   2059                 Binder.restoreCallingIdentity(ident);
   2060             }
   2061         }
   2062 
   2063         public int getPid() {
   2064             return mPid;
   2065         }
   2066 
   2067         public void setMode(int mode) {
   2068             mMode = mode;
   2069         }
   2070 
   2071         public int getMode() {
   2072             return mMode;
   2073         }
   2074 
   2075         public IBinder getBinder() {
   2076             return mCb;
   2077         }
   2078     }
   2079 
   2080     /** @see AudioManager#setMode(int) */
   2081     public void setMode(int mode, IBinder cb) {
   2082         if (DEBUG_MODE) { Log.v(TAG, "setMode(mode=" + mode + ")"); }
   2083         if (!checkAudioSettingsPermission("setMode()")) {
   2084             return;
   2085         }
   2086 
   2087         if ( (mode == AudioSystem.MODE_IN_CALL) &&
   2088                 (mContext.checkCallingOrSelfPermission(
   2089                         android.Manifest.permission.MODIFY_PHONE_STATE)
   2090                             != PackageManager.PERMISSION_GRANTED)) {
   2091             Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: setMode(MODE_IN_CALL) from pid="
   2092                     + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
   2093             return;
   2094         }
   2095 
   2096         if (mode < AudioSystem.MODE_CURRENT || mode >= AudioSystem.NUM_MODES) {
   2097             return;
   2098         }
   2099 
   2100         int newModeOwnerPid = 0;
   2101         synchronized(mSetModeDeathHandlers) {
   2102             if (mode == AudioSystem.MODE_CURRENT) {
   2103                 mode = mMode;
   2104             }
   2105             newModeOwnerPid = setModeInt(mode, cb, Binder.getCallingPid());
   2106         }
   2107         // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
   2108         // SCO connections not started by the application changing the mode
   2109         if (newModeOwnerPid != 0) {
   2110              disconnectBluetoothSco(newModeOwnerPid);
   2111         }
   2112     }
   2113 
   2114     // must be called synchronized on mSetModeDeathHandlers
   2115     // setModeInt() returns a valid PID if the audio mode was successfully set to
   2116     // any mode other than NORMAL.
   2117     private int setModeInt(int mode, IBinder cb, int pid) {
   2118         if (DEBUG_MODE) { Log.v(TAG, "setModeInt(mode=" + mode + ", pid=" + pid + ")"); }
   2119         int newModeOwnerPid = 0;
   2120         if (cb == null) {
   2121             Log.e(TAG, "setModeInt() called with null binder");
   2122             return newModeOwnerPid;
   2123         }
   2124 
   2125         SetModeDeathHandler hdlr = null;
   2126         Iterator iter = mSetModeDeathHandlers.iterator();
   2127         while (iter.hasNext()) {
   2128             SetModeDeathHandler h = (SetModeDeathHandler)iter.next();
   2129             if (h.getPid() == pid) {
   2130                 hdlr = h;
   2131                 // Remove from client list so that it is re-inserted at top of list
   2132                 iter.remove();
   2133                 hdlr.getBinder().unlinkToDeath(hdlr, 0);
   2134                 break;
   2135             }
   2136         }
   2137         int status = AudioSystem.AUDIO_STATUS_OK;
   2138         do {
   2139             if (mode == AudioSystem.MODE_NORMAL) {
   2140                 // get new mode from client at top the list if any
   2141                 if (!mSetModeDeathHandlers.isEmpty()) {
   2142                     hdlr = mSetModeDeathHandlers.get(0);
   2143                     cb = hdlr.getBinder();
   2144                     mode = hdlr.getMode();
   2145                     if (DEBUG_MODE) {
   2146                         Log.w(TAG, " using mode=" + mode + " instead due to death hdlr at pid="
   2147                                 + hdlr.mPid);
   2148                     }
   2149                 }
   2150             } else {
   2151                 if (hdlr == null) {
   2152                     hdlr = new SetModeDeathHandler(cb, pid);
   2153                 }
   2154                 // Register for client death notification
   2155                 try {
   2156                     cb.linkToDeath(hdlr, 0);
   2157                 } catch (RemoteException e) {
   2158                     // Client has died!
   2159                     Log.w(TAG, "setMode() could not link to "+cb+" binder death");
   2160                 }
   2161 
   2162                 // Last client to call setMode() is always at top of client list
   2163                 // as required by SetModeDeathHandler.binderDied()
   2164                 mSetModeDeathHandlers.add(0, hdlr);
   2165                 hdlr.setMode(mode);
   2166             }
   2167 
   2168             if (mode != mMode) {
   2169                 status = AudioSystem.setPhoneState(mode);
   2170                 if (status == AudioSystem.AUDIO_STATUS_OK) {
   2171                     if (DEBUG_MODE) { Log.v(TAG, " mode successfully set to " + mode); }
   2172                     mMode = mode;
   2173                 } else {
   2174                     if (hdlr != null) {
   2175                         mSetModeDeathHandlers.remove(hdlr);
   2176                         cb.unlinkToDeath(hdlr, 0);
   2177                     }
   2178                     // force reading new top of mSetModeDeathHandlers stack
   2179                     if (DEBUG_MODE) { Log.w(TAG, " mode set to MODE_NORMAL after phoneState pb"); }
   2180                     mode = AudioSystem.MODE_NORMAL;
   2181                 }
   2182             } else {
   2183                 status = AudioSystem.AUDIO_STATUS_OK;
   2184             }
   2185         } while (status != AudioSystem.AUDIO_STATUS_OK && !mSetModeDeathHandlers.isEmpty());
   2186 
   2187         if (status == AudioSystem.AUDIO_STATUS_OK) {
   2188             if (mode != AudioSystem.MODE_NORMAL) {
   2189                 if (mSetModeDeathHandlers.isEmpty()) {
   2190                     Log.e(TAG, "setMode() different from MODE_NORMAL with empty mode client stack");
   2191                 } else {
   2192                     newModeOwnerPid = mSetModeDeathHandlers.get(0).getPid();
   2193                 }
   2194             }
   2195             int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE);
   2196             int device = getDeviceForStream(streamType);
   2197             int index = mStreamStates[mStreamVolumeAlias[streamType]].getIndex(device);
   2198             setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, true);
   2199 
   2200             updateStreamVolumeAlias(true /*updateVolumes*/);
   2201         }
   2202         return newModeOwnerPid;
   2203     }
   2204 
   2205     /** @see AudioManager#getMode() */
   2206     public int getMode() {
   2207         return mMode;
   2208     }
   2209 
   2210     //==========================================================================================
   2211     // Sound Effects
   2212     //==========================================================================================
   2213 
   2214     private static final String TAG_AUDIO_ASSETS = "audio_assets";
   2215     private static final String ATTR_VERSION = "version";
   2216     private static final String TAG_GROUP = "group";
   2217     private static final String ATTR_GROUP_NAME = "name";
   2218     private static final String TAG_ASSET = "asset";
   2219     private static final String ATTR_ASSET_ID = "id";
   2220     private static final String ATTR_ASSET_FILE = "file";
   2221 
   2222     private static final String ASSET_FILE_VERSION = "1.0";
   2223     private static final String GROUP_TOUCH_SOUNDS = "touch_sounds";
   2224 
   2225     private static final int SOUND_EFFECTS_LOAD_TIMEOUT_MS = 5000;
   2226 
   2227     class LoadSoundEffectReply {
   2228         public int mStatus = 1;
   2229     };
   2230 
   2231     private void loadTouchSoundAssetDefaults() {
   2232         SOUND_EFFECT_FILES.add("Effect_Tick.ogg");
   2233         for (int i = 0; i < AudioManager.NUM_SOUND_EFFECTS; i++) {
   2234             SOUND_EFFECT_FILES_MAP[i][0] = 0;
   2235             SOUND_EFFECT_FILES_MAP[i][1] = -1;
   2236         }
   2237     }
   2238 
   2239     private void loadTouchSoundAssets() {
   2240         XmlResourceParser parser = null;
   2241 
   2242         // only load assets once.
   2243         if (!SOUND_EFFECT_FILES.isEmpty()) {
   2244             return;
   2245         }
   2246 
   2247         loadTouchSoundAssetDefaults();
   2248 
   2249         try {
   2250             parser = mContext.getResources().getXml(com.android.internal.R.xml.audio_assets);
   2251 
   2252             XmlUtils.beginDocument(parser, TAG_AUDIO_ASSETS);
   2253             String version = parser.getAttributeValue(null, ATTR_VERSION);
   2254             boolean inTouchSoundsGroup = false;
   2255 
   2256             if (ASSET_FILE_VERSION.equals(version)) {
   2257                 while (true) {
   2258                     XmlUtils.nextElement(parser);
   2259                     String element = parser.getName();
   2260                     if (element == null) {
   2261                         break;
   2262                     }
   2263                     if (element.equals(TAG_GROUP)) {
   2264                         String name = parser.getAttributeValue(null, ATTR_GROUP_NAME);
   2265                         if (GROUP_TOUCH_SOUNDS.equals(name)) {
   2266                             inTouchSoundsGroup = true;
   2267                             break;
   2268                         }
   2269                     }
   2270                 }
   2271                 while (inTouchSoundsGroup) {
   2272                     XmlUtils.nextElement(parser);
   2273                     String element = parser.getName();
   2274                     if (element == null) {
   2275                         break;
   2276                     }
   2277                     if (element.equals(TAG_ASSET)) {
   2278                         String id = parser.getAttributeValue(null, ATTR_ASSET_ID);
   2279                         String file = parser.getAttributeValue(null, ATTR_ASSET_FILE);
   2280                         int fx;
   2281 
   2282                         try {
   2283                             Field field = AudioManager.class.getField(id);
   2284                             fx = field.getInt(null);
   2285                         } catch (Exception e) {
   2286                             Log.w(TAG, "Invalid touch sound ID: "+id);
   2287                             continue;
   2288                         }
   2289 
   2290                         int i = SOUND_EFFECT_FILES.indexOf(file);
   2291                         if (i == -1) {
   2292                             i = SOUND_EFFECT_FILES.size();
   2293                             SOUND_EFFECT_FILES.add(file);
   2294                         }
   2295                         SOUND_EFFECT_FILES_MAP[fx][0] = i;
   2296                     } else {
   2297                         break;
   2298                     }
   2299                 }
   2300             }
   2301         } catch (Resources.NotFoundException e) {
   2302             Log.w(TAG, "audio assets file not found", e);
   2303         } catch (XmlPullParserException e) {
   2304             Log.w(TAG, "XML parser exception reading touch sound assets", e);
   2305         } catch (IOException e) {
   2306             Log.w(TAG, "I/O exception reading touch sound assets", e);
   2307         } finally {
   2308             if (parser != null) {
   2309                 parser.close();
   2310             }
   2311         }
   2312     }
   2313 
   2314     /** @see AudioManager#playSoundEffect(int) */
   2315     public void playSoundEffect(int effectType) {
   2316         playSoundEffectVolume(effectType, -1.0f);
   2317     }
   2318 
   2319     /** @see AudioManager#playSoundEffect(int, float) */
   2320     public void playSoundEffectVolume(int effectType, float volume) {
   2321         if (effectType >= AudioManager.NUM_SOUND_EFFECTS || effectType < 0) {
   2322             Log.w(TAG, "AudioService effectType value " + effectType + " out of range");
   2323             return;
   2324         }
   2325 
   2326         sendMsg(mAudioHandler, MSG_PLAY_SOUND_EFFECT, SENDMSG_QUEUE,
   2327                 effectType, (int) (volume * 1000), null, 0);
   2328     }
   2329 
   2330     /**
   2331      * Loads samples into the soundpool.
   2332      * This method must be called at first when sound effects are enabled
   2333      */
   2334     public boolean loadSoundEffects() {
   2335         int attempts = 3;
   2336         LoadSoundEffectReply reply = new LoadSoundEffectReply();
   2337 
   2338         synchronized (reply) {
   2339             sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, reply, 0);
   2340             while ((reply.mStatus == 1) && (attempts-- > 0)) {
   2341                 try {
   2342                     reply.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
   2343                 } catch (InterruptedException e) {
   2344                     Log.w(TAG, "loadSoundEffects Interrupted while waiting sound pool loaded.");
   2345                 }
   2346             }
   2347         }
   2348         return (reply.mStatus == 0);
   2349     }
   2350 
   2351     /**
   2352      *  Unloads samples from the sound pool.
   2353      *  This method can be called to free some memory when
   2354      *  sound effects are disabled.
   2355      */
   2356     public void unloadSoundEffects() {
   2357         sendMsg(mAudioHandler, MSG_UNLOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, null, 0);
   2358     }
   2359 
   2360     class SoundPoolListenerThread extends Thread {
   2361         public SoundPoolListenerThread() {
   2362             super("SoundPoolListenerThread");
   2363         }
   2364 
   2365         @Override
   2366         public void run() {
   2367 
   2368             Looper.prepare();
   2369             mSoundPoolLooper = Looper.myLooper();
   2370 
   2371             synchronized (mSoundEffectsLock) {
   2372                 if (mSoundPool != null) {
   2373                     mSoundPoolCallBack = new SoundPoolCallback();
   2374                     mSoundPool.setOnLoadCompleteListener(mSoundPoolCallBack);
   2375                 }
   2376                 mSoundEffectsLock.notify();
   2377             }
   2378             Looper.loop();
   2379         }
   2380     }
   2381 
   2382     private final class SoundPoolCallback implements
   2383             android.media.SoundPool.OnLoadCompleteListener {
   2384 
   2385         int mStatus = 1; // 1 means neither error nor last sample loaded yet
   2386         List<Integer> mSamples = new ArrayList<Integer>();
   2387 
   2388         public int status() {
   2389             return mStatus;
   2390         }
   2391 
   2392         public void setSamples(int[] samples) {
   2393             for (int i = 0; i < samples.length; i++) {
   2394                 // do not wait ack for samples rejected upfront by SoundPool
   2395                 if (samples[i] > 0) {
   2396                     mSamples.add(samples[i]);
   2397                 }
   2398             }
   2399         }
   2400 
   2401         public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
   2402             synchronized (mSoundEffectsLock) {
   2403                 int i = mSamples.indexOf(sampleId);
   2404                 if (i >= 0) {
   2405                     mSamples.remove(i);
   2406                 }
   2407                 if ((status != 0) || mSamples. isEmpty()) {
   2408                     mStatus = status;
   2409                     mSoundEffectsLock.notify();
   2410                 }
   2411             }
   2412         }
   2413     }
   2414 
   2415     /** @see AudioManager#reloadAudioSettings() */
   2416     public void reloadAudioSettings() {
   2417         readAudioSettings(false /*userSwitch*/);
   2418     }
   2419 
   2420     private void readAudioSettings(boolean userSwitch) {
   2421         // restore ringer mode, ringer mode affected streams, mute affected streams and vibrate settings
   2422         readPersistedSettings();
   2423 
   2424         // restore volume settings
   2425         int numStreamTypes = AudioSystem.getNumStreamTypes();
   2426         for (int streamType = 0; streamType < numStreamTypes; streamType++) {
   2427             VolumeStreamState streamState = mStreamStates[streamType];
   2428 
   2429             if (userSwitch && mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) {
   2430                 continue;
   2431             }
   2432 
   2433             streamState.readSettings();
   2434             synchronized (VolumeStreamState.class) {
   2435                 // unmute stream that was muted but is not affect by mute anymore
   2436                 if (streamState.isMuted_syncVSS() && ((!isStreamAffectedByMute(streamType) &&
   2437                         !isStreamMutedByRingerMode(streamType)) || mUseFixedVolume)) {
   2438                     int size = streamState.mDeathHandlers.size();
   2439                     for (int i = 0; i < size; i++) {
   2440                         streamState.mDeathHandlers.get(i).mMuteCount = 1;
   2441                         streamState.mDeathHandlers.get(i).mute_syncVSS(false);
   2442                     }
   2443                 }
   2444             }
   2445         }
   2446 
   2447         // apply new ringer mode before checking volume for alias streams so that streams
   2448         // muted by ringer mode have the correct volume
   2449         setRingerModeInt(getRingerModeInternal(), false);
   2450 
   2451         checkAllFixedVolumeDevices();
   2452         checkAllAliasStreamVolumes();
   2453 
   2454         synchronized (mSafeMediaVolumeState) {
   2455             mMusicActiveMs = MathUtils.constrain(Settings.Secure.getIntForUser(mContentResolver,
   2456                     Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS, 0, UserHandle.USER_CURRENT),
   2457                     0, UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX);
   2458             if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) {
   2459                 enforceSafeMediaVolume();
   2460             }
   2461         }
   2462     }
   2463 
   2464     /** @see AudioManager#setSpeakerphoneOn(boolean) */
   2465     public void setSpeakerphoneOn(boolean on){
   2466         if (!checkAudioSettingsPermission("setSpeakerphoneOn()")) {
   2467             return;
   2468         }
   2469 
   2470         if (on) {
   2471             if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
   2472                     sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
   2473                             AudioSystem.FOR_RECORD, AudioSystem.FORCE_NONE, null, 0);
   2474             }
   2475             mForcedUseForComm = AudioSystem.FORCE_SPEAKER;
   2476         } else if (mForcedUseForComm == AudioSystem.FORCE_SPEAKER){
   2477             mForcedUseForComm = AudioSystem.FORCE_NONE;
   2478         }
   2479 
   2480         sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
   2481                 AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, null, 0);
   2482     }
   2483 
   2484     /** @see AudioManager#isSpeakerphoneOn() */
   2485     public boolean isSpeakerphoneOn() {
   2486         return (mForcedUseForComm == AudioSystem.FORCE_SPEAKER);
   2487     }
   2488 
   2489     /** @see AudioManager#setBluetoothScoOn(boolean) */
   2490     public void setBluetoothScoOn(boolean on){
   2491         if (!checkAudioSettingsPermission("setBluetoothScoOn()")) {
   2492             return;
   2493         }
   2494 
   2495         if (on) {
   2496             mForcedUseForComm = AudioSystem.FORCE_BT_SCO;
   2497         } else if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
   2498             mForcedUseForComm = AudioSystem.FORCE_NONE;
   2499         }
   2500 
   2501         sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
   2502                 AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, null, 0);
   2503         sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
   2504                 AudioSystem.FOR_RECORD, mForcedUseForComm, null, 0);
   2505     }
   2506 
   2507     /** @see AudioManager#isBluetoothScoOn() */
   2508     public boolean isBluetoothScoOn() {
   2509         return (mForcedUseForComm == AudioSystem.FORCE_BT_SCO);
   2510     }
   2511 
   2512     /** @see AudioManager#setBluetoothA2dpOn(boolean) */
   2513     public void setBluetoothA2dpOn(boolean on) {
   2514         synchronized (mBluetoothA2dpEnabledLock) {
   2515             mBluetoothA2dpEnabled = on;
   2516             sendMsg(mAudioHandler, MSG_SET_FORCE_BT_A2DP_USE, SENDMSG_QUEUE,
   2517                     AudioSystem.FOR_MEDIA,
   2518                     mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP,
   2519                     null, 0);
   2520         }
   2521     }
   2522 
   2523     /** @see AudioManager#isBluetoothA2dpOn() */
   2524     public boolean isBluetoothA2dpOn() {
   2525         synchronized (mBluetoothA2dpEnabledLock) {
   2526             return mBluetoothA2dpEnabled;
   2527         }
   2528     }
   2529 
   2530     /** @see AudioManager#startBluetoothSco() */
   2531     public void startBluetoothSco(IBinder cb, int targetSdkVersion) {
   2532         int scoAudioMode =
   2533                 (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR2) ?
   2534                         SCO_MODE_VIRTUAL_CALL : SCO_MODE_UNDEFINED;
   2535         startBluetoothScoInt(cb, scoAudioMode);
   2536     }
   2537 
   2538     /** @see AudioManager#startBluetoothScoVirtualCall() */
   2539     public void startBluetoothScoVirtualCall(IBinder cb) {
   2540         startBluetoothScoInt(cb, SCO_MODE_VIRTUAL_CALL);
   2541     }
   2542 
   2543     void startBluetoothScoInt(IBinder cb, int scoAudioMode){
   2544         if (!checkAudioSettingsPermission("startBluetoothSco()") ||
   2545                 !mSystemReady) {
   2546             return;
   2547         }
   2548         ScoClient client = getScoClient(cb, true);
   2549         // The calling identity must be cleared before calling ScoClient.incCount().
   2550         // inCount() calls requestScoState() which in turn can call BluetoothHeadset APIs
   2551         // and this must be done on behalf of system server to make sure permissions are granted.
   2552         // The caller identity must be cleared after getScoClient() because it is needed if a new
   2553         // client is created.
   2554         final long ident = Binder.clearCallingIdentity();
   2555         client.incCount(scoAudioMode);
   2556         Binder.restoreCallingIdentity(ident);
   2557     }
   2558 
   2559     /** @see AudioManager#stopBluetoothSco() */
   2560     public void stopBluetoothSco(IBinder cb){
   2561         if (!checkAudioSettingsPermission("stopBluetoothSco()") ||
   2562                 !mSystemReady) {
   2563             return;
   2564         }
   2565         ScoClient client = getScoClient(cb, false);
   2566         // The calling identity must be cleared before calling ScoClient.decCount().
   2567         // decCount() calls requestScoState() which in turn can call BluetoothHeadset APIs
   2568         // and this must be done on behalf of system server to make sure permissions are granted.
   2569         final long ident = Binder.clearCallingIdentity();
   2570         if (client != null) {
   2571             client.decCount();
   2572         }
   2573         Binder.restoreCallingIdentity(ident);
   2574     }
   2575 
   2576 
   2577     private class ScoClient implements IBinder.DeathRecipient {
   2578         private IBinder mCb; // To be notified of client's death
   2579         private int mCreatorPid;
   2580         private int mStartcount; // number of SCO connections started by this client
   2581 
   2582         ScoClient(IBinder cb) {
   2583             mCb = cb;
   2584             mCreatorPid = Binder.getCallingPid();
   2585             mStartcount = 0;
   2586         }
   2587 
   2588         public void binderDied() {
   2589             synchronized(mScoClients) {
   2590                 Log.w(TAG, "SCO client died");
   2591                 int index = mScoClients.indexOf(this);
   2592                 if (index < 0) {
   2593                     Log.w(TAG, "unregistered SCO client died");
   2594                 } else {
   2595                     clearCount(true);
   2596                     mScoClients.remove(this);
   2597                 }
   2598             }
   2599         }
   2600 
   2601         public void incCount(int scoAudioMode) {
   2602             synchronized(mScoClients) {
   2603                 requestScoState(BluetoothHeadset.STATE_AUDIO_CONNECTED, scoAudioMode);
   2604                 if (mStartcount == 0) {
   2605                     try {
   2606                         mCb.linkToDeath(this, 0);
   2607                     } catch (RemoteException e) {
   2608                         // client has already died!
   2609                         Log.w(TAG, "ScoClient  incCount() could not link to "+mCb+" binder death");
   2610                     }
   2611                 }
   2612                 mStartcount++;
   2613             }
   2614         }
   2615 
   2616         public void decCount() {
   2617             synchronized(mScoClients) {
   2618                 if (mStartcount == 0) {
   2619                     Log.w(TAG, "ScoClient.decCount() already 0");
   2620                 } else {
   2621                     mStartcount--;
   2622                     if (mStartcount == 0) {
   2623                         try {
   2624                             mCb.unlinkToDeath(this, 0);
   2625                         } catch (NoSuchElementException e) {
   2626                             Log.w(TAG, "decCount() going to 0 but not registered to binder");
   2627                         }
   2628                     }
   2629                     requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, 0);
   2630                 }
   2631             }
   2632         }
   2633 
   2634         public void clearCount(boolean stopSco) {
   2635             synchronized(mScoClients) {
   2636                 if (mStartcount != 0) {
   2637                     try {
   2638                         mCb.unlinkToDeath(this, 0);
   2639                     } catch (NoSuchElementException e) {
   2640                         Log.w(TAG, "clearCount() mStartcount: "+mStartcount+" != 0 but not registered to binder");
   2641                     }
   2642                 }
   2643                 mStartcount = 0;
   2644                 if (stopSco) {
   2645                     requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, 0);
   2646                 }
   2647             }
   2648         }
   2649 
   2650         public int getCount() {
   2651             return mStartcount;
   2652         }
   2653 
   2654         public IBinder getBinder() {
   2655             return mCb;
   2656         }
   2657 
   2658         public int getPid() {
   2659             return mCreatorPid;
   2660         }
   2661 
   2662         public int totalCount() {
   2663             synchronized(mScoClients) {
   2664                 int count = 0;
   2665                 int size = mScoClients.size();
   2666                 for (int i = 0; i < size; i++) {
   2667                     count += mScoClients.get(i).getCount();
   2668                 }
   2669                 return count;
   2670             }
   2671         }
   2672 
   2673         private void requestScoState(int state, int scoAudioMode) {
   2674             checkScoAudioState();
   2675             if (totalCount() == 0) {
   2676                 if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) {
   2677                     // Make sure that the state transitions to CONNECTING even if we cannot initiate
   2678                     // the connection.
   2679                     broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTING);
   2680                     // Accept SCO audio activation only in NORMAL audio mode or if the mode is
   2681                     // currently controlled by the same client process.
   2682                     synchronized(mSetModeDeathHandlers) {
   2683                         if ((mSetModeDeathHandlers.isEmpty() ||
   2684                                 mSetModeDeathHandlers.get(0).getPid() == mCreatorPid) &&
   2685                                 (mScoAudioState == SCO_STATE_INACTIVE ||
   2686                                  mScoAudioState == SCO_STATE_DEACTIVATE_REQ)) {
   2687                             if (mScoAudioState == SCO_STATE_INACTIVE) {
   2688                                 mScoAudioMode = scoAudioMode;
   2689                                 if (scoAudioMode == SCO_MODE_UNDEFINED) {
   2690                                     if (mBluetoothHeadsetDevice != null) {
   2691                                         mScoAudioMode = new Integer(Settings.Global.getInt(
   2692                                                                 mContentResolver,
   2693                                                                 "bluetooth_sco_channel_"+
   2694                                                                 mBluetoothHeadsetDevice.getAddress(),
   2695                                                                 SCO_MODE_VIRTUAL_CALL));
   2696                                         if (mScoAudioMode > SCO_MODE_MAX || mScoAudioMode < 0) {
   2697                                             mScoAudioMode = SCO_MODE_VIRTUAL_CALL;
   2698                                         }
   2699                                     } else {
   2700                                         mScoAudioMode = SCO_MODE_RAW;
   2701                                     }
   2702                                 }
   2703                                 if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) {
   2704                                     boolean status = false;
   2705                                     if (mScoAudioMode == SCO_MODE_RAW) {
   2706                                         status = mBluetoothHeadset.connectAudio();
   2707                                     } else if (mScoAudioMode == SCO_MODE_VIRTUAL_CALL) {
   2708                                         status = mBluetoothHeadset.startScoUsingVirtualVoiceCall(
   2709                                                                             mBluetoothHeadsetDevice);
   2710                                     } else if (mScoAudioMode == SCO_MODE_VR) {
   2711                                         status = mBluetoothHeadset.startVoiceRecognition(
   2712                                                                            mBluetoothHeadsetDevice);
   2713                                     }
   2714 
   2715                                     if (status) {
   2716                                         mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
   2717                                     } else {
   2718                                         broadcastScoConnectionState(
   2719                                                 AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
   2720                                     }
   2721                                 } else if (getBluetoothHeadset()) {
   2722                                     mScoAudioState = SCO_STATE_ACTIVATE_REQ;
   2723                                 }
   2724                             } else {
   2725                                 mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
   2726                                 broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTED);
   2727                             }
   2728                         } else {
   2729                             broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
   2730                         }
   2731                     }
   2732                 } else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED &&
   2733                               (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL ||
   2734                                mScoAudioState == SCO_STATE_ACTIVATE_REQ)) {
   2735                     if (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL) {
   2736                         if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) {
   2737                             boolean status = false;
   2738                             if (mScoAudioMode == SCO_MODE_RAW) {
   2739                                 status = mBluetoothHeadset.disconnectAudio();
   2740                             } else if (mScoAudioMode == SCO_MODE_VIRTUAL_CALL) {
   2741                                 status = mBluetoothHeadset.stopScoUsingVirtualVoiceCall(
   2742                                                                         mBluetoothHeadsetDevice);
   2743                             } else if (mScoAudioMode == SCO_MODE_VR) {
   2744                                         status = mBluetoothHeadset.stopVoiceRecognition(
   2745                                                                       mBluetoothHeadsetDevice);
   2746                             }
   2747 
   2748                             if (!status) {
   2749                                 mScoAudioState = SCO_STATE_INACTIVE;
   2750                                 broadcastScoConnectionState(
   2751                                         AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
   2752                             }
   2753                         } else if (getBluetoothHeadset()) {
   2754                             mScoAudioState = SCO_STATE_DEACTIVATE_REQ;
   2755                         }
   2756                     } else {
   2757                         mScoAudioState = SCO_STATE_INACTIVE;
   2758                         broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
   2759                     }
   2760                 }
   2761             }
   2762         }
   2763     }
   2764 
   2765     private void checkScoAudioState() {
   2766         if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null &&
   2767                 mScoAudioState == SCO_STATE_INACTIVE &&
   2768                 mBluetoothHeadset.getAudioState(mBluetoothHeadsetDevice)
   2769                 != BluetoothHeadset.STATE_AUDIO_DISCONNECTED) {
   2770             mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL;
   2771         }
   2772     }
   2773 
   2774     private ScoClient getScoClient(IBinder cb, boolean create) {
   2775         synchronized(mScoClients) {
   2776             ScoClient client = null;
   2777             int size = mScoClients.size();
   2778             for (int i = 0; i < size; i++) {
   2779                 client = mScoClients.get(i);
   2780                 if (client.getBinder() == cb)
   2781                     return client;
   2782             }
   2783             if (create) {
   2784                 client = new ScoClient(cb);
   2785                 mScoClients.add(client);
   2786             }
   2787             return client;
   2788         }
   2789     }
   2790 
   2791     public void clearAllScoClients(int exceptPid, boolean stopSco) {
   2792         synchronized(mScoClients) {
   2793             ScoClient savedClient = null;
   2794             int size = mScoClients.size();
   2795             for (int i = 0; i < size; i++) {
   2796                 ScoClient cl = mScoClients.get(i);
   2797                 if (cl.getPid() != exceptPid) {
   2798                     cl.clearCount(stopSco);
   2799                 } else {
   2800                     savedClient = cl;
   2801                 }
   2802             }
   2803             mScoClients.clear();
   2804             if (savedClient != null) {
   2805                 mScoClients.add(savedClient);
   2806             }
   2807         }
   2808     }
   2809 
   2810     private boolean getBluetoothHeadset() {
   2811         boolean result = false;
   2812         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
   2813         if (adapter != null) {
   2814             result = adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
   2815                                     BluetoothProfile.HEADSET);
   2816         }
   2817         // If we could not get a bluetooth headset proxy, send a failure message
   2818         // without delay to reset the SCO audio state and clear SCO clients.
   2819         // If we could get a proxy, send a delayed failure message that will reset our state
   2820         // in case we don't receive onServiceConnected().
   2821         sendMsg(mAudioHandler, MSG_BT_HEADSET_CNCT_FAILED,
   2822                 SENDMSG_REPLACE, 0, 0, null, result ? BT_HEADSET_CNCT_TIMEOUT_MS : 0);
   2823         return result;
   2824     }
   2825 
   2826     private void disconnectBluetoothSco(int exceptPid) {
   2827         synchronized(mScoClients) {
   2828             checkScoAudioState();
   2829             if (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL ||
   2830                     mScoAudioState == SCO_STATE_DEACTIVATE_EXT_REQ) {
   2831                 if (mBluetoothHeadsetDevice != null) {
   2832                     if (mBluetoothHeadset != null) {
   2833                         if (!mBluetoothHeadset.stopVoiceRecognition(
   2834                                 mBluetoothHeadsetDevice)) {
   2835                             sendMsg(mAudioHandler, MSG_BT_HEADSET_CNCT_FAILED,
   2836                                     SENDMSG_REPLACE, 0, 0, null, 0);
   2837                         }
   2838                     } else if (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL &&
   2839                             getBluetoothHeadset()) {
   2840                         mScoAudioState = SCO_STATE_DEACTIVATE_EXT_REQ;
   2841                     }
   2842                 }
   2843             } else {
   2844                 clearAllScoClients(exceptPid, true);
   2845             }
   2846         }
   2847     }
   2848 
   2849     private void resetBluetoothSco() {
   2850         synchronized(mScoClients) {
   2851             clearAllScoClients(0, false);
   2852             mScoAudioState = SCO_STATE_INACTIVE;
   2853             broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
   2854         }
   2855     }
   2856 
   2857     private void broadcastScoConnectionState(int state) {
   2858         sendMsg(mAudioHandler, MSG_BROADCAST_BT_CONNECTION_STATE,
   2859                 SENDMSG_QUEUE, state, 0, null, 0);
   2860     }
   2861 
   2862     private void onBroadcastScoConnectionState(int state) {
   2863         if (state != mScoConnectionState) {
   2864             Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
   2865             newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, state);
   2866             newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_PREVIOUS_STATE,
   2867                     mScoConnectionState);
   2868             sendStickyBroadcastToAll(newIntent);
   2869             mScoConnectionState = state;
   2870         }
   2871     }
   2872 
   2873     private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
   2874         new BluetoothProfile.ServiceListener() {
   2875         public void onServiceConnected(int profile, BluetoothProfile proxy) {
   2876             BluetoothDevice btDevice;
   2877             List<BluetoothDevice> deviceList;
   2878             switch(profile) {
   2879             case BluetoothProfile.A2DP:
   2880                 synchronized (mA2dpAvrcpLock) {
   2881                     mA2dp = (BluetoothA2dp) proxy;
   2882                     deviceList = mA2dp.getConnectedDevices();
   2883                     if (deviceList.size() > 0) {
   2884                         btDevice = deviceList.get(0);
   2885                         synchronized (mConnectedDevices) {
   2886                             int state = mA2dp.getConnectionState(btDevice);
   2887                             int delay = checkSendBecomingNoisyIntent(
   2888                                                 AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
   2889                                                 (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0);
   2890                             queueMsgUnderWakeLock(mAudioHandler,
   2891                                     MSG_SET_A2DP_SINK_CONNECTION_STATE,
   2892                                     state,
   2893                                     0,
   2894                                     btDevice,
   2895                                     delay);
   2896                         }
   2897                     }
   2898                 }
   2899                 break;
   2900 
   2901             case BluetoothProfile.A2DP_SINK:
   2902                 deviceList = proxy.getConnectedDevices();
   2903                 if (deviceList.size() > 0) {
   2904                     btDevice = deviceList.get(0);
   2905                     synchronized (mConnectedDevices) {
   2906                         int state = proxy.getConnectionState(btDevice);
   2907                         queueMsgUnderWakeLock(mAudioHandler,
   2908                                 MSG_SET_A2DP_SRC_CONNECTION_STATE,
   2909                                 state,
   2910                                 0,
   2911                                 btDevice,
   2912                                 0 /* delay */);
   2913                     }
   2914                 }
   2915                 break;
   2916 
   2917             case BluetoothProfile.HEADSET:
   2918                 synchronized (mScoClients) {
   2919                     // Discard timeout message
   2920                     mAudioHandler.removeMessages(MSG_BT_HEADSET_CNCT_FAILED);
   2921                     mBluetoothHeadset = (BluetoothHeadset) proxy;
   2922                     deviceList = mBluetoothHeadset.getConnectedDevices();
   2923                     if (deviceList.size() > 0) {
   2924                         mBluetoothHeadsetDevice = deviceList.get(0);
   2925                     } else {
   2926                         mBluetoothHeadsetDevice = null;
   2927                     }
   2928                     // Refresh SCO audio state
   2929                     checkScoAudioState();
   2930                     // Continue pending action if any
   2931                     if (mScoAudioState == SCO_STATE_ACTIVATE_REQ ||
   2932                             mScoAudioState == SCO_STATE_DEACTIVATE_REQ ||
   2933                             mScoAudioState == SCO_STATE_DEACTIVATE_EXT_REQ) {
   2934                         boolean status = false;
   2935                         if (mBluetoothHeadsetDevice != null) {
   2936                             switch (mScoAudioState) {
   2937                             case SCO_STATE_ACTIVATE_REQ:
   2938                                 mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
   2939                                 if (mScoAudioMode == SCO_MODE_RAW) {
   2940                                     status = mBluetoothHeadset.connectAudio();
   2941                                 } else if (mScoAudioMode == SCO_MODE_VIRTUAL_CALL) {
   2942                                     status = mBluetoothHeadset.startScoUsingVirtualVoiceCall(
   2943                                                                         mBluetoothHeadsetDevice);
   2944                                 } else if (mScoAudioMode == SCO_MODE_VR) {
   2945                                     status = mBluetoothHeadset.startVoiceRecognition(
   2946                                                                       mBluetoothHeadsetDevice);
   2947                                 }
   2948                                 break;
   2949                             case SCO_STATE_DEACTIVATE_REQ:
   2950                                 if (mScoAudioMode == SCO_MODE_RAW) {
   2951                                     status = mBluetoothHeadset.disconnectAudio();
   2952                                 } else if (mScoAudioMode == SCO_MODE_VIRTUAL_CALL) {
   2953                                     status = mBluetoothHeadset.stopScoUsingVirtualVoiceCall(
   2954                                                                         mBluetoothHeadsetDevice);
   2955                                 } else if (mScoAudioMode == SCO_MODE_VR) {
   2956                                     status = mBluetoothHeadset.stopVoiceRecognition(
   2957                                                                       mBluetoothHeadsetDevice);
   2958                                 }
   2959                                 break;
   2960                             case SCO_STATE_DEACTIVATE_EXT_REQ:
   2961                                 status = mBluetoothHeadset.stopVoiceRecognition(
   2962                                         mBluetoothHeadsetDevice);
   2963                             }
   2964                         }
   2965                         if (!status) {
   2966                             sendMsg(mAudioHandler, MSG_BT_HEADSET_CNCT_FAILED,
   2967                                     SENDMSG_REPLACE, 0, 0, null, 0);
   2968                         }
   2969                     }
   2970                 }
   2971                 break;
   2972 
   2973             default:
   2974                 break;
   2975             }
   2976         }
   2977         public void onServiceDisconnected(int profile) {
   2978             switch(profile) {
   2979             case BluetoothProfile.A2DP:
   2980                 synchronized (mA2dpAvrcpLock) {
   2981                     mA2dp = null;
   2982                     synchronized (mConnectedDevices) {
   2983                         if (mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP)) {
   2984                             makeA2dpDeviceUnavailableNow(
   2985                                     mConnectedDevices.get(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP));
   2986                         }
   2987                     }
   2988                 }
   2989                 break;
   2990 
   2991             case BluetoothProfile.A2DP_SINK:
   2992                 synchronized (mConnectedDevices) {
   2993                     if (mConnectedDevices.containsKey(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP)) {
   2994                         makeA2dpSrcUnavailable(
   2995                                 mConnectedDevices.get(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP));
   2996                     }
   2997                 }
   2998                 break;
   2999 
   3000             case BluetoothProfile.HEADSET:
   3001                 synchronized (mScoClients) {
   3002                     mBluetoothHeadset = null;
   3003                 }
   3004                 break;
   3005 
   3006             default:
   3007                 break;
   3008             }
   3009         }
   3010     };
   3011 
   3012     private void onCheckMusicActive() {
   3013         synchronized (mSafeMediaVolumeState) {
   3014             if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE) {
   3015                 int device = getDeviceForStream(AudioSystem.STREAM_MUSIC);
   3016 
   3017                 if ((device & mSafeMediaVolumeDevices) != 0) {
   3018                     sendMsg(mAudioHandler,
   3019                             MSG_CHECK_MUSIC_ACTIVE,
   3020                             SENDMSG_REPLACE,
   3021                             0,
   3022                             0,
   3023                             null,
   3024                             MUSIC_ACTIVE_POLL_PERIOD_MS);
   3025                     int index = mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(device);
   3026                     if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0) &&
   3027                             (index > mSafeMediaVolumeIndex)) {
   3028                         // Approximate cumulative active music time
   3029                         mMusicActiveMs += MUSIC_ACTIVE_POLL_PERIOD_MS;
   3030                         if (mMusicActiveMs > UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX) {
   3031                             setSafeMediaVolumeEnabled(true);
   3032                             mMusicActiveMs = 0;
   3033                         }
   3034                         saveMusicActiveMs();
   3035                     }
   3036                 }
   3037             }
   3038         }
   3039     }
   3040 
   3041     private void saveMusicActiveMs() {
   3042         mAudioHandler.obtainMessage(MSG_PERSIST_MUSIC_ACTIVE_MS, mMusicActiveMs, 0).sendToTarget();
   3043     }
   3044 
   3045     private void onConfigureSafeVolume(boolean force) {
   3046         synchronized (mSafeMediaVolumeState) {
   3047             int mcc = mContext.getResources().getConfiguration().mcc;
   3048             if ((mMcc != mcc) || ((mMcc == 0) && force)) {
   3049                 mSafeMediaVolumeIndex = mContext.getResources().getInteger(
   3050                         com.android.internal.R.integer.config_safe_media_volume_index) * 10;
   3051                 boolean safeMediaVolumeEnabled =
   3052                         SystemProperties.getBoolean("audio.safemedia.force", false)
   3053                         || mContext.getResources().getBoolean(
   3054                                 com.android.internal.R.bool.config_safe_media_volume_enabled);
   3055 
   3056                 // The persisted state is either "disabled" or "active": this is the state applied
   3057                 // next time we boot and cannot be "inactive"
   3058                 int persistedState;
   3059                 if (safeMediaVolumeEnabled) {
   3060                     persistedState = SAFE_MEDIA_VOLUME_ACTIVE;
   3061                     // The state can already be "inactive" here if the user has forced it before
   3062                     // the 30 seconds timeout for forced configuration. In this case we don't reset
   3063                     // it to "active".
   3064                     if (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_INACTIVE) {
   3065                         if (mMusicActiveMs == 0) {
   3066                             mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE;
   3067                             enforceSafeMediaVolume();
   3068                         } else {
   3069                             // We have existing playback time recorded, already confirmed.
   3070                             mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE;
   3071                         }
   3072                     }
   3073                 } else {
   3074                     persistedState = SAFE_MEDIA_VOLUME_DISABLED;
   3075                     mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_DISABLED;
   3076                 }
   3077                 mMcc = mcc;
   3078                 sendMsg(mAudioHandler,
   3079                         MSG_PERSIST_SAFE_VOLUME_STATE,
   3080                         SENDMSG_QUEUE,
   3081                         persistedState,
   3082                         0,
   3083                         null,
   3084                         0);
   3085             }
   3086         }
   3087     }
   3088 
   3089     ///////////////////////////////////////////////////////////////////////////
   3090     // Internal methods
   3091     ///////////////////////////////////////////////////////////////////////////
   3092 
   3093     /**
   3094      * Checks if the adjustment should change ringer mode instead of just
   3095      * adjusting volume. If so, this will set the proper ringer mode and volume
   3096      * indices on the stream states.
   3097      */
   3098     private int checkForRingerModeChange(int oldIndex, int direction,  int step) {
   3099         int result = FLAG_ADJUST_VOLUME;
   3100         int ringerMode = getRingerModeInternal();
   3101 
   3102         switch (ringerMode) {
   3103         case RINGER_MODE_NORMAL:
   3104             if (direction == AudioManager.ADJUST_LOWER) {
   3105                 if (mHasVibrator) {
   3106                     // "step" is the delta in internal index units corresponding to a
   3107                     // change of 1 in UI index units.
   3108                     // Because of rounding when rescaling from one stream index range to its alias
   3109                     // index range, we cannot simply test oldIndex == step:
   3110                     //   (step <= oldIndex < 2 * step) is equivalent to: (old UI index == 1)
   3111                     if (step <= oldIndex && oldIndex < 2 * step) {
   3112                         ringerMode = RINGER_MODE_VIBRATE;
   3113                     }
   3114                 } else {
   3115                     // (oldIndex < step) is equivalent to (old UI index == 0)
   3116                     if ((oldIndex < step)
   3117                             && VOLUME_SETS_RINGER_MODE_SILENT
   3118                             && mPrevVolDirection != AudioManager.ADJUST_LOWER) {
   3119                         ringerMode = RINGER_MODE_SILENT;
   3120                     }
   3121                 }
   3122             }
   3123             break;
   3124         case RINGER_MODE_VIBRATE:
   3125             if (!mHasVibrator) {
   3126                 Log.e(TAG, "checkForRingerModeChange() current ringer mode is vibrate" +
   3127                         "but no vibrator is present");
   3128                 break;
   3129             }
   3130             if ((direction == AudioManager.ADJUST_LOWER)) {
   3131                 if (mPrevVolDirection != AudioManager.ADJUST_LOWER) {
   3132                     if (VOLUME_SETS_RINGER_MODE_SILENT) {
   3133                         ringerMode = RINGER_MODE_SILENT;
   3134                     } else {
   3135                         result |= AudioManager.FLAG_SHOW_VIBRATE_HINT;
   3136                     }
   3137                 }
   3138             } else if (direction == AudioManager.ADJUST_RAISE) {
   3139                 ringerMode = RINGER_MODE_NORMAL;
   3140             }
   3141             result &= ~FLAG_ADJUST_VOLUME;
   3142             break;
   3143         case RINGER_MODE_SILENT:
   3144             if (direction == AudioManager.ADJUST_RAISE) {
   3145                 if (PREVENT_VOLUME_ADJUSTMENT_IF_SILENT) {
   3146                     result |= AudioManager.FLAG_SHOW_SILENT_HINT;
   3147                 } else {
   3148                   if (mHasVibrator) {
   3149                       ringerMode = RINGER_MODE_VIBRATE;
   3150                   } else {
   3151                       ringerMode = RINGER_MODE_NORMAL;
   3152                   }
   3153                 }
   3154             }
   3155             result &= ~FLAG_ADJUST_VOLUME;
   3156             break;
   3157         default:
   3158             Log.e(TAG, "checkForRingerModeChange() wrong ringer mode: "+ringerMode);
   3159             break;
   3160         }
   3161 
   3162         setRingerMode(ringerMode, TAG + ".checkForRingerModeChange", false /*external*/);
   3163 
   3164         mPrevVolDirection = direction;
   3165 
   3166         return result;
   3167     }
   3168 
   3169     @Override
   3170     public boolean isStreamAffectedByRingerMode(int streamType) {
   3171         return (mRingerModeAffectedStreams & (1 << streamType)) != 0;
   3172     }
   3173 
   3174     private boolean isStreamMutedByRingerMode(int streamType) {
   3175         return (mRingerModeMutedStreams & (1 << streamType)) != 0;
   3176     }
   3177 
   3178     boolean updateRingerModeAffectedStreams() {
   3179         int ringerModeAffectedStreams;
   3180         // make sure settings for ringer mode are consistent with device type: non voice capable
   3181         // devices (tablets) include media stream in silent mode whereas phones don't.
   3182         ringerModeAffectedStreams = Settings.System.getIntForUser(mContentResolver,
   3183                 Settings.System.MODE_RINGER_STREAMS_AFFECTED,
   3184                 ((1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_NOTIFICATION)|
   3185                  (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)),
   3186                  UserHandle.USER_CURRENT);
   3187 
   3188         // ringtone, notification and system streams are always affected by ringer mode
   3189         ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_RING)|
   3190                                         (1 << AudioSystem.STREAM_NOTIFICATION)|
   3191                                         (1 << AudioSystem.STREAM_SYSTEM);
   3192 
   3193         switch (mPlatformType) {
   3194             case PLATFORM_TELEVISION:
   3195                 ringerModeAffectedStreams = 0;
   3196                 break;
   3197             default:
   3198                 ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_MUSIC);
   3199                 break;
   3200         }
   3201 
   3202         synchronized (mCameraSoundForced) {
   3203             if (mCameraSoundForced) {
   3204                 ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
   3205             } else {
   3206                 ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
   3207             }
   3208         }
   3209         if (mStreamVolumeAlias[AudioSystem.STREAM_DTMF] == AudioSystem.STREAM_RING) {
   3210             ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_DTMF);
   3211         } else {
   3212             ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_DTMF);
   3213         }
   3214 
   3215         if (ringerModeAffectedStreams != mRingerModeAffectedStreams) {
   3216             Settings.System.putIntForUser(mContentResolver,
   3217                     Settings.System.MODE_RINGER_STREAMS_AFFECTED,
   3218                     ringerModeAffectedStreams,
   3219                     UserHandle.USER_CURRENT);
   3220             mRingerModeAffectedStreams = ringerModeAffectedStreams;
   3221             return true;
   3222         }
   3223         return false;
   3224     }
   3225 
   3226     public boolean isStreamAffectedByMute(int streamType) {
   3227         return (mMuteAffectedStreams & (1 << streamType)) != 0;
   3228     }
   3229 
   3230     private void ensureValidDirection(int direction) {
   3231         if (direction < AudioManager.ADJUST_LOWER || direction > AudioManager.ADJUST_RAISE) {
   3232             throw new IllegalArgumentException("Bad direction " + direction);
   3233         }
   3234     }
   3235 
   3236     private void ensureValidSteps(int steps) {
   3237         if (Math.abs(steps) > MAX_BATCH_VOLUME_ADJUST_STEPS) {
   3238             throw new IllegalArgumentException("Bad volume adjust steps " + steps);
   3239         }
   3240     }
   3241 
   3242     private void ensureValidStreamType(int streamType) {
   3243         if (streamType < 0 || streamType >= mStreamStates.length) {
   3244             throw new IllegalArgumentException("Bad stream type " + streamType);
   3245         }
   3246     }
   3247 
   3248     private boolean isInCommunication() {
   3249         boolean IsInCall = false;
   3250 
   3251         TelecomManager telecomManager =
   3252                 (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
   3253 
   3254         final long ident = Binder.clearCallingIdentity();
   3255         IsInCall = telecomManager.isInCall();
   3256         Binder.restoreCallingIdentity(ident);
   3257 
   3258         return (IsInCall || getMode() == AudioManager.MODE_IN_COMMUNICATION);
   3259     }
   3260 
   3261     /**
   3262      * For code clarity for getActiveStreamType(int)
   3263      * @param delay_ms max time since last STREAM_MUSIC activity to consider
   3264      * @return true if STREAM_MUSIC is active in streams handled by AudioFlinger now or
   3265      *     in the last "delay_ms" ms.
   3266      */
   3267     private boolean isAfMusicActiveRecently(int delay_ms) {
   3268         return AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, delay_ms)
   3269                 || AudioSystem.isStreamActiveRemotely(AudioSystem.STREAM_MUSIC, delay_ms);
   3270     }
   3271 
   3272     private int getActiveStreamType(int suggestedStreamType) {
   3273         switch (mPlatformType) {
   3274         case PLATFORM_VOICE:
   3275             if (isInCommunication()) {
   3276                 if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION)
   3277                         == AudioSystem.FORCE_BT_SCO) {
   3278                     // Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO...");
   3279                     return AudioSystem.STREAM_BLUETOOTH_SCO;
   3280                 } else {
   3281                     // Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL...");
   3282                     return AudioSystem.STREAM_VOICE_CALL;
   3283                 }
   3284             } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
   3285                 if (isAfMusicActiveRecently(StreamOverride.sDelayMs)) {
   3286                     if (DEBUG_VOL)
   3287                         Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC stream active");
   3288                     return AudioSystem.STREAM_MUSIC;
   3289                     } else {
   3290                         if (DEBUG_VOL)
   3291                             Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING b/c default");
   3292                         return AudioSystem.STREAM_RING;
   3293                 }
   3294             } else if (isAfMusicActiveRecently(0)) {
   3295                 if (DEBUG_VOL)
   3296                     Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC stream active");
   3297                 return AudioSystem.STREAM_MUSIC;
   3298             }
   3299             break;
   3300         case PLATFORM_TELEVISION:
   3301             if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
   3302                     // TV always defaults to STREAM_MUSIC
   3303                     return AudioSystem.STREAM_MUSIC;
   3304             }
   3305             break;
   3306         default:
   3307             if (isInCommunication()) {
   3308                 if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION)
   3309                         == AudioSystem.FORCE_BT_SCO) {
   3310                     if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO");
   3311                     return AudioSystem.STREAM_BLUETOOTH_SCO;
   3312                 } else {
   3313                     if (DEBUG_VOL)  Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL");
   3314                     return AudioSystem.STREAM_VOICE_CALL;
   3315                 }
   3316             } else if (AudioSystem.isStreamActive(AudioSystem.STREAM_NOTIFICATION,
   3317                     StreamOverride.sDelayMs) ||
   3318                     AudioSystem.isStreamActive(AudioSystem.STREAM_RING,
   3319                             StreamOverride.sDelayMs)) {
   3320                 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION");
   3321                 return AudioSystem.STREAM_NOTIFICATION;
   3322             } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
   3323                 if (isAfMusicActiveRecently(StreamOverride.sDelayMs)) {
   3324                     if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: forcing STREAM_MUSIC");
   3325                     return AudioSystem.STREAM_MUSIC;
   3326                 } else {
   3327                     if (DEBUG_VOL) Log.v(TAG,
   3328                             "getActiveStreamType: using STREAM_NOTIFICATION as default");
   3329                     return AudioSystem.STREAM_NOTIFICATION;
   3330                 }
   3331             }
   3332             break;
   3333         }
   3334         if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Returning suggested type "
   3335                 + suggestedStreamType);
   3336         return suggestedStreamType;
   3337     }
   3338 
   3339     private void broadcastRingerMode(String action, int ringerMode) {
   3340         // Send sticky broadcast
   3341         Intent broadcast = new Intent(action);
   3342         broadcast.putExtra(AudioManager.EXTRA_RINGER_MODE, ringerMode);
   3343         broadcast.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
   3344                 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
   3345         sendStickyBroadcastToAll(broadcast);
   3346     }
   3347 
   3348     private void broadcastVibrateSetting(int vibrateType) {
   3349         // Send broadcast
   3350         if (ActivityManagerNative.isSystemReady()) {
   3351             Intent broadcast = new Intent(AudioManager.VIBRATE_SETTING_CHANGED_ACTION);
   3352             broadcast.putExtra(AudioManager.EXTRA_VIBRATE_TYPE, vibrateType);
   3353             broadcast.putExtra(AudioManager.EXTRA_VIBRATE_SETTING, getVibrateSetting(vibrateType));
   3354             sendBroadcastToAll(broadcast);
   3355         }
   3356     }
   3357 
   3358     // Message helper methods
   3359     /**
   3360      * Queue a message on the given handler's message queue, after acquiring the service wake lock.
   3361      * Note that the wake lock needs to be released after the message has been handled.
   3362      */
   3363     private void queueMsgUnderWakeLock(Handler handler, int msg,
   3364             int arg1, int arg2, Object obj, int delay) {
   3365         final long ident = Binder.clearCallingIdentity();
   3366         // Always acquire the wake lock as AudioService because it is released by the
   3367         // message handler.
   3368         mAudioEventWakeLock.acquire();
   3369         Binder.restoreCallingIdentity(ident);
   3370         sendMsg(handler, msg, SENDMSG_QUEUE, arg1, arg2, obj, delay);
   3371     }
   3372 
   3373     private static void sendMsg(Handler handler, int msg,
   3374             int existingMsgPolicy, int arg1, int arg2, Object obj, int delay) {
   3375 
   3376         if (existingMsgPolicy == SENDMSG_REPLACE) {
   3377             handler.removeMessages(msg);
   3378         } else if (existingMsgPolicy == SENDMSG_NOOP && handler.hasMessages(msg)) {
   3379             return;
   3380         }
   3381         synchronized (mLastDeviceConnectMsgTime) {
   3382             long time = SystemClock.uptimeMillis() + delay;
   3383             handler.sendMessageAtTime(handler.obtainMessage(msg, arg1, arg2, obj), time);
   3384             if (msg == MSG_SET_WIRED_DEVICE_CONNECTION_STATE ||
   3385                     msg == MSG_SET_A2DP_SRC_CONNECTION_STATE ||
   3386                     msg == MSG_SET_A2DP_SINK_CONNECTION_STATE) {
   3387                 mLastDeviceConnectMsgTime = time;
   3388             }
   3389         }
   3390     }
   3391 
   3392     boolean checkAudioSettingsPermission(String method) {
   3393         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS)
   3394                 == PackageManager.PERMISSION_GRANTED) {
   3395             return true;
   3396         }
   3397         String msg = "Audio Settings Permission Denial: " + method + " from pid="
   3398                 + Binder.getCallingPid()
   3399                 + ", uid=" + Binder.getCallingUid();
   3400         Log.w(TAG, msg);
   3401         return false;
   3402     }
   3403 
   3404     private int getDeviceForStream(int stream) {
   3405         int device = AudioSystem.getDevicesForStream(stream);
   3406         if ((device & (device - 1)) != 0) {
   3407             // Multiple device selection is either:
   3408             //  - speaker + one other device: give priority to speaker in this case.
   3409             //  - one A2DP device + another device: happens with duplicated output. In this case
   3410             // retain the device on the A2DP output as the other must not correspond to an active
   3411             // selection if not the speaker.
   3412             //  - HDMI-CEC system audio mode only output: give priority to available item in order.
   3413             if ((device & AudioSystem.DEVICE_OUT_SPEAKER) != 0) {
   3414                 device = AudioSystem.DEVICE_OUT_SPEAKER;
   3415             } else if ((device & AudioSystem.DEVICE_OUT_HDMI_ARC) != 0) {
   3416                 device = AudioSystem.DEVICE_OUT_HDMI_ARC;
   3417             } else if ((device & AudioSystem.DEVICE_OUT_SPDIF) != 0) {
   3418                 device = AudioSystem.DEVICE_OUT_SPDIF;
   3419             } else if ((device & AudioSystem.DEVICE_OUT_AUX_LINE) != 0) {
   3420                 device = AudioSystem.DEVICE_OUT_AUX_LINE;
   3421             } else {
   3422                 device &= AudioSystem.DEVICE_OUT_ALL_A2DP;
   3423             }
   3424         }
   3425         return device;
   3426     }
   3427 
   3428     public void setWiredDeviceConnectionState(int device, int state, String name) {
   3429         synchronized (mConnectedDevices) {
   3430             int delay = checkSendBecomingNoisyIntent(device, state);
   3431             queueMsgUnderWakeLock(mAudioHandler,
   3432                     MSG_SET_WIRED_DEVICE_CONNECTION_STATE,
   3433                     device,
   3434                     state,
   3435                     name,
   3436                     delay);
   3437         }
   3438     }
   3439 
   3440     public int setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state, int profile)
   3441     {
   3442         int delay;
   3443         if (profile != BluetoothProfile.A2DP && profile != BluetoothProfile.A2DP_SINK) {
   3444             throw new IllegalArgumentException("invalid profile " + profile);
   3445         }
   3446         synchronized (mConnectedDevices) {
   3447             if (profile == BluetoothProfile.A2DP) {
   3448                 delay = checkSendBecomingNoisyIntent(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
   3449                                                 (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0);
   3450             } else {
   3451                 delay = 0;
   3452             }
   3453             queueMsgUnderWakeLock(mAudioHandler,
   3454                     (profile == BluetoothProfile.A2DP ?
   3455                         MSG_SET_A2DP_SINK_CONNECTION_STATE : MSG_SET_A2DP_SRC_CONNECTION_STATE),
   3456                     state,
   3457                     0,
   3458                     device,
   3459                     delay);
   3460         }
   3461         return delay;
   3462     }
   3463 
   3464     ///////////////////////////////////////////////////////////////////////////
   3465     // Inner classes
   3466     ///////////////////////////////////////////////////////////////////////////
   3467 
   3468     // NOTE: Locking order for synchronized objects related to volume or ringer mode management:
   3469     //  1 mScoclient OR mSafeMediaVolumeState
   3470     //  2   mSetModeDeathHandlers
   3471     //  3     mSettingsLock
   3472     //  4       VolumeStreamState.class
   3473     //  5         mCameraSoundForced
   3474     public class VolumeStreamState {
   3475         private final int mStreamType;
   3476 
   3477         private String mVolumeIndexSettingName;
   3478         private int mIndexMax;
   3479         private final ConcurrentHashMap<Integer, Integer> mIndex =
   3480                                             new ConcurrentHashMap<Integer, Integer>(8, 0.75f, 4);
   3481         private ArrayList<VolumeDeathHandler> mDeathHandlers; //handles mute/solo clients death
   3482 
   3483         private VolumeStreamState(String settingName, int streamType) {
   3484 
   3485             mVolumeIndexSettingName = settingName;
   3486 
   3487             mStreamType = streamType;
   3488             mIndexMax = MAX_STREAM_VOLUME[streamType];
   3489             AudioSystem.initStreamVolume(streamType, 0, mIndexMax);
   3490             mIndexMax *= 10;
   3491 
   3492             // mDeathHandlers must be created before calling readSettings()
   3493             mDeathHandlers = new ArrayList<VolumeDeathHandler>();
   3494 
   3495             readSettings();
   3496         }
   3497 
   3498         public String getSettingNameForDevice(int device) {
   3499             String name = mVolumeIndexSettingName;
   3500             String suffix = AudioSystem.getOutputDeviceName(device);
   3501             if (suffix.isEmpty()) {
   3502                 return name;
   3503             }
   3504             return name + "_" + suffix;
   3505         }
   3506 
   3507         public void readSettings() {
   3508             synchronized (VolumeStreamState.class) {
   3509                 // force maximum volume on all streams if fixed volume property
   3510                 // or master volume property is set
   3511                 if (mUseFixedVolume || mUseMasterVolume) {
   3512                     mIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, mIndexMax);
   3513                     return;
   3514                 }
   3515                 // do not read system stream volume from settings: this stream is always aliased
   3516                 // to another stream type and its volume is never persisted. Values in settings can
   3517                 // only be stale values
   3518                 if ((mStreamType == AudioSystem.STREAM_SYSTEM) ||
   3519                         (mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED)) {
   3520                     int index = 10 * DEFAULT_STREAM_VOLUME[mStreamType];
   3521                     synchronized (mCameraSoundForced) {
   3522                         if (mCameraSoundForced) {
   3523                             index = mIndexMax;
   3524                         }
   3525                     }
   3526                     mIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, index);
   3527                     return;
   3528                 }
   3529 
   3530                 int remainingDevices = AudioSystem.DEVICE_OUT_ALL;
   3531 
   3532                 for (int i = 0; remainingDevices != 0; i++) {
   3533                     int device = (1 << i);
   3534                     if ((device & remainingDevices) == 0) {
   3535                         continue;
   3536                     }
   3537                     remainingDevices &= ~device;
   3538 
   3539                     // retrieve current volume for device
   3540                     String name = getSettingNameForDevice(device);
   3541                     // if no volume stored for current stream and device, use default volume if default
   3542                     // device, continue otherwise
   3543                     int defaultIndex = (device == AudioSystem.DEVICE_OUT_DEFAULT) ?
   3544                                             DEFAULT_STREAM_VOLUME[mStreamType] : -1;
   3545                     int index = Settings.System.getIntForUser(
   3546                             mContentResolver, name, defaultIndex, UserHandle.USER_CURRENT);
   3547                     if (index == -1) {
   3548                         continue;
   3549                     }
   3550 
   3551                     mIndex.put(device, getValidIndex(10 * index));
   3552                 }
   3553             }
   3554         }
   3555 
   3556         // must be called while synchronized VolumeStreamState.class
   3557         public void applyDeviceVolume_syncVSS(int device) {
   3558             int index;
   3559             if (isMuted_syncVSS()) {
   3560                 index = 0;
   3561             } else if (((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && mAvrcpAbsVolSupported)
   3562                     || ((device & mFullVolumeDevices) != 0)) {
   3563                 index = (mIndexMax + 5)/10;
   3564             } else {
   3565                 index = (getIndex(device) + 5)/10;
   3566             }
   3567             AudioSystem.setStreamVolumeIndex(mStreamType, index, device);
   3568         }
   3569 
   3570         public void applyAllVolumes() {
   3571             synchronized (VolumeStreamState.class) {
   3572                 // apply default volume first: by convention this will reset all
   3573                 // devices volumes in audio policy manager to the supplied value
   3574                 int index;
   3575                 if (isMuted_syncVSS()) {
   3576                     index = 0;
   3577                 } else {
   3578                     index = (getIndex(AudioSystem.DEVICE_OUT_DEFAULT) + 5)/10;
   3579                 }
   3580                 AudioSystem.setStreamVolumeIndex(mStreamType, index, AudioSystem.DEVICE_OUT_DEFAULT);
   3581                 // then apply device specific volumes
   3582                 Set set = mIndex.entrySet();
   3583                 Iterator i = set.iterator();
   3584                 while (i.hasNext()) {
   3585                     Map.Entry entry = (Map.Entry)i.next();
   3586                     int device = ((Integer)entry.getKey()).intValue();
   3587                     if (device != AudioSystem.DEVICE_OUT_DEFAULT) {
   3588                         if (isMuted_syncVSS()) {
   3589                             index = 0;
   3590                         } else if (((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
   3591                                 mAvrcpAbsVolSupported)
   3592                                     || ((device & mFullVolumeDevices) != 0))
   3593                         {
   3594                             index = (mIndexMax + 5)/10;
   3595                         } else {
   3596                             index = ((Integer)entry.getValue() + 5)/10;
   3597                         }
   3598                         AudioSystem.setStreamVolumeIndex(mStreamType, index, device);
   3599                     }
   3600                 }
   3601             }
   3602         }
   3603 
   3604         public boolean adjustIndex(int deltaIndex, int device) {
   3605             return setIndex(getIndex(device) + deltaIndex,
   3606                             device);
   3607         }
   3608 
   3609         public boolean setIndex(int index, int device) {
   3610             synchronized (VolumeStreamState.class) {
   3611                 int oldIndex = getIndex(device);
   3612                 index = getValidIndex(index);
   3613                 synchronized (mCameraSoundForced) {
   3614                     if ((mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED) && mCameraSoundForced) {
   3615                         index = mIndexMax;
   3616                     }
   3617                 }
   3618                 mIndex.put(device, index);
   3619 
   3620                 if (oldIndex != index) {
   3621                     // Apply change to all streams using this one as alias
   3622                     // if changing volume of current device, also change volume of current
   3623                     // device on aliased stream
   3624                     boolean currentDevice = (device == getDeviceForStream(mStreamType));
   3625                     int numStreamTypes = AudioSystem.getNumStreamTypes();
   3626                     for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
   3627                         if (streamType != mStreamType &&
   3628                                 mStreamVolumeAlias[streamType] == mStreamType) {
   3629                             int scaledIndex = rescaleIndex(index, mStreamType, streamType);
   3630                             mStreamStates[streamType].setIndex(scaledIndex,
   3631                                                                device);
   3632                             if (currentDevice) {
   3633                                 mStreamStates[streamType].setIndex(scaledIndex,
   3634                                                                    getDeviceForStream(streamType));
   3635                             }
   3636                         }
   3637                     }
   3638                     return true;
   3639                 } else {
   3640                     return false;
   3641                 }
   3642             }
   3643         }
   3644 
   3645         public int getIndex(int device) {
   3646             synchronized (VolumeStreamState.class) {
   3647                 Integer index = mIndex.get(device);
   3648                 if (index == null) {
   3649                     // there is always an entry for AudioSystem.DEVICE_OUT_DEFAULT
   3650                     index = mIndex.get(AudioSystem.DEVICE_OUT_DEFAULT);
   3651                 }
   3652                 return index.intValue();
   3653             }
   3654         }
   3655 
   3656         public int getMaxIndex() {
   3657             return mIndexMax;
   3658         }
   3659 
   3660         public void setAllIndexes(VolumeStreamState srcStream) {
   3661             synchronized (VolumeStreamState.class) {
   3662                 int srcStreamType = srcStream.getStreamType();
   3663                 // apply default device volume from source stream to all devices first in case
   3664                 // some devices are present in this stream state but not in source stream state
   3665                 int index = srcStream.getIndex(AudioSystem.DEVICE_OUT_DEFAULT);
   3666                 index = rescaleIndex(index, srcStreamType, mStreamType);
   3667                 Set set = mIndex.entrySet();
   3668                 Iterator i = set.iterator();
   3669                 while (i.hasNext()) {
   3670                     Map.Entry entry = (Map.Entry)i.next();
   3671                     entry.setValue(index);
   3672                 }
   3673                 // Now apply actual volume for devices in source stream state
   3674                 set = srcStream.mIndex.entrySet();
   3675                 i = set.iterator();
   3676                 while (i.hasNext()) {
   3677                     Map.Entry entry = (Map.Entry)i.next();
   3678                     int device = ((Integer)entry.getKey()).intValue();
   3679                     index = ((Integer)entry.getValue()).intValue();
   3680                     index = rescaleIndex(index, srcStreamType, mStreamType);
   3681 
   3682                     setIndex(index, device);
   3683                 }
   3684             }
   3685         }
   3686 
   3687         public void setAllIndexesToMax() {
   3688             synchronized (VolumeStreamState.class) {
   3689                 Set set = mIndex.entrySet();
   3690                 Iterator i = set.iterator();
   3691                 while (i.hasNext()) {
   3692                     Map.Entry entry = (Map.Entry)i.next();
   3693                     entry.setValue(mIndexMax);
   3694                 }
   3695             }
   3696         }
   3697 
   3698         public void mute(IBinder cb, boolean state) {
   3699             synchronized (VolumeStreamState.class) {
   3700                 VolumeDeathHandler handler = getDeathHandler_syncVSS(cb, state);
   3701                 if (handler == null) {
   3702                     Log.e(TAG, "Could not get client death handler for stream: "+mStreamType);
   3703                     return;
   3704                 }
   3705                 handler.mute_syncVSS(state);
   3706             }
   3707         }
   3708 
   3709         public int getStreamType() {
   3710             return mStreamType;
   3711         }
   3712 
   3713         public void checkFixedVolumeDevices() {
   3714             synchronized (VolumeStreamState.class) {
   3715                 // ignore settings for fixed volume devices: volume should always be at max or 0
   3716                 if (mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_MUSIC) {
   3717                     Set set = mIndex.entrySet();
   3718                     Iterator i = set.iterator();
   3719                     while (i.hasNext()) {
   3720                         Map.Entry entry = (Map.Entry)i.next();
   3721                         int device = ((Integer)entry.getKey()).intValue();
   3722                         int index = ((Integer)entry.getValue()).intValue();
   3723                         if (((device & mFullVolumeDevices) != 0)
   3724                                 || (((device & mFixedVolumeDevices) != 0) && index != 0)) {
   3725                             entry.setValue(mIndexMax);
   3726                         }
   3727                         applyDeviceVolume_syncVSS(device);
   3728                     }
   3729                 }
   3730             }
   3731         }
   3732 
   3733         private int getValidIndex(int index) {
   3734             if (index < 0) {
   3735                 return 0;
   3736             } else if (mUseFixedVolume || mUseMasterVolume || index > mIndexMax) {
   3737                 return mIndexMax;
   3738             }
   3739 
   3740             return index;
   3741         }
   3742 
   3743         private class VolumeDeathHandler implements IBinder.DeathRecipient {
   3744             private IBinder mICallback; // To be notified of client's death
   3745             private int mMuteCount; // Number of active mutes for this client
   3746 
   3747             VolumeDeathHandler(IBinder cb) {
   3748                 mICallback = cb;
   3749             }
   3750 
   3751             // must be called while synchronized VolumeStreamState.class
   3752             public void mute_syncVSS(boolean state) {
   3753                 boolean updateVolume = false;
   3754                 if (state) {
   3755                     if (mMuteCount == 0) {
   3756                         // Register for client death notification
   3757                         try {
   3758                             // mICallback can be 0 if muted by AudioService
   3759                             if (mICallback != null) {
   3760                                 mICallback.linkToDeath(this, 0);
   3761                             }
   3762                             VolumeStreamState.this.mDeathHandlers.add(this);
   3763                             // If the stream is not yet muted by any client, set level to 0
   3764                             if (!VolumeStreamState.this.isMuted_syncVSS()) {
   3765                                 updateVolume = true;
   3766                             }
   3767                         } catch (RemoteException e) {
   3768                             // Client has died!
   3769                             binderDied();
   3770                             return;
   3771                         }
   3772                     } else {
   3773                         Log.w(TAG, "stream: "+mStreamType+" was already muted by this client");
   3774                     }
   3775                     mMuteCount++;
   3776                 } else {
   3777                     if (mMuteCount == 0) {
   3778                         Log.e(TAG, "unexpected unmute for stream: "+mStreamType);
   3779                     } else {
   3780                         mMuteCount--;
   3781                         if (mMuteCount == 0) {
   3782                             // Unregister from client death notification
   3783                             VolumeStreamState.this.mDeathHandlers.remove(this);
   3784                             // mICallback can be 0 if muted by AudioService
   3785                             if (mICallback != null) {
   3786                                 mICallback.unlinkToDeath(this, 0);
   3787                             }
   3788                             if (!VolumeStreamState.this.isMuted_syncVSS()) {
   3789                                 updateVolume = true;
   3790                             }
   3791                         }
   3792                     }
   3793                 }
   3794                 if (updateVolume) {
   3795                     sendMsg(mAudioHandler,
   3796                             MSG_SET_ALL_VOLUMES,
   3797                             SENDMSG_QUEUE,
   3798                             0,
   3799                             0,
   3800                             VolumeStreamState.this, 0);
   3801                 }
   3802             }
   3803 
   3804             public void binderDied() {
   3805                 Log.w(TAG, "Volume service client died for stream: "+mStreamType);
   3806                 synchronized (VolumeStreamState.class) {
   3807                     if (mMuteCount != 0) {
   3808                         // Reset all active mute requests from this client.
   3809                         mMuteCount = 1;
   3810                         mute_syncVSS(false);
   3811                     }
   3812                 }
   3813             }
   3814         }
   3815 
   3816         private int muteCount() {
   3817             int count = 0;
   3818             int size = mDeathHandlers.size();
   3819             for (int i = 0; i < size; i++) {
   3820                 count += mDeathHandlers.get(i).mMuteCount;
   3821             }
   3822             return count;
   3823         }
   3824 
   3825         // must be called while synchronized VolumeStreamState.class
   3826         private boolean isMuted_syncVSS() {
   3827             return muteCount() != 0;
   3828         }
   3829 
   3830         // must be called while synchronized VolumeStreamState.class
   3831         private VolumeDeathHandler getDeathHandler_syncVSS(IBinder cb, boolean state) {
   3832             VolumeDeathHandler handler;
   3833             int size = mDeathHandlers.size();
   3834             for (int i = 0; i < size; i++) {
   3835                 handler = mDeathHandlers.get(i);
   3836                 if (cb == handler.mICallback) {
   3837                     return handler;
   3838                 }
   3839             }
   3840             // If this is the first mute request for this client, create a new
   3841             // client death handler. Otherwise, it is an out of sequence unmute request.
   3842             if (state) {
   3843                 handler = new VolumeDeathHandler(cb);
   3844             } else {
   3845                 Log.w(TAG, "stream was not muted by this client");
   3846                 handler = null;
   3847             }
   3848             return handler;
   3849         }
   3850 
   3851         private void dump(PrintWriter pw) {
   3852             pw.print("   Mute count: ");
   3853             pw.println(muteCount());
   3854             pw.print("   Max: ");
   3855             pw.println((mIndexMax + 5) / 10);
   3856             pw.print("   Current: ");
   3857             Set set = mIndex.entrySet();
   3858             Iterator i = set.iterator();
   3859             while (i.hasNext()) {
   3860                 Map.Entry entry = (Map.Entry)i.next();
   3861                 final int device = (Integer) entry.getKey();
   3862                 pw.print(Integer.toHexString(device));
   3863                 final String deviceName = device == AudioSystem.DEVICE_OUT_DEFAULT ? "default"
   3864                         : AudioSystem.getOutputDeviceName(device);
   3865                 if (!deviceName.isEmpty()) {
   3866                     pw.print(" (");
   3867                     pw.print(deviceName);
   3868                     pw.print(")");
   3869                 }
   3870                 pw.print(": ");
   3871                 final int index = (((Integer) entry.getValue()) + 5) / 10;
   3872                 pw.print(index);
   3873                 if (i.hasNext()) {
   3874                     pw.print(", ");
   3875                 }
   3876             }
   3877         }
   3878     }
   3879 
   3880     /** Thread that handles native AudioSystem control. */
   3881     private class AudioSystemThread extends Thread {
   3882         AudioSystemThread() {
   3883             super("AudioService");
   3884         }
   3885 
   3886         @Override
   3887         public void run() {
   3888             // Set this thread up so the handler will work on it
   3889             Looper.prepare();
   3890 
   3891             synchronized(AudioService.this) {
   3892                 mAudioHandler = new AudioHandler();
   3893 
   3894                 // Notify that the handler has been created
   3895                 AudioService.this.notify();
   3896             }
   3897 
   3898             // Listen for volume change requests that are set by VolumePanel
   3899             Looper.loop();
   3900         }
   3901     }
   3902 
   3903     /** Handles internal volume messages in separate volume thread. */
   3904     private class AudioHandler extends Handler {
   3905 
   3906         private void setDeviceVolume(VolumeStreamState streamState, int device) {
   3907 
   3908             synchronized (VolumeStreamState.class) {
   3909                 // Apply volume
   3910                 streamState.applyDeviceVolume_syncVSS(device);
   3911 
   3912                 // Apply change to all streams using this one as alias
   3913                 int numStreamTypes = AudioSystem.getNumStreamTypes();
   3914                 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
   3915                     if (streamType != streamState.mStreamType &&
   3916                             mStreamVolumeAlias[streamType] == streamState.mStreamType) {
   3917                         // Make sure volume is also maxed out on A2DP device for aliased stream
   3918                         // that may have a different device selected
   3919                         int streamDevice = getDeviceForStream(streamType);
   3920                         if ((device != streamDevice) && mAvrcpAbsVolSupported &&
   3921                                 ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0)) {
   3922                             mStreamStates[streamType].applyDeviceVolume_syncVSS(device);
   3923                         }
   3924                         mStreamStates[streamType].applyDeviceVolume_syncVSS(streamDevice);
   3925                     }
   3926                 }
   3927             }
   3928             // Post a persist volume msg
   3929             sendMsg(mAudioHandler,
   3930                     MSG_PERSIST_VOLUME,
   3931                     SENDMSG_QUEUE,
   3932                     device,
   3933                     0,
   3934                     streamState,
   3935                     PERSIST_DELAY);
   3936 
   3937         }
   3938 
   3939         private void setAllVolumes(VolumeStreamState streamState) {
   3940 
   3941             // Apply volume
   3942             streamState.applyAllVolumes();
   3943 
   3944             // Apply change to all streams using this one as alias
   3945             int numStreamTypes = AudioSystem.getNumStreamTypes();
   3946             for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
   3947                 if (streamType != streamState.mStreamType &&
   3948                         mStreamVolumeAlias[streamType] == streamState.mStreamType) {
   3949                     mStreamStates[streamType].applyAllVolumes();
   3950                 }
   3951             }
   3952         }
   3953 
   3954         private void persistVolume(VolumeStreamState streamState, int device) {
   3955             if (mUseFixedVolume) {
   3956                 return;
   3957             }
   3958             if (isPlatformTelevision() && (streamState.mStreamType != AudioSystem.STREAM_MUSIC)) {
   3959                 return;
   3960             }
   3961             System.putIntForUser(mContentResolver,
   3962                       streamState.getSettingNameForDevice(device),
   3963                       (streamState.getIndex(device) + 5)/ 10,
   3964                       UserHandle.USER_CURRENT);
   3965         }
   3966 
   3967         private void persistRingerMode(int ringerMode) {
   3968             if (mUseFixedVolume) {
   3969                 return;
   3970             }
   3971             Settings.Global.putInt(mContentResolver, Settings.Global.MODE_RINGER, ringerMode);
   3972         }
   3973 
   3974         private boolean onLoadSoundEffects() {
   3975             int status;
   3976 
   3977             synchronized (mSoundEffectsLock) {
   3978                 if (!mSystemReady) {
   3979                     Log.w(TAG, "onLoadSoundEffects() called before boot complete");
   3980                     return false;
   3981                 }
   3982 
   3983                 if (mSoundPool != null) {
   3984                     return true;
   3985                 }
   3986 
   3987                 loadTouchSoundAssets();
   3988 
   3989                 mSoundPool = new SoundPool.Builder()
   3990                         .setMaxStreams(NUM_SOUNDPOOL_CHANNELS)
   3991                         .setAudioAttributes(new AudioAttributes.Builder()
   3992                             .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
   3993                             .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
   3994                             .build())
   3995                         .build();
   3996                 mSoundPoolCallBack = null;
   3997                 mSoundPoolListenerThread = new SoundPoolListenerThread();
   3998                 mSoundPoolListenerThread.start();
   3999                 int attempts = 3;
   4000                 while ((mSoundPoolCallBack == null) && (attempts-- > 0)) {
   4001                     try {
   4002                         // Wait for mSoundPoolCallBack to be set by the other thread
   4003                         mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
   4004                     } catch (InterruptedException e) {
   4005                         Log.w(TAG, "Interrupted while waiting sound pool listener thread.");
   4006                     }
   4007                 }
   4008 
   4009                 if (mSoundPoolCallBack == null) {
   4010                     Log.w(TAG, "onLoadSoundEffects() SoundPool listener or thread creation error");
   4011                     if (mSoundPoolLooper != null) {
   4012                         mSoundPoolLooper.quit();
   4013                         mSoundPoolLooper = null;
   4014                     }
   4015                     mSoundPoolListenerThread = null;
   4016                     mSoundPool.release();
   4017                     mSoundPool = null;
   4018                     return false;
   4019                 }
   4020                 /*
   4021                  * poolId table: The value -1 in this table indicates that corresponding
   4022                  * file (same index in SOUND_EFFECT_FILES[] has not been loaded.
   4023                  * Once loaded, the value in poolId is the sample ID and the same
   4024                  * sample can be reused for another effect using the same file.
   4025                  */
   4026                 int[] poolId = new int[SOUND_EFFECT_FILES.size()];
   4027                 for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) {
   4028                     poolId[fileIdx] = -1;
   4029                 }
   4030                 /*
   4031                  * Effects whose value in SOUND_EFFECT_FILES_MAP[effect][1] is -1 must be loaded.
   4032                  * If load succeeds, value in SOUND_EFFECT_FILES_MAP[effect][1] is > 0:
   4033                  * this indicates we have a valid sample loaded for this effect.
   4034                  */
   4035 
   4036                 int numSamples = 0;
   4037                 for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
   4038                     // Do not load sample if this effect uses the MediaPlayer
   4039                     if (SOUND_EFFECT_FILES_MAP[effect][1] == 0) {
   4040                         continue;
   4041                     }
   4042                     if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == -1) {
   4043                         String filePath = Environment.getRootDirectory()
   4044                                 + SOUND_EFFECTS_PATH
   4045                                 + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effect][0]);
   4046                         int sampleId = mSoundPool.load(filePath, 0);
   4047                         if (sampleId <= 0) {
   4048                             Log.w(TAG, "Soundpool could not load file: "+filePath);
   4049                         } else {
   4050                             SOUND_EFFECT_FILES_MAP[effect][1] = sampleId;
   4051                             poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = sampleId;
   4052                             numSamples++;
   4053                         }
   4054                     } else {
   4055                         SOUND_EFFECT_FILES_MAP[effect][1] =
   4056                                 poolId[SOUND_EFFECT_FILES_MAP[effect][0]];
   4057                     }
   4058                 }
   4059                 // wait for all samples to be loaded
   4060                 if (numSamples > 0) {
   4061                     mSoundPoolCallBack.setSamples(poolId);
   4062 
   4063                     attempts = 3;
   4064                     status = 1;
   4065                     while ((status == 1) && (attempts-- > 0)) {
   4066                         try {
   4067                             mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
   4068                             status = mSoundPoolCallBack.status();
   4069                         } catch (InterruptedException e) {
   4070                             Log.w(TAG, "Interrupted while waiting sound pool callback.");
   4071                         }
   4072                     }
   4073                 } else {
   4074                     status = -1;
   4075                 }
   4076 
   4077                 if (mSoundPoolLooper != null) {
   4078                     mSoundPoolLooper.quit();
   4079                     mSoundPoolLooper = null;
   4080                 }
   4081                 mSoundPoolListenerThread = null;
   4082                 if (status != 0) {
   4083                     Log.w(TAG,
   4084                             "onLoadSoundEffects(), Error "+status+ " while loading samples");
   4085                     for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
   4086                         if (SOUND_EFFECT_FILES_MAP[effect][1] > 0) {
   4087                             SOUND_EFFECT_FILES_MAP[effect][1] = -1;
   4088                         }
   4089                     }
   4090 
   4091                     mSoundPool.release();
   4092                     mSoundPool = null;
   4093                 }
   4094             }
   4095             return (status == 0);
   4096         }
   4097 
   4098         /**
   4099          *  Unloads samples from the sound pool.
   4100          *  This method can be called to free some memory when
   4101          *  sound effects are disabled.
   4102          */
   4103         private void onUnloadSoundEffects() {
   4104             synchronized (mSoundEffectsLock) {
   4105                 if (mSoundPool == null) {
   4106                     return;
   4107                 }
   4108 
   4109                 int[] poolId = new int[SOUND_EFFECT_FILES.size()];
   4110                 for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) {
   4111                     poolId[fileIdx] = 0;
   4112                 }
   4113 
   4114                 for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
   4115                     if (SOUND_EFFECT_FILES_MAP[effect][1] <= 0) {
   4116                         continue;
   4117                     }
   4118                     if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == 0) {
   4119                         mSoundPool.unload(SOUND_EFFECT_FILES_MAP[effect][1]);
   4120                         SOUND_EFFECT_FILES_MAP[effect][1] = -1;
   4121                         poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = -1;
   4122                     }
   4123                 }
   4124                 mSoundPool.release();
   4125                 mSoundPool = null;
   4126             }
   4127         }
   4128 
   4129         private void onPlaySoundEffect(int effectType, int volume) {
   4130             synchronized (mSoundEffectsLock) {
   4131 
   4132                 onLoadSoundEffects();
   4133 
   4134                 if (mSoundPool == null) {
   4135                     return;
   4136                 }
   4137                 float volFloat;
   4138                 // use default if volume is not specified by caller
   4139                 if (volume < 0) {
   4140                     volFloat = (float)Math.pow(10, (float)sSoundEffectVolumeDb/20);
   4141                 } else {
   4142                     volFloat = volume / 1000.0f;
   4143                 }
   4144 
   4145                 if (SOUND_EFFECT_FILES_MAP[effectType][1] > 0) {
   4146                     mSoundPool.play(SOUND_EFFECT_FILES_MAP[effectType][1],
   4147                                         volFloat, volFloat, 0, 0, 1.0f);
   4148                 } else {
   4149                     MediaPlayer mediaPlayer = new MediaPlayer();
   4150                     try {
   4151                         String filePath = Environment.getRootDirectory() + SOUND_EFFECTS_PATH +
   4152                                     SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]);
   4153                         mediaPlayer.setDataSource(filePath);
   4154                         mediaPlayer.setAudioStreamType(AudioSystem.STREAM_SYSTEM);
   4155                         mediaPlayer.prepare();
   4156                         mediaPlayer.setVolume(volFloat);
   4157                         mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
   4158                             public void onCompletion(MediaPlayer mp) {
   4159                                 cleanupPlayer(mp);
   4160                             }
   4161                         });
   4162                         mediaPlayer.setOnErrorListener(new OnErrorListener() {
   4163                             public boolean onError(MediaPlayer mp, int what, int extra) {
   4164                                 cleanupPlayer(mp);
   4165                                 return true;
   4166                             }
   4167                         });
   4168                         mediaPlayer.start();
   4169                     } catch (IOException ex) {
   4170                         Log.w(TAG, "MediaPlayer IOException: "+ex);
   4171                     } catch (IllegalArgumentException ex) {
   4172                         Log.w(TAG, "MediaPlayer IllegalArgumentException: "+ex);
   4173                     } catch (IllegalStateException ex) {
   4174                         Log.w(TAG, "MediaPlayer IllegalStateException: "+ex);
   4175                     }
   4176                 }
   4177             }
   4178         }
   4179 
   4180         private void cleanupPlayer(MediaPlayer mp) {
   4181             if (mp != null) {
   4182                 try {
   4183                     mp.stop();
   4184                     mp.release();
   4185                 } catch (IllegalStateException ex) {
   4186                     Log.w(TAG, "MediaPlayer IllegalStateException: "+ex);
   4187                 }
   4188             }
   4189         }
   4190 
   4191         private void setForceUse(int usage, int config) {
   4192             AudioSystem.setForceUse(usage, config);
   4193         }
   4194 
   4195         private void onPersistSafeVolumeState(int state) {
   4196             Settings.Global.putInt(mContentResolver,
   4197                     Settings.Global.AUDIO_SAFE_VOLUME_STATE,
   4198                     state);
   4199         }
   4200 
   4201         @Override
   4202         public void handleMessage(Message msg) {
   4203             switch (msg.what) {
   4204 
   4205                 case MSG_SET_DEVICE_VOLUME:
   4206                     setDeviceVolume((VolumeStreamState) msg.obj, msg.arg1);
   4207                     break;
   4208 
   4209                 case MSG_SET_ALL_VOLUMES:
   4210                     setAllVolumes((VolumeStreamState) msg.obj);
   4211                     break;
   4212 
   4213                 case MSG_PERSIST_VOLUME:
   4214                     persistVolume((VolumeStreamState) msg.obj, msg.arg1);
   4215                     break;
   4216 
   4217                 case MSG_PERSIST_MASTER_VOLUME:
   4218                     if (mUseFixedVolume) {
   4219                         return;
   4220                     }
   4221                     Settings.System.putFloatForUser(mContentResolver,
   4222                                                     Settings.System.VOLUME_MASTER,
   4223                                                     msg.arg1 / (float)1000.0,
   4224                                                     UserHandle.USER_CURRENT);
   4225                     break;
   4226 
   4227                 case MSG_PERSIST_MASTER_VOLUME_MUTE:
   4228                     if (mUseFixedVolume) {
   4229                         return;
   4230                     }
   4231                     Settings.System.putIntForUser(mContentResolver,
   4232                                                  Settings.System.VOLUME_MASTER_MUTE,
   4233                                                  msg.arg1,
   4234                                                  msg.arg2);
   4235                     break;
   4236 
   4237                 case MSG_PERSIST_RINGER_MODE:
   4238                     // note that the value persisted is the current ringer mode, not the
   4239                     // value of ringer mode as of the time the request was made to persist
   4240                     persistRingerMode(getRingerModeInternal());
   4241                     break;
   4242 
   4243                 case MSG_MEDIA_SERVER_DIED:
   4244                     if (!mSystemReady ||
   4245                             (AudioSystem.checkAudioFlinger() != AudioSystem.AUDIO_STATUS_OK)) {
   4246                         Log.e(TAG, "Media server died.");
   4247                         sendMsg(mAudioHandler, MSG_MEDIA_SERVER_DIED, SENDMSG_NOOP, 0, 0,
   4248                                 null, 500);
   4249                         break;
   4250                     }
   4251                     Log.e(TAG, "Media server started.");
   4252 
   4253                     // indicate to audio HAL that we start the reconfiguration phase after a media
   4254                     // server crash
   4255                     // Note that we only execute this when the media server
   4256                     // process restarts after a crash, not the first time it is started.
   4257                     AudioSystem.setParameters("restarting=true");
   4258 
   4259                     readAndSetLowRamDevice();
   4260 
   4261                     // Restore device connection states
   4262                     synchronized (mConnectedDevices) {
   4263                         Set set = mConnectedDevices.entrySet();
   4264                         Iterator i = set.iterator();
   4265                         while (i.hasNext()) {
   4266                             Map.Entry device = (Map.Entry)i.next();
   4267                             AudioSystem.setDeviceConnectionState(
   4268                                                             ((Integer)device.getKey()).intValue(),
   4269                                                             AudioSystem.DEVICE_STATE_AVAILABLE,
   4270                                                             (String)device.getValue());
   4271                         }
   4272                     }
   4273                     // Restore call state
   4274                     AudioSystem.setPhoneState(mMode);
   4275 
   4276                     // Restore forced usage for communcations and record
   4277                     AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm);
   4278                     AudioSystem.setForceUse(AudioSystem.FOR_RECORD, mForcedUseForComm);
   4279                     AudioSystem.setForceUse(AudioSystem.FOR_SYSTEM, mCameraSoundForced ?
   4280                                     AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE);
   4281 
   4282                     // Restore stream volumes
   4283                     int numStreamTypes = AudioSystem.getNumStreamTypes();
   4284                     for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
   4285                         VolumeStreamState streamState = mStreamStates[streamType];
   4286                         AudioSystem.initStreamVolume(streamType, 0, (streamState.mIndexMax + 5) / 10);
   4287 
   4288                         streamState.applyAllVolumes();
   4289                     }
   4290 
   4291                     // Restore ringer mode
   4292                     setRingerModeInt(getRingerModeInternal(), false);
   4293 
   4294                     // Restore master volume
   4295                     restoreMasterVolume();
   4296 
   4297                     // Reset device orientation (if monitored for this device)
   4298                     if (mMonitorOrientation) {
   4299                         setOrientationForAudioSystem();
   4300                     }
   4301                     if (mMonitorRotation) {
   4302                         setRotationForAudioSystem();
   4303                     }
   4304 
   4305                     synchronized (mBluetoothA2dpEnabledLock) {
   4306                         AudioSystem.setForceUse(AudioSystem.FOR_MEDIA,
   4307                                 mBluetoothA2dpEnabled ?
   4308                                         AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP);
   4309                     }
   4310 
   4311                     synchronized (mSettingsLock) {
   4312                         AudioSystem.setForceUse(AudioSystem.FOR_DOCK,
   4313                                 mDockAudioMediaEnabled ?
   4314                                         AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE);
   4315                     }
   4316                     if (mHdmiManager != null) {
   4317                         synchronized (mHdmiManager) {
   4318                             if (mHdmiTvClient != null) {
   4319                                 setHdmiSystemAudioSupported(mHdmiSystemAudioSupported);
   4320                             }
   4321                         }
   4322                     }
   4323 
   4324                     synchronized (mAudioPolicies) {
   4325                         for(AudioPolicyProxy policy : mAudioPolicies.values()) {
   4326                             policy.connectMixes();
   4327                         }
   4328                     }
   4329 
   4330                     // indicate the end of reconfiguration phase to audio HAL
   4331                     AudioSystem.setParameters("restarting=false");
   4332                     break;
   4333 
   4334                 case MSG_UNLOAD_SOUND_EFFECTS:
   4335                     onUnloadSoundEffects();
   4336                     break;
   4337 
   4338                 case MSG_LOAD_SOUND_EFFECTS:
   4339                     //FIXME: onLoadSoundEffects() should be executed in a separate thread as it
   4340                     // can take several dozens of milliseconds to complete
   4341                     boolean loaded = onLoadSoundEffects();
   4342                     if (msg.obj != null) {
   4343                         LoadSoundEffectReply reply = (LoadSoundEffectReply)msg.obj;
   4344                         synchronized (reply) {
   4345                             reply.mStatus = loaded ? 0 : -1;
   4346                             reply.notify();
   4347                         }
   4348                     }
   4349                     break;
   4350 
   4351                 case MSG_PLAY_SOUND_EFFECT:
   4352                     onPlaySoundEffect(msg.arg1, msg.arg2);
   4353                     break;
   4354 
   4355                 case MSG_BTA2DP_DOCK_TIMEOUT:
   4356                     // msg.obj  == address of BTA2DP device
   4357                     synchronized (mConnectedDevices) {
   4358                         makeA2dpDeviceUnavailableNow( (String) msg.obj );
   4359                     }
   4360                     break;
   4361 
   4362                 case MSG_SET_FORCE_USE:
   4363                 case MSG_SET_FORCE_BT_A2DP_USE:
   4364                     setForceUse(msg.arg1, msg.arg2);
   4365                     break;
   4366 
   4367                 case MSG_BT_HEADSET_CNCT_FAILED:
   4368                     resetBluetoothSco();
   4369                     break;
   4370 
   4371                 case MSG_SET_WIRED_DEVICE_CONNECTION_STATE:
   4372                     onSetWiredDeviceConnectionState(msg.arg1, msg.arg2, (String)msg.obj);
   4373                     mAudioEventWakeLock.release();
   4374                     break;
   4375 
   4376                 case MSG_SET_A2DP_SRC_CONNECTION_STATE:
   4377                     onSetA2dpSourceConnectionState((BluetoothDevice)msg.obj, msg.arg1);
   4378                     mAudioEventWakeLock.release();
   4379                     break;
   4380 
   4381                 case MSG_SET_A2DP_SINK_CONNECTION_STATE:
   4382                     onSetA2dpSinkConnectionState((BluetoothDevice)msg.obj, msg.arg1);
   4383                     mAudioEventWakeLock.release();
   4384                     break;
   4385 
   4386                 case MSG_REPORT_NEW_ROUTES: {
   4387                     int N = mRoutesObservers.beginBroadcast();
   4388                     if (N > 0) {
   4389                         AudioRoutesInfo routes;
   4390                         synchronized (mCurAudioRoutes) {
   4391                             routes = new AudioRoutesInfo(mCurAudioRoutes);
   4392                         }
   4393                         while (N > 0) {
   4394                             N--;
   4395                             IAudioRoutesObserver obs = mRoutesObservers.getBroadcastItem(N);
   4396                             try {
   4397                                 obs.dispatchAudioRoutesChanged(routes);
   4398                             } catch (RemoteException e) {
   4399                             }
   4400                         }
   4401                     }
   4402                     mRoutesObservers.finishBroadcast();
   4403                     break;
   4404                 }
   4405 
   4406                 case MSG_CHECK_MUSIC_ACTIVE:
   4407                     onCheckMusicActive();
   4408                     break;
   4409 
   4410                 case MSG_BROADCAST_AUDIO_BECOMING_NOISY:
   4411                     onSendBecomingNoisyIntent();
   4412                     break;
   4413 
   4414                 case MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED:
   4415                 case MSG_CONFIGURE_SAFE_MEDIA_VOLUME:
   4416                     onConfigureSafeVolume((msg.what == MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED));
   4417                     break;
   4418                 case MSG_PERSIST_SAFE_VOLUME_STATE:
   4419                     onPersistSafeVolumeState(msg.arg1);
   4420                     break;
   4421 
   4422                 case MSG_BROADCAST_BT_CONNECTION_STATE:
   4423                     onBroadcastScoConnectionState(msg.arg1);
   4424                     break;
   4425 
   4426                 case MSG_SYSTEM_READY:
   4427                     onSystemReady();
   4428                     break;
   4429 
   4430                 case MSG_PERSIST_MUSIC_ACTIVE_MS:
   4431                     final int musicActiveMs = msg.arg1;
   4432                     Settings.Secure.putIntForUser(mContentResolver,
   4433                             Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS, musicActiveMs,
   4434                             UserHandle.USER_CURRENT);
   4435                     break;
   4436                 case MSG_PERSIST_MICROPHONE_MUTE:
   4437                     Settings.System.putIntForUser(mContentResolver,
   4438                                                  Settings.System.MICROPHONE_MUTE,
   4439                                                  msg.arg1,
   4440                                                  msg.arg2);
   4441                     break;
   4442             }
   4443         }
   4444     }
   4445 
   4446     private class SettingsObserver extends ContentObserver {
   4447 
   4448         SettingsObserver() {
   4449             super(new Handler());
   4450             mContentResolver.registerContentObserver(Settings.System.getUriFor(
   4451                 Settings.System.MODE_RINGER_STREAMS_AFFECTED), false, this);
   4452             mContentResolver.registerContentObserver(Settings.Global.getUriFor(
   4453                 Settings.Global.DOCK_AUDIO_MEDIA_ENABLED), false, this);
   4454         }
   4455 
   4456         @Override
   4457         public void onChange(boolean selfChange) {
   4458             super.onChange(selfChange);
   4459             // FIXME This synchronized is not necessary if mSettingsLock only protects mRingerMode.
   4460             //       However there appear to be some missing locks around mRingerModeMutedStreams
   4461             //       and mRingerModeAffectedStreams, so will leave this synchronized for now.
   4462             //       mRingerModeMutedStreams and mMuteAffectedStreams are safe (only accessed once).
   4463             synchronized (mSettingsLock) {
   4464                 if (updateRingerModeAffectedStreams()) {
   4465                     /*
   4466                      * Ensure all stream types that should be affected by ringer mode
   4467                      * are in the proper state.
   4468                      */
   4469                     setRingerModeInt(getRingerModeInternal(), false);
   4470                 }
   4471                 readDockAudioSettings(mContentResolver);
   4472             }
   4473         }
   4474     }
   4475 
   4476     // must be called synchronized on mConnectedDevices
   4477     private void makeA2dpDeviceAvailable(String address) {
   4478         // enable A2DP before notifying A2DP connection to avoid unecessary processing in
   4479         // audio policy manager
   4480         VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC];
   4481         sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE,
   4482                 AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0, streamState, 0);
   4483         setBluetoothA2dpOnInt(true);
   4484         AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
   4485                 AudioSystem.DEVICE_STATE_AVAILABLE,
   4486                 address);
   4487         // Reset A2DP suspend state each time a new sink is connected
   4488         AudioSystem.setParameters("A2dpSuspended=false");
   4489         mConnectedDevices.put( new Integer(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP),
   4490                 address);
   4491     }
   4492 
   4493     private void onSendBecomingNoisyIntent() {
   4494         sendBroadcastToAll(new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY));
   4495     }
   4496 
   4497     // must be called synchronized on mConnectedDevices
   4498     private void makeA2dpDeviceUnavailableNow(String address) {
   4499         synchronized (mA2dpAvrcpLock) {
   4500             mAvrcpAbsVolSupported = false;
   4501         }
   4502         AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
   4503                 AudioSystem.DEVICE_STATE_UNAVAILABLE,
   4504                 address);
   4505         mConnectedDevices.remove(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
   4506         synchronized (mCurAudioRoutes) {
   4507             // Remove A2DP routes as well
   4508             if (mCurAudioRoutes.mBluetoothName != null) {
   4509                 mCurAudioRoutes.mBluetoothName = null;
   4510                 sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES,
   4511                         SENDMSG_NOOP, 0, 0, null, 0);
   4512             }
   4513         }
   4514     }
   4515 
   4516     // must be called synchronized on mConnectedDevices
   4517     private void makeA2dpDeviceUnavailableLater(String address) {
   4518         // prevent any activity on the A2DP audio output to avoid unwanted
   4519         // reconnection of the sink.
   4520         AudioSystem.setParameters("A2dpSuspended=true");
   4521         // the device will be made unavailable later, so consider it disconnected right away
   4522         mConnectedDevices.remove(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
   4523         // send the delayed message to make the device unavailable later
   4524         Message msg = mAudioHandler.obtainMessage(MSG_BTA2DP_DOCK_TIMEOUT, address);
   4525         mAudioHandler.sendMessageDelayed(msg, BTA2DP_DOCK_TIMEOUT_MILLIS);
   4526 
   4527     }
   4528 
   4529     // must be called synchronized on mConnectedDevices
   4530     private void makeA2dpSrcAvailable(String address) {
   4531         AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP,
   4532                 AudioSystem.DEVICE_STATE_AVAILABLE,
   4533                 address);
   4534         mConnectedDevices.put( new Integer(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP),
   4535                 address);
   4536     }
   4537 
   4538     // must be called synchronized on mConnectedDevices
   4539     private void makeA2dpSrcUnavailable(String address) {
   4540         AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP,
   4541                 AudioSystem.DEVICE_STATE_UNAVAILABLE,
   4542                 address);
   4543         mConnectedDevices.remove(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP);
   4544     }
   4545 
   4546     // must be called synchronized on mConnectedDevices
   4547     private void cancelA2dpDeviceTimeout() {
   4548         mAudioHandler.removeMessages(MSG_BTA2DP_DOCK_TIMEOUT);
   4549     }
   4550 
   4551     // must be called synchronized on mConnectedDevices
   4552     private boolean hasScheduledA2dpDockTimeout() {
   4553         return mAudioHandler.hasMessages(MSG_BTA2DP_DOCK_TIMEOUT);
   4554     }
   4555 
   4556     private void onSetA2dpSinkConnectionState(BluetoothDevice btDevice, int state)
   4557     {
   4558         if (DEBUG_VOL) {
   4559             Log.d(TAG, "onSetA2dpSinkConnectionState btDevice="+btDevice+"state="+state);
   4560         }
   4561         if (btDevice == null) {
   4562             return;
   4563         }
   4564         String address = btDevice.getAddress();
   4565         if (!BluetoothAdapter.checkBluetoothAddress(address)) {
   4566             address = "";
   4567         }
   4568 
   4569         synchronized (mConnectedDevices) {
   4570             boolean isConnected =
   4571                 (mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) &&
   4572                  mConnectedDevices.get(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP).equals(address));
   4573 
   4574             if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
   4575                 if (btDevice.isBluetoothDock()) {
   4576                     if (state == BluetoothProfile.STATE_DISCONNECTED) {
   4577                         // introduction of a delay for transient disconnections of docks when
   4578                         // power is rapidly turned off/on, this message will be canceled if
   4579                         // we reconnect the dock under a preset delay
   4580                         makeA2dpDeviceUnavailableLater(address);
   4581                         // the next time isConnected is evaluated, it will be false for the dock
   4582                     }
   4583                 } else {
   4584                     makeA2dpDeviceUnavailableNow(address);
   4585                 }
   4586                 synchronized (mCurAudioRoutes) {
   4587                     if (mCurAudioRoutes.mBluetoothName != null) {
   4588                         mCurAudioRoutes.mBluetoothName = null;
   4589                         sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES,
   4590                                 SENDMSG_NOOP, 0, 0, null, 0);
   4591                     }
   4592                 }
   4593             } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
   4594                 if (btDevice.isBluetoothDock()) {
   4595                     // this could be a reconnection after a transient disconnection
   4596                     cancelA2dpDeviceTimeout();
   4597                     mDockAddress = address;
   4598                 } else {
   4599                     // this could be a connection of another A2DP device before the timeout of
   4600                     // a dock: cancel the dock timeout, and make the dock unavailable now
   4601                     if(hasScheduledA2dpDockTimeout()) {
   4602                         cancelA2dpDeviceTimeout();
   4603                         makeA2dpDeviceUnavailableNow(mDockAddress);
   4604                     }
   4605                 }
   4606                 makeA2dpDeviceAvailable(address);
   4607                 synchronized (mCurAudioRoutes) {
   4608                     String name = btDevice.getAliasName();
   4609                     if (!TextUtils.equals(mCurAudioRoutes.mBluetoothName, name)) {
   4610                         mCurAudioRoutes.mBluetoothName = name;
   4611                         sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES,
   4612                                 SENDMSG_NOOP, 0, 0, null, 0);
   4613                     }
   4614                 }
   4615             }
   4616         }
   4617     }
   4618 
   4619     private void onSetA2dpSourceConnectionState(BluetoothDevice btDevice, int state)
   4620     {
   4621         if (DEBUG_VOL) {
   4622             Log.d(TAG, "onSetA2dpSourceConnectionState btDevice="+btDevice+" state="+state);
   4623         }
   4624         if (btDevice == null) {
   4625             return;
   4626         }
   4627         String address = btDevice.getAddress();
   4628         if (!BluetoothAdapter.checkBluetoothAddress(address)) {
   4629             address = "";
   4630         }
   4631 
   4632         synchronized (mConnectedDevices) {
   4633                 boolean isConnected =
   4634                 (mConnectedDevices.containsKey(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP) &&
   4635                  mConnectedDevices.get(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP).equals(address));
   4636 
   4637             if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
   4638                 makeA2dpSrcUnavailable(address);
   4639             } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
   4640                 makeA2dpSrcAvailable(address);
   4641             }
   4642         }
   4643     }
   4644 
   4645     public void avrcpSupportsAbsoluteVolume(String address, boolean support) {
   4646         // address is not used for now, but may be used when multiple a2dp devices are supported
   4647         synchronized (mA2dpAvrcpLock) {
   4648             mAvrcpAbsVolSupported = support;
   4649             sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE,
   4650                     AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0,
   4651                     mStreamStates[AudioSystem.STREAM_MUSIC], 0);
   4652             sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE,
   4653                     AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0,
   4654                     mStreamStates[AudioSystem.STREAM_RING], 0);
   4655         }
   4656     }
   4657 
   4658     private boolean handleDeviceConnection(boolean connected, int device, String params) {
   4659         synchronized (mConnectedDevices) {
   4660             boolean isConnected = (mConnectedDevices.containsKey(device) &&
   4661                     (params.isEmpty() || mConnectedDevices.get(device).equals(params)));
   4662 
   4663             if (isConnected && !connected) {
   4664                 AudioSystem.setDeviceConnectionState(device,
   4665                                               AudioSystem.DEVICE_STATE_UNAVAILABLE,
   4666                                               mConnectedDevices.get(device));
   4667                  mConnectedDevices.remove(device);
   4668                  return true;
   4669             } else if (!isConnected && connected) {
   4670                  AudioSystem.setDeviceConnectionState(device,
   4671                                                       AudioSystem.DEVICE_STATE_AVAILABLE,
   4672                                                       params);
   4673                  mConnectedDevices.put(new Integer(device), params);
   4674                  return true;
   4675             }
   4676         }
   4677         return false;
   4678     }
   4679 
   4680     // Devices which removal triggers intent ACTION_AUDIO_BECOMING_NOISY. The intent is only
   4681     // sent if none of these devices is connected.
   4682     int mBecomingNoisyIntentDevices =
   4683             AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE |
   4684             AudioSystem.DEVICE_OUT_ALL_A2DP | AudioSystem.DEVICE_OUT_HDMI |
   4685             AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET | AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET |
   4686             AudioSystem.DEVICE_OUT_ALL_USB | AudioSystem.DEVICE_OUT_LINE;
   4687 
   4688     // must be called before removing the device from mConnectedDevices
   4689     private int checkSendBecomingNoisyIntent(int device, int state) {
   4690         int delay = 0;
   4691         if ((state == 0) && ((device & mBecomingNoisyIntentDevices) != 0)) {
   4692             int devices = 0;
   4693             for (int dev : mConnectedDevices.keySet()) {
   4694                 if (((dev & AudioSystem.DEVICE_BIT_IN) == 0) &&
   4695                         ((dev & mBecomingNoisyIntentDevices) != 0)) {
   4696                    devices |= dev;
   4697                 }
   4698             }
   4699             if (devices == device) {
   4700                 sendMsg(mAudioHandler,
   4701                         MSG_BROADCAST_AUDIO_BECOMING_NOISY,
   4702                         SENDMSG_REPLACE,
   4703                         0,
   4704                         0,
   4705                         null,
   4706                         0);
   4707                 delay = 1000;
   4708             }
   4709         }
   4710 
   4711         if (mAudioHandler.hasMessages(MSG_SET_A2DP_SRC_CONNECTION_STATE) ||
   4712                 mAudioHandler.hasMessages(MSG_SET_A2DP_SINK_CONNECTION_STATE) ||
   4713                 mAudioHandler.hasMessages(MSG_SET_WIRED_DEVICE_CONNECTION_STATE)) {
   4714             synchronized (mLastDeviceConnectMsgTime) {
   4715                 long time = SystemClock.uptimeMillis();
   4716                 if (mLastDeviceConnectMsgTime > time) {
   4717                     delay = (int)(mLastDeviceConnectMsgTime - time) + 30;
   4718                 }
   4719             }
   4720         }
   4721         return delay;
   4722     }
   4723 
   4724     private void sendDeviceConnectionIntent(int device, int state, String name)
   4725     {
   4726         Intent intent = new Intent();
   4727 
   4728         intent.putExtra("state", state);
   4729         intent.putExtra("name", name);
   4730         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
   4731 
   4732         int connType = 0;
   4733 
   4734         if (device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) {
   4735             connType = AudioRoutesInfo.MAIN_HEADSET;
   4736             intent.setAction(Intent.ACTION_HEADSET_PLUG);
   4737             intent.putExtra("microphone", 1);
   4738         } else if (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE ||
   4739                    device == AudioSystem.DEVICE_OUT_LINE) {
   4740             /*do apps care about line-out vs headphones?*/
   4741             connType = AudioRoutesInfo.MAIN_HEADPHONES;
   4742             intent.setAction(Intent.ACTION_HEADSET_PLUG);
   4743             intent.putExtra("microphone", 0);
   4744         } else if (device == AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET) {
   4745             connType = AudioRoutesInfo.MAIN_DOCK_SPEAKERS;
   4746             intent.setAction(AudioManager.ACTION_ANALOG_AUDIO_DOCK_PLUG);
   4747         } else if (device == AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET) {
   4748             connType = AudioRoutesInfo.MAIN_DOCK_SPEAKERS;
   4749             intent.setAction(AudioManager.ACTION_DIGITAL_AUDIO_DOCK_PLUG);
   4750         } else if (device == AudioSystem.DEVICE_OUT_HDMI ||
   4751                 device == AudioSystem.DEVICE_OUT_HDMI_ARC) {
   4752             connType = AudioRoutesInfo.MAIN_HDMI;
   4753             configureHdmiPlugIntent(intent, state);
   4754         }
   4755 
   4756         synchronized (mCurAudioRoutes) {
   4757             if (connType != 0) {
   4758                 int newConn = mCurAudioRoutes.mMainType;
   4759                 if (state != 0) {
   4760                     newConn |= connType;
   4761                 } else {
   4762                     newConn &= ~connType;
   4763                 }
   4764                 if (newConn != mCurAudioRoutes.mMainType) {
   4765                     mCurAudioRoutes.mMainType = newConn;
   4766                     sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES,
   4767                             SENDMSG_NOOP, 0, 0, null, 0);
   4768                 }
   4769             }
   4770         }
   4771 
   4772         final long ident = Binder.clearCallingIdentity();
   4773         try {
   4774             ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.USER_ALL);
   4775         } finally {
   4776             Binder.restoreCallingIdentity(ident);
   4777         }
   4778     }
   4779 
   4780     private void onSetWiredDeviceConnectionState(int device, int state, String name)
   4781     {
   4782         synchronized (mConnectedDevices) {
   4783             if ((state == 0) && ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) ||
   4784                     (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE) ||
   4785                     (device == AudioSystem.DEVICE_OUT_LINE))) {
   4786                 setBluetoothA2dpOnInt(true);
   4787             }
   4788             boolean isUsb = ((device & ~AudioSystem.DEVICE_OUT_ALL_USB) == 0) ||
   4789                             (((device & AudioSystem.DEVICE_BIT_IN) != 0) &&
   4790                              ((device & ~AudioSystem.DEVICE_IN_ALL_USB) == 0));
   4791             handleDeviceConnection((state == 1), device, (isUsb ? name : ""));
   4792             if (state != 0) {
   4793                 if ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) ||
   4794                     (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE) ||
   4795                     (device == AudioSystem.DEVICE_OUT_LINE)) {
   4796                     setBluetoothA2dpOnInt(false);
   4797                 }
   4798                 if ((device & mSafeMediaVolumeDevices) != 0) {
   4799                     sendMsg(mAudioHandler,
   4800                             MSG_CHECK_MUSIC_ACTIVE,
   4801                             SENDMSG_REPLACE,
   4802                             0,
   4803                             0,
   4804                             null,
   4805                             MUSIC_ACTIVE_POLL_PERIOD_MS);
   4806                 }
   4807                 // Television devices without CEC service apply software volume on HDMI output
   4808                 if (isPlatformTelevision() && ((device & AudioSystem.DEVICE_OUT_HDMI) != 0)) {
   4809                     mFixedVolumeDevices |= AudioSystem.DEVICE_OUT_HDMI;
   4810                     checkAllFixedVolumeDevices();
   4811                     if (mHdmiManager != null) {
   4812                         synchronized (mHdmiManager) {
   4813                             if (mHdmiPlaybackClient != null) {
   4814                                 mHdmiCecSink = false;
   4815                                 mHdmiPlaybackClient.queryDisplayStatus(mHdmiDisplayStatusCallback);
   4816                             }
   4817                         }
   4818                     }
   4819                 }
   4820             } else {
   4821                 if (isPlatformTelevision() && ((device & AudioSystem.DEVICE_OUT_HDMI) != 0)) {
   4822                     if (mHdmiManager != null) {
   4823                         synchronized (mHdmiManager) {
   4824                             mHdmiCecSink = false;
   4825                         }
   4826                     }
   4827                 }
   4828             }
   4829             if (!isUsb && (device != AudioSystem.DEVICE_IN_WIRED_HEADSET)) {
   4830                 sendDeviceConnectionIntent(device, state, name);
   4831             }
   4832         }
   4833     }
   4834 
   4835     private void configureHdmiPlugIntent(Intent intent, int state) {
   4836         intent.setAction(AudioManager.ACTION_HDMI_AUDIO_PLUG);
   4837         intent.putExtra(AudioManager.EXTRA_AUDIO_PLUG_STATE, state);
   4838         if (state == 1) {
   4839             ArrayList<AudioPort> ports = new ArrayList<AudioPort>();
   4840             int[] portGeneration = new int[1];
   4841             int status = AudioSystem.listAudioPorts(ports, portGeneration);
   4842             if (status == AudioManager.SUCCESS) {
   4843                 for (AudioPort port : ports) {
   4844                     if (port instanceof AudioDevicePort) {
   4845                         final AudioDevicePort devicePort = (AudioDevicePort) port;
   4846                         if (devicePort.type() == AudioManager.DEVICE_OUT_HDMI ||
   4847                                 devicePort.type() == AudioManager.DEVICE_OUT_HDMI_ARC) {
   4848                             // format the list of supported encodings
   4849                             int[] formats = devicePort.formats();
   4850                             if (formats.length > 0) {
   4851                                 ArrayList<Integer> encodingList = new ArrayList(1);
   4852                                 for (int format : formats) {
   4853                                     // a format in the list can be 0, skip it
   4854                                     if (format != AudioFormat.ENCODING_INVALID) {
   4855                                         encodingList.add(format);
   4856                                     }
   4857                                 }
   4858                                 int[] encodingArray = new int[encodingList.size()];
   4859                                 for (int i = 0 ; i < encodingArray.length ; i++) {
   4860                                     encodingArray[i] = encodingList.get(i);
   4861                                 }
   4862                                 intent.putExtra(AudioManager.EXTRA_ENCODINGS, encodingArray);
   4863                             }
   4864                             // find the maximum supported number of channels
   4865                             int maxChannels = 0;
   4866                             for (int mask : devicePort.channelMasks()) {
   4867                                 int channelCount = AudioFormat.channelCountFromOutChannelMask(mask);
   4868                                 if (channelCount > maxChannels) {
   4869                                     maxChannels = channelCount;
   4870                                 }
   4871                             }
   4872                             intent.putExtra(AudioManager.EXTRA_MAX_CHANNEL_COUNT, maxChannels);
   4873                         }
   4874                     }
   4875                 }
   4876             }
   4877         }
   4878     }
   4879 
   4880     /* cache of the address of the last dock the device was connected to */
   4881     private String mDockAddress;
   4882 
   4883     /**
   4884      * Receiver for misc intent broadcasts the Phone app cares about.
   4885      */
   4886     private class AudioServiceBroadcastReceiver extends BroadcastReceiver {
   4887         @Override
   4888         public void onReceive(Context context, Intent intent) {
   4889             String action = intent.getAction();
   4890             int outDevice;
   4891             int inDevice;
   4892             int state;
   4893 
   4894             if (action.equals(Intent.ACTION_DOCK_EVENT)) {
   4895                 int dockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
   4896                         Intent.EXTRA_DOCK_STATE_UNDOCKED);
   4897                 int config;
   4898                 switch (dockState) {
   4899                     case Intent.EXTRA_DOCK_STATE_DESK:
   4900                         config = AudioSystem.FORCE_BT_DESK_DOCK;
   4901                         break;
   4902                     case Intent.EXTRA_DOCK_STATE_CAR:
   4903                         config = AudioSystem.FORCE_BT_CAR_DOCK;
   4904                         break;
   4905                     case Intent.EXTRA_DOCK_STATE_LE_DESK:
   4906                         config = AudioSystem.FORCE_ANALOG_DOCK;
   4907                         break;
   4908                     case Intent.EXTRA_DOCK_STATE_HE_DESK:
   4909                         config = AudioSystem.FORCE_DIGITAL_DOCK;
   4910                         break;
   4911                     case Intent.EXTRA_DOCK_STATE_UNDOCKED:
   4912                     default:
   4913                         config = AudioSystem.FORCE_NONE;
   4914                 }
   4915                 // Low end docks have a menu to enable or disable audio
   4916                 // (see mDockAudioMediaEnabled)
   4917                 if (!((dockState == Intent.EXTRA_DOCK_STATE_LE_DESK) ||
   4918                       ((dockState == Intent.EXTRA_DOCK_STATE_UNDOCKED) &&
   4919                        (mDockState == Intent.EXTRA_DOCK_STATE_LE_DESK)))) {
   4920                     AudioSystem.setForceUse(AudioSystem.FOR_DOCK, config);
   4921                 }
   4922                 mDockState = dockState;
   4923             } else if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) {
   4924                 state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE,
   4925                                                BluetoothProfile.STATE_DISCONNECTED);
   4926                 outDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO;
   4927                 inDevice = AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET;
   4928                 String address = null;
   4929 
   4930                 BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
   4931                 if (btDevice == null) {
   4932                     return;
   4933                 }
   4934 
   4935                 address = btDevice.getAddress();
   4936                 BluetoothClass btClass = btDevice.getBluetoothClass();
   4937                 if (btClass != null) {
   4938                     switch (btClass.getDeviceClass()) {
   4939                     case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET:
   4940                     case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE:
   4941                         outDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
   4942                         break;
   4943                     case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO:
   4944                         outDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
   4945                         break;
   4946                     }
   4947                 }
   4948 
   4949                 if (!BluetoothAdapter.checkBluetoothAddress(address)) {
   4950                     address = "";
   4951                 }
   4952 
   4953                 boolean connected = (state == BluetoothProfile.STATE_CONNECTED);
   4954                 boolean success = handleDeviceConnection(connected, outDevice, address) &&
   4955                                       handleDeviceConnection(connected, inDevice, address);
   4956                 if (success) {
   4957                     synchronized (mScoClients) {
   4958                         if (connected) {
   4959                             mBluetoothHeadsetDevice = btDevice;
   4960                         } else {
   4961                             mBluetoothHeadsetDevice = null;
   4962                             resetBluetoothSco();
   4963                         }
   4964                     }
   4965                 }
   4966             } else if (action.equals(AudioManager.ACTION_USB_AUDIO_ACCESSORY_PLUG)) {
   4967                 state = intent.getIntExtra("state", 0);
   4968 
   4969                 int alsaCard = intent.getIntExtra("card", -1);
   4970                 int alsaDevice = intent.getIntExtra("device", -1);
   4971 
   4972                 String params = (alsaCard == -1 && alsaDevice == -1 ? ""
   4973                                     : "card=" + alsaCard + ";device=" + alsaDevice);
   4974 
   4975                 // Playback Device
   4976                 outDevice = AudioSystem.DEVICE_OUT_USB_ACCESSORY;
   4977                 setWiredDeviceConnectionState(outDevice, state, params);
   4978             } else if (action.equals(AudioManager.ACTION_USB_AUDIO_DEVICE_PLUG)) {
   4979                 // FIXME Does not yet handle the case where the setting is changed
   4980                 // after device connection.  Ideally we should handle the settings change
   4981                 // in SettingsObserver. Here we should log that a USB device is connected
   4982                 // and disconnected with its address (card , device) and force the
   4983                 // connection or disconnection when the setting changes.
   4984                 int isDisabled = Settings.Secure.getInt(mContentResolver,
   4985                         Settings.Secure.USB_AUDIO_AUTOMATIC_ROUTING_DISABLED, 0);
   4986                 if (isDisabled != 0) {
   4987                     return;
   4988                 }
   4989 
   4990                 state = intent.getIntExtra("state", 0);
   4991 
   4992                 int alsaCard = intent.getIntExtra("card", -1);
   4993                 int alsaDevice = intent.getIntExtra("device", -1);
   4994                 boolean hasPlayback = intent.getBooleanExtra("hasPlayback", false);
   4995                 boolean hasCapture = intent.getBooleanExtra("hasCapture", false);
   4996                 boolean hasMIDI = intent.getBooleanExtra("hasMIDI", false);
   4997 
   4998                 String params = (alsaCard == -1 && alsaDevice == -1 ? ""
   4999                                     : "card=" + alsaCard + ";device=" + alsaDevice);
   5000 
   5001                 // Playback Device
   5002                 if (hasPlayback) {
   5003                     outDevice = AudioSystem.DEVICE_OUT_USB_DEVICE;
   5004                     setWiredDeviceConnectionState(outDevice, state, params);
   5005                 }
   5006 
   5007                 // Capture Device
   5008                 if (hasCapture) {
   5009                     inDevice = AudioSystem.DEVICE_IN_USB_DEVICE;
   5010                     setWiredDeviceConnectionState(inDevice, state, params);
   5011                 }
   5012             } else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
   5013                 boolean broadcast = false;
   5014                 int scoAudioState = AudioManager.SCO_AUDIO_STATE_ERROR;
   5015                 synchronized (mScoClients) {
   5016                     int btState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
   5017                     // broadcast intent if the connection was initated by AudioService
   5018                     if (!mScoClients.isEmpty() &&
   5019                             (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL ||
   5020                              mScoAudioState == SCO_STATE_ACTIVATE_REQ ||
   5021                              mScoAudioState == SCO_STATE_DEACTIVATE_REQ)) {
   5022                         broadcast = true;
   5023                     }
   5024                     switch (btState) {
   5025                     case BluetoothHeadset.STATE_AUDIO_CONNECTED:
   5026                         scoAudioState = AudioManager.SCO_AUDIO_STATE_CONNECTED;
   5027                         if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL &&
   5028                             mScoAudioState != SCO_STATE_DEACTIVATE_REQ &&
   5029                             mScoAudioState != SCO_STATE_DEACTIVATE_EXT_REQ) {
   5030                             mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL;
   5031                         }
   5032                         break;
   5033                     case BluetoothHeadset.STATE_AUDIO_DISCONNECTED:
   5034                         scoAudioState = AudioManager.SCO_AUDIO_STATE_DISCONNECTED;
   5035                         mScoAudioState = SCO_STATE_INACTIVE;
   5036                         clearAllScoClients(0, false);
   5037                         break;
   5038                     case BluetoothHeadset.STATE_AUDIO_CONNECTING:
   5039                         if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL &&
   5040                             mScoAudioState != SCO_STATE_DEACTIVATE_REQ &&
   5041                             mScoAudioState != SCO_STATE_DEACTIVATE_EXT_REQ) {
   5042                             mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL;
   5043                         }
   5044                     default:
   5045                         // do not broadcast CONNECTING or invalid state
   5046                         broadcast = false;
   5047                         break;
   5048                     }
   5049                 }
   5050                 if (broadcast) {
   5051                     broadcastScoConnectionState(scoAudioState);
   5052                     //FIXME: this is to maintain compatibility with deprecated intent
   5053                     // AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. Remove when appropriate.
   5054                     Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED);
   5055                     newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, scoAudioState);
   5056                     sendStickyBroadcastToAll(newIntent);
   5057                 }
   5058             } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
   5059                 if (mMonitorRotation) {
   5060                     mOrientationListener.onOrientationChanged(0); //argument is ignored anyway
   5061                     mOrientationListener.enable();
   5062                 }
   5063                 AudioSystem.setParameters("screen_state=on");
   5064             } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
   5065                 if (mMonitorRotation) {
   5066                     //reduce wakeups (save current) by only listening when display is on
   5067                     mOrientationListener.disable();
   5068                 }
   5069                 AudioSystem.setParameters("screen_state=off");
   5070             } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
   5071                 handleConfigurationChanged(context);
   5072             } else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
   5073                 // attempt to stop music playback for background user
   5074                 sendMsg(mAudioHandler,
   5075                         MSG_BROADCAST_AUDIO_BECOMING_NOISY,
   5076                         SENDMSG_REPLACE,
   5077                         0,
   5078                         0,
   5079                         null,
   5080                         0);
   5081                 // the current audio focus owner is no longer valid
   5082                 mMediaFocusControl.discardAudioFocusOwner();
   5083 
   5084                 // load volume settings for new user
   5085                 readAudioSettings(true /*userSwitch*/);
   5086                 // preserve STREAM_MUSIC volume from one user to the next.
   5087                 sendMsg(mAudioHandler,
   5088                         MSG_SET_ALL_VOLUMES,
   5089                         SENDMSG_QUEUE,
   5090                         0,
   5091                         0,
   5092                         mStreamStates[AudioSystem.STREAM_MUSIC], 0);
   5093             }
   5094         }
   5095     } // end class AudioServiceBroadcastReceiver
   5096 
   5097     //==========================================================================================
   5098     // RemoteControlDisplay / RemoteControlClient / Remote info
   5099     //==========================================================================================
   5100     public boolean registerRemoteController(IRemoteControlDisplay rcd, int w, int h,
   5101             ComponentName listenerComp) {
   5102         return mMediaFocusControl.registerRemoteController(rcd, w, h, listenerComp);
   5103     }
   5104 
   5105     public boolean registerRemoteControlDisplay(IRemoteControlDisplay rcd, int w, int h) {
   5106         return mMediaFocusControl.registerRemoteControlDisplay(rcd, w, h);
   5107     }
   5108 
   5109     public void unregisterRemoteControlDisplay(IRemoteControlDisplay rcd) {
   5110         mMediaFocusControl.unregisterRemoteControlDisplay(rcd);
   5111     }
   5112 
   5113     public void remoteControlDisplayUsesBitmapSize(IRemoteControlDisplay rcd, int w, int h) {
   5114         mMediaFocusControl.remoteControlDisplayUsesBitmapSize(rcd, w, h);
   5115     }
   5116 
   5117     public void remoteControlDisplayWantsPlaybackPositionSync(IRemoteControlDisplay rcd,
   5118             boolean wantsSync) {
   5119         mMediaFocusControl.remoteControlDisplayWantsPlaybackPositionSync(rcd, wantsSync);
   5120     }
   5121 
   5122     @Override
   5123     public void setRemoteStreamVolume(int index) {
   5124         enforceSelfOrSystemUI("set the remote stream volume");
   5125         mMediaFocusControl.setRemoteStreamVolume(index);
   5126     }
   5127 
   5128     //==========================================================================================
   5129     // Audio Focus
   5130     //==========================================================================================
   5131     public int requestAudioFocus(AudioAttributes aa, int durationHint, IBinder cb,
   5132             IAudioFocusDispatcher fd, String clientId, String callingPackageName, int flags,
   5133             IAudioPolicyCallback pcb) {
   5134         // permission checks
   5135         if ((flags & AudioManager.AUDIOFOCUS_FLAG_LOCK) == AudioManager.AUDIOFOCUS_FLAG_LOCK) {
   5136             if (mMediaFocusControl.IN_VOICE_COMM_FOCUS_ID.equals(clientId)) {
   5137                 if (PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission(
   5138                             android.Manifest.permission.MODIFY_PHONE_STATE)) {
   5139                     Log.e(TAG, "Invalid permission to (un)lock audio focus", new Exception());
   5140                     return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
   5141                 }
   5142             } else {
   5143                 // only a registered audio policy can be used to lock focus
   5144                 synchronized (mAudioPolicies) {
   5145                     if (!mAudioPolicies.containsKey(pcb.asBinder())) {
   5146                         Log.e(TAG, "Invalid unregistered AudioPolicy to (un)lock audio focus");
   5147                         return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
   5148                     }
   5149                 }
   5150             }
   5151         }
   5152 
   5153         return mMediaFocusControl.requestAudioFocus(aa, durationHint, cb, fd,
   5154                 clientId, callingPackageName, flags);
   5155     }
   5156 
   5157     public int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId, AudioAttributes aa) {
   5158         return mMediaFocusControl.abandonAudioFocus(fd, clientId, aa);
   5159     }
   5160 
   5161     public void unregisterAudioFocusClient(String clientId) {
   5162         mMediaFocusControl.unregisterAudioFocusClient(clientId);
   5163     }
   5164 
   5165     public int getCurrentAudioFocus() {
   5166         return mMediaFocusControl.getCurrentAudioFocus();
   5167     }
   5168 
   5169     //==========================================================================================
   5170     // Device orientation
   5171     //==========================================================================================
   5172     /**
   5173      * Handles device configuration changes that may map to a change in the orientation
   5174      * or orientation.
   5175      * Monitoring orientation and rotation is optional, and is defined by the definition and value
   5176      * of the "ro.audio.monitorOrientation" and "ro.audio.monitorRotation" system properties.
   5177      */
   5178     private void handleConfigurationChanged(Context context) {
   5179         try {
   5180             // reading new orientation "safely" (i.e. under try catch) in case anything
   5181             // goes wrong when obtaining resources and configuration
   5182             Configuration config = context.getResources().getConfiguration();
   5183             // TODO merge rotation and orientation
   5184             if (mMonitorOrientation) {
   5185                 int newOrientation = config.orientation;
   5186                 if (newOrientation != mDeviceOrientation) {
   5187                     mDeviceOrientation = newOrientation;
   5188                     setOrientationForAudioSystem();
   5189                 }
   5190             }
   5191             sendMsg(mAudioHandler,
   5192                     MSG_CONFIGURE_SAFE_MEDIA_VOLUME,
   5193                     SENDMSG_REPLACE,
   5194                     0,
   5195                     0,
   5196                     null,
   5197                     0);
   5198 
   5199             boolean cameraSoundForced = mContext.getResources().getBoolean(
   5200                     com.android.internal.R.bool.config_camera_sound_forced);
   5201             synchronized (mSettingsLock) {
   5202                 boolean cameraSoundForcedChanged = false;
   5203                 synchronized (mCameraSoundForced) {
   5204                     if (cameraSoundForced != mCameraSoundForced) {
   5205                         mCameraSoundForced = cameraSoundForced;
   5206                         cameraSoundForcedChanged = true;
   5207                     }
   5208                 }
   5209                 if (cameraSoundForcedChanged) {
   5210                     if (!isPlatformTelevision()) {
   5211                         VolumeStreamState s = mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED];
   5212                         if (cameraSoundForced) {
   5213                             s.setAllIndexesToMax();
   5214                             mRingerModeAffectedStreams &=
   5215                                     ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
   5216                         } else {
   5217                             s.setAllIndexes(mStreamStates[AudioSystem.STREAM_SYSTEM]);
   5218                             mRingerModeAffectedStreams |=
   5219                                     (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
   5220                         }
   5221                         // take new state into account for streams muted by ringer mode
   5222                         setRingerModeInt(getRingerModeInternal(), false);
   5223                     }
   5224 
   5225                     sendMsg(mAudioHandler,
   5226                             MSG_SET_FORCE_USE,
   5227                             SENDMSG_QUEUE,
   5228                             AudioSystem.FOR_SYSTEM,
   5229                             cameraSoundForced ?
   5230                                     AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE,
   5231                             null,
   5232                             0);
   5233 
   5234                     sendMsg(mAudioHandler,
   5235                             MSG_SET_ALL_VOLUMES,
   5236                             SENDMSG_QUEUE,
   5237                             0,
   5238                             0,
   5239                             mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED], 0);
   5240                 }
   5241             }
   5242             mVolumeController.setLayoutDirection(config.getLayoutDirection());
   5243         } catch (Exception e) {
   5244             Log.e(TAG, "Error handling configuration change: ", e);
   5245         }
   5246     }
   5247 
   5248     private void setOrientationForAudioSystem() {
   5249         switch (mDeviceOrientation) {
   5250             case Configuration.ORIENTATION_LANDSCAPE:
   5251                 //Log.i(TAG, "orientation is landscape");
   5252                 AudioSystem.setParameters("orientation=landscape");
   5253                 break;
   5254             case Configuration.ORIENTATION_PORTRAIT:
   5255                 //Log.i(TAG, "orientation is portrait");
   5256                 AudioSystem.setParameters("orientation=portrait");
   5257                 break;
   5258             case Configuration.ORIENTATION_SQUARE:
   5259                 //Log.i(TAG, "orientation is square");
   5260                 AudioSystem.setParameters("orientation=square");
   5261                 break;
   5262             case Configuration.ORIENTATION_UNDEFINED:
   5263                 //Log.i(TAG, "orientation is undefined");
   5264                 AudioSystem.setParameters("orientation=undefined");
   5265                 break;
   5266             default:
   5267                 Log.e(TAG, "Unknown orientation");
   5268         }
   5269     }
   5270 
   5271     private void setRotationForAudioSystem() {
   5272         switch (mDeviceRotation) {
   5273             case Surface.ROTATION_0:
   5274                 AudioSystem.setParameters("rotation=0");
   5275                 break;
   5276             case Surface.ROTATION_90:
   5277                 AudioSystem.setParameters("rotation=90");
   5278                 break;
   5279             case Surface.ROTATION_180:
   5280                 AudioSystem.setParameters("rotation=180");
   5281                 break;
   5282             case Surface.ROTATION_270:
   5283                 AudioSystem.setParameters("rotation=270");
   5284                 break;
   5285             default:
   5286                 Log.e(TAG, "Unknown device rotation");
   5287         }
   5288     }
   5289 
   5290 
   5291     // Handles request to override default use of A2DP for media.
   5292     public void setBluetoothA2dpOnInt(boolean on) {
   5293         synchronized (mBluetoothA2dpEnabledLock) {
   5294             mBluetoothA2dpEnabled = on;
   5295             mAudioHandler.removeMessages(MSG_SET_FORCE_BT_A2DP_USE);
   5296             AudioSystem.setForceUse(AudioSystem.FOR_MEDIA,
   5297                     mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP);
   5298         }
   5299     }
   5300 
   5301     @Override
   5302     public void setRingtonePlayer(IRingtonePlayer player) {
   5303         mContext.enforceCallingOrSelfPermission(REMOTE_AUDIO_PLAYBACK, null);
   5304         mRingtonePlayer = player;
   5305     }
   5306 
   5307     @Override
   5308     public IRingtonePlayer getRingtonePlayer() {
   5309         return mRingtonePlayer;
   5310     }
   5311 
   5312     @Override
   5313     public AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) {
   5314         synchronized (mCurAudioRoutes) {
   5315             AudioRoutesInfo routes = new AudioRoutesInfo(mCurAudioRoutes);
   5316             mRoutesObservers.register(observer);
   5317             return routes;
   5318         }
   5319     }
   5320 
   5321 
   5322     //==========================================================================================
   5323     // Safe media volume management.
   5324     // MUSIC stream volume level is limited when headphones are connected according to safety
   5325     // regulation. When the user attempts to raise the volume above the limit, a warning is
   5326     // displayed and the user has to acknowlegde before the volume is actually changed.
   5327     // The volume index corresponding to the limit is stored in config_safe_media_volume_index
   5328     // property. Platforms with a different limit must set this property accordingly in their
   5329     // overlay.
   5330     //==========================================================================================
   5331 
   5332     // mSafeMediaVolumeState indicates whether the media volume is limited over headphones.
   5333     // It is SAFE_MEDIA_VOLUME_NOT_CONFIGURED at boot time until a network service is connected
   5334     // or the configure time is elapsed. It is then set to SAFE_MEDIA_VOLUME_ACTIVE or
   5335     // SAFE_MEDIA_VOLUME_DISABLED according to country option. If not SAFE_MEDIA_VOLUME_DISABLED, it
   5336     // can be set to SAFE_MEDIA_VOLUME_INACTIVE by calling AudioService.disableSafeMediaVolume()
   5337     // (when user opts out).
   5338     private static final int SAFE_MEDIA_VOLUME_NOT_CONFIGURED = 0;
   5339     private static final int SAFE_MEDIA_VOLUME_DISABLED = 1;
   5340     private static final int SAFE_MEDIA_VOLUME_INACTIVE = 2;  // confirmed
   5341     private static final int SAFE_MEDIA_VOLUME_ACTIVE = 3;  // unconfirmed
   5342     private Integer mSafeMediaVolumeState;
   5343 
   5344     private int mMcc = 0;
   5345     // mSafeMediaVolumeIndex is the cached value of config_safe_media_volume_index property
   5346     private int mSafeMediaVolumeIndex;
   5347     // mSafeMediaVolumeDevices lists the devices for which safe media volume is enforced,
   5348     private final int mSafeMediaVolumeDevices = AudioSystem.DEVICE_OUT_WIRED_HEADSET |
   5349                                                 AudioSystem.DEVICE_OUT_WIRED_HEADPHONE;
   5350     // mMusicActiveMs is the cumulative time of music activity since safe volume was disabled.
   5351     // When this time reaches UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX, the safe media volume is re-enabled
   5352     // automatically. mMusicActiveMs is rounded to a multiple of MUSIC_ACTIVE_POLL_PERIOD_MS.
   5353     private int mMusicActiveMs;
   5354     private static final int UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX = (20 * 3600 * 1000); // 20 hours
   5355     private static final int MUSIC_ACTIVE_POLL_PERIOD_MS = 60000;  // 1 minute polling interval
   5356     private static final int SAFE_VOLUME_CONFIGURE_TIMEOUT_MS = 30000;  // 30s after boot completed
   5357 
   5358     private void setSafeMediaVolumeEnabled(boolean on) {
   5359         synchronized (mSafeMediaVolumeState) {
   5360             if ((mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_NOT_CONFIGURED) &&
   5361                     (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_DISABLED)) {
   5362                 if (on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE)) {
   5363                     mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE;
   5364                     enforceSafeMediaVolume();
   5365                 } else if (!on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE)) {
   5366                     mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE;
   5367                     mMusicActiveMs = 1;  // nonzero = confirmed
   5368                     saveMusicActiveMs();
   5369                     sendMsg(mAudioHandler,
   5370                             MSG_CHECK_MUSIC_ACTIVE,
   5371                             SENDMSG_REPLACE,
   5372                             0,
   5373                             0,
   5374                             null,
   5375                             MUSIC_ACTIVE_POLL_PERIOD_MS);
   5376                 }
   5377             }
   5378         }
   5379     }
   5380 
   5381     private void enforceSafeMediaVolume() {
   5382         VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC];
   5383         int devices = mSafeMediaVolumeDevices;
   5384         int i = 0;
   5385 
   5386         while (devices != 0) {
   5387             int device = 1 << i++;
   5388             if ((device & devices) == 0) {
   5389                 continue;
   5390             }
   5391             int index = streamState.getIndex(device);
   5392             if (index > mSafeMediaVolumeIndex) {
   5393                 streamState.setIndex(mSafeMediaVolumeIndex, device);
   5394                 sendMsg(mAudioHandler,
   5395                         MSG_SET_DEVICE_VOLUME,
   5396                         SENDMSG_QUEUE,
   5397                         device,
   5398                         0,
   5399                         streamState,
   5400                         0);
   5401             }
   5402             devices &= ~device;
   5403         }
   5404     }
   5405 
   5406     private boolean checkSafeMediaVolume(int streamType, int index, int device) {
   5407         synchronized (mSafeMediaVolumeState) {
   5408             if ((mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) &&
   5409                     (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
   5410                     ((device & mSafeMediaVolumeDevices) != 0) &&
   5411                     (index > mSafeMediaVolumeIndex)) {
   5412                 return false;
   5413             }
   5414             return true;
   5415         }
   5416     }
   5417 
   5418     @Override
   5419     public void disableSafeMediaVolume() {
   5420         enforceSelfOrSystemUI("disable the safe media volume");
   5421         synchronized (mSafeMediaVolumeState) {
   5422             setSafeMediaVolumeEnabled(false);
   5423             if (mPendingVolumeCommand != null) {
   5424                 onSetStreamVolume(mPendingVolumeCommand.mStreamType,
   5425                                   mPendingVolumeCommand.mIndex,
   5426                                   mPendingVolumeCommand.mFlags,
   5427                                   mPendingVolumeCommand.mDevice);
   5428                 mPendingVolumeCommand = null;
   5429             }
   5430         }
   5431     }
   5432 
   5433     //==========================================================================================
   5434     // Hdmi Cec system audio mode.
   5435     // If Hdmi Cec's system audio mode is on, audio service should notify volume change
   5436     // to HdmiControlService so that audio recevier can handle volume change.
   5437     //==========================================================================================
   5438 
   5439     private class MyDisplayStatusCallback implements HdmiPlaybackClient.DisplayStatusCallback {
   5440         public void onComplete(int status) {
   5441             if (mHdmiManager != null) {
   5442                 synchronized (mHdmiManager) {
   5443                     mHdmiCecSink = (status != HdmiControlManager.POWER_STATUS_UNKNOWN);
   5444                     // Television devices without CEC service apply software volume on HDMI output
   5445                     if (isPlatformTelevision() && !mHdmiCecSink) {
   5446                         mFixedVolumeDevices &= ~AudioSystem.DEVICE_OUT_HDMI;
   5447                     }
   5448                     checkAllFixedVolumeDevices();
   5449                 }
   5450             }
   5451         }
   5452     };
   5453 
   5454     // If HDMI-CEC system audio is supported
   5455     private boolean mHdmiSystemAudioSupported = false;
   5456     // Set only when device is tv.
   5457     private HdmiTvClient mHdmiTvClient;
   5458     // true if the device has system feature PackageManager.FEATURE_LEANBACK.
   5459     // cached HdmiControlManager interface
   5460     private HdmiControlManager mHdmiManager;
   5461     // Set only when device is a set-top box.
   5462     private HdmiPlaybackClient mHdmiPlaybackClient;
   5463     // true if we are a set-top box, an HDMI sink is connected and it supports CEC.
   5464     private boolean mHdmiCecSink;
   5465 
   5466     private MyDisplayStatusCallback mHdmiDisplayStatusCallback = new MyDisplayStatusCallback();
   5467 
   5468     @Override
   5469     public int setHdmiSystemAudioSupported(boolean on) {
   5470         int device = AudioSystem.DEVICE_NONE;
   5471         if (mHdmiManager != null) {
   5472             synchronized (mHdmiManager) {
   5473                 if (mHdmiTvClient == null) {
   5474                     Log.w(TAG, "Only Hdmi-Cec enabled TV device supports system audio mode.");
   5475                     return device;
   5476                 }
   5477 
   5478                 synchronized (mHdmiTvClient) {
   5479                     if (mHdmiSystemAudioSupported != on) {
   5480                         mHdmiSystemAudioSupported = on;
   5481                         AudioSystem.setForceUse(AudioSystem.FOR_HDMI_SYSTEM_AUDIO,
   5482                                 on ? AudioSystem.FORCE_HDMI_SYSTEM_AUDIO_ENFORCED :
   5483                                      AudioSystem.FORCE_NONE);
   5484                     }
   5485                     device = AudioSystem.getDevicesForStream(AudioSystem.STREAM_MUSIC);
   5486                 }
   5487             }
   5488         }
   5489         return device;
   5490     }
   5491 
   5492     @Override
   5493     public boolean isHdmiSystemAudioSupported() {
   5494         return mHdmiSystemAudioSupported;
   5495     }
   5496 
   5497     //==========================================================================================
   5498     // Accessibility: taking touch exploration into account for selecting the default
   5499     //   stream override timeout when adjusting volume
   5500     //==========================================================================================
   5501     private static class StreamOverride
   5502             implements AccessibilityManager.TouchExplorationStateChangeListener {
   5503 
   5504         // AudioService.getActiveStreamType() will return:
   5505         // - STREAM_NOTIFICATION on tablets during this period after a notification stopped
   5506         // - STREAM_MUSIC on phones during this period after music or talkback/voice search prompt
   5507         // stopped
   5508         private static final int DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS = 5000;
   5509         private static final int TOUCH_EXPLORE_STREAM_TYPE_OVERRIDE_DELAY_MS = 1000;
   5510 
   5511         static int sDelayMs;
   5512 
   5513         static void init(Context ctxt) {
   5514             AccessibilityManager accessibilityManager =
   5515                     (AccessibilityManager) ctxt.getSystemService(Context.ACCESSIBILITY_SERVICE);
   5516             updateDefaultStreamOverrideDelay(
   5517                     accessibilityManager.isTouchExplorationEnabled());
   5518             accessibilityManager.addTouchExplorationStateChangeListener(
   5519                     new StreamOverride());
   5520         }
   5521 
   5522         @Override
   5523         public void onTouchExplorationStateChanged(boolean enabled) {
   5524             updateDefaultStreamOverrideDelay(enabled);
   5525         }
   5526 
   5527         private static void updateDefaultStreamOverrideDelay(boolean touchExploreEnabled) {
   5528             if (touchExploreEnabled) {
   5529                 sDelayMs = TOUCH_EXPLORE_STREAM_TYPE_OVERRIDE_DELAY_MS;
   5530             } else {
   5531                 sDelayMs = DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS;
   5532             }
   5533             if (DEBUG_VOL) Log.d(TAG, "Touch exploration enabled=" + touchExploreEnabled
   5534                     + " stream override delay is now " + sDelayMs + " ms");
   5535         }
   5536     }
   5537 
   5538     //==========================================================================================
   5539     // Camera shutter sound policy.
   5540     // config_camera_sound_forced configuration option in config.xml defines if the camera shutter
   5541     // sound is forced (sound even if the device is in silent mode) or not. This option is false by
   5542     // default and can be overridden by country specific overlay in values-mccXXX/config.xml.
   5543     //==========================================================================================
   5544 
   5545     // cached value of com.android.internal.R.bool.config_camera_sound_forced
   5546     private Boolean mCameraSoundForced;
   5547 
   5548     // called by android.hardware.Camera to populate CameraInfo.canDisableShutterSound
   5549     public boolean isCameraSoundForced() {
   5550         synchronized (mCameraSoundForced) {
   5551             return mCameraSoundForced;
   5552         }
   5553     }
   5554 
   5555     private static final String[] RINGER_MODE_NAMES = new String[] {
   5556             "SILENT",
   5557             "VIBRATE",
   5558             "NORMAL"
   5559     };
   5560 
   5561     private void dumpRingerMode(PrintWriter pw) {
   5562         pw.println("\nRinger mode: ");
   5563         pw.println("- mode (internal) = " + RINGER_MODE_NAMES[mRingerMode]);
   5564         pw.println("- mode (external) = " + RINGER_MODE_NAMES[mRingerModeExternal]);
   5565         pw.print("- ringer mode affected streams = 0x");
   5566         pw.println(Integer.toHexString(mRingerModeAffectedStreams));
   5567         pw.print("- ringer mode muted streams = 0x");
   5568         pw.println(Integer.toHexString(mRingerModeMutedStreams));
   5569         pw.print("- delegate = "); pw.println(mRingerModeDelegate);
   5570     }
   5571 
   5572     @Override
   5573     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
   5574         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
   5575 
   5576         mMediaFocusControl.dump(pw);
   5577         dumpStreamStates(pw);
   5578         dumpRingerMode(pw);
   5579         pw.println("\nAudio routes:");
   5580         pw.print("  mMainType=0x"); pw.println(Integer.toHexString(mCurAudioRoutes.mMainType));
   5581         pw.print("  mBluetoothName="); pw.println(mCurAudioRoutes.mBluetoothName);
   5582 
   5583         pw.println("\nOther state:");
   5584         pw.print("  mVolumeController="); pw.println(mVolumeController);
   5585         pw.print("  mSafeMediaVolumeState=");
   5586         pw.println(safeMediaVolumeStateToString(mSafeMediaVolumeState));
   5587         pw.print("  mSafeMediaVolumeIndex="); pw.println(mSafeMediaVolumeIndex);
   5588         pw.print("  mPendingVolumeCommand="); pw.println(mPendingVolumeCommand);
   5589         pw.print("  mMusicActiveMs="); pw.println(mMusicActiveMs);
   5590         pw.print("  mMcc="); pw.println(mMcc);
   5591         pw.print("  mHasVibrator="); pw.println(mHasVibrator);
   5592 
   5593         dumpAudioPolicies(pw);
   5594     }
   5595 
   5596     private static String safeMediaVolumeStateToString(Integer state) {
   5597         switch(state) {
   5598             case SAFE_MEDIA_VOLUME_NOT_CONFIGURED: return "SAFE_MEDIA_VOLUME_NOT_CONFIGURED";
   5599             case SAFE_MEDIA_VOLUME_DISABLED: return "SAFE_MEDIA_VOLUME_DISABLED";
   5600             case SAFE_MEDIA_VOLUME_INACTIVE: return "SAFE_MEDIA_VOLUME_INACTIVE";
   5601             case SAFE_MEDIA_VOLUME_ACTIVE: return "SAFE_MEDIA_VOLUME_ACTIVE";
   5602         }
   5603         return null;
   5604     }
   5605 
   5606     // Inform AudioFlinger of our device's low RAM attribute
   5607     private static void readAndSetLowRamDevice()
   5608     {
   5609         int status = AudioSystem.setLowRamDevice(ActivityManager.isLowRamDeviceStatic());
   5610         if (status != 0) {
   5611             Log.w(TAG, "AudioFlinger informed of device's low RAM attribute; status " + status);
   5612         }
   5613     }
   5614 
   5615     private void enforceSelfOrSystemUI(String action) {
   5616         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE,
   5617                 "Only SystemUI can " + action);
   5618     }
   5619 
   5620     @Override
   5621     public void setVolumeController(final IVolumeController controller) {
   5622         enforceSelfOrSystemUI("set the volume controller");
   5623 
   5624         // return early if things are not actually changing
   5625         if (mVolumeController.isSameBinder(controller)) {
   5626             return;
   5627         }
   5628 
   5629         // dismiss the old volume controller
   5630         mVolumeController.postDismiss();
   5631         if (controller != null) {
   5632             // we are about to register a new controller, listen for its death
   5633             try {
   5634                 controller.asBinder().linkToDeath(new DeathRecipient() {
   5635                     @Override
   5636                     public void binderDied() {
   5637                         if (mVolumeController.isSameBinder(controller)) {
   5638                             Log.w(TAG, "Current remote volume controller died, unregistering");
   5639                             setVolumeController(null);
   5640                         }
   5641                     }
   5642                 }, 0);
   5643             } catch (RemoteException e) {
   5644                 // noop
   5645             }
   5646         }
   5647         mVolumeController.setController(controller);
   5648         if (DEBUG_VOL) Log.d(TAG, "Volume controller: " + mVolumeController);
   5649     }
   5650 
   5651     @Override
   5652     public void notifyVolumeControllerVisible(final IVolumeController controller, boolean visible) {
   5653         enforceSelfOrSystemUI("notify about volume controller visibility");
   5654 
   5655         // return early if the controller is not current
   5656         if (!mVolumeController.isSameBinder(controller)) {
   5657             return;
   5658         }
   5659 
   5660         mVolumeController.setVisible(visible);
   5661         if (DEBUG_VOL) Log.d(TAG, "Volume controller visible: " + visible);
   5662     }
   5663 
   5664     public static class VolumeController {
   5665         private static final String TAG = "VolumeController";
   5666 
   5667         private IVolumeController mController;
   5668         private boolean mVisible;
   5669         private long mNextLongPress;
   5670         private int mLongPressTimeout;
   5671 
   5672         public void setController(IVolumeController controller) {
   5673             mController = controller;
   5674             mVisible = false;
   5675         }
   5676 
   5677         public void loadSettings(ContentResolver cr) {
   5678             mLongPressTimeout = Settings.Secure.getIntForUser(cr,
   5679                     Settings.Secure.LONG_PRESS_TIMEOUT, 500, UserHandle.USER_CURRENT);
   5680         }
   5681 
   5682         public boolean suppressAdjustment(int resolvedStream, int flags) {
   5683             boolean suppress = false;
   5684             if (resolvedStream == AudioSystem.STREAM_RING && mController != null) {
   5685                 final long now = SystemClock.uptimeMillis();
   5686                 if ((flags & AudioManager.FLAG_SHOW_UI) != 0 && !mVisible) {
   5687                     // ui will become visible
   5688                     if (mNextLongPress < now) {
   5689                         mNextLongPress = now + mLongPressTimeout;
   5690                     }
   5691                     suppress = true;
   5692                 } else if (mNextLongPress > 0) {  // in a long-press
   5693                     if (now > mNextLongPress) {
   5694                         // long press triggered, no more suppression
   5695                         mNextLongPress = 0;
   5696                     } else {
   5697                         // keep suppressing until the long press triggers
   5698                         suppress = true;
   5699                     }
   5700                 }
   5701             }
   5702             return suppress;
   5703         }
   5704 
   5705         public void setVisible(boolean visible) {
   5706             mVisible = visible;
   5707         }
   5708 
   5709         public boolean isSameBinder(IVolumeController controller) {
   5710             return Objects.equals(asBinder(), binder(controller));
   5711         }
   5712 
   5713         public IBinder asBinder() {
   5714             return binder(mController);
   5715         }
   5716 
   5717         private static IBinder binder(IVolumeController controller) {
   5718             return controller == null ? null : controller.asBinder();
   5719         }
   5720 
   5721         @Override
   5722         public String toString() {
   5723             return "VolumeController(" + asBinder() + ",mVisible=" + mVisible + ")";
   5724         }
   5725 
   5726         public void postDisplaySafeVolumeWarning(int flags) {
   5727             if (mController == null)
   5728                 return;
   5729             try {
   5730                 mController.displaySafeVolumeWarning(flags);
   5731             } catch (RemoteException e) {
   5732                 Log.w(TAG, "Error calling displaySafeVolumeWarning", e);
   5733             }
   5734         }
   5735 
   5736         public void postVolumeChanged(int streamType, int flags) {
   5737             if (mController == null)
   5738                 return;
   5739             try {
   5740                 mController.volumeChanged(streamType, flags);
   5741             } catch (RemoteException e) {
   5742                 Log.w(TAG, "Error calling volumeChanged", e);
   5743             }
   5744         }
   5745 
   5746         public void postMasterVolumeChanged(int flags) {
   5747             if (mController == null)
   5748                 return;
   5749             try {
   5750                 mController.masterVolumeChanged(flags);
   5751             } catch (RemoteException e) {
   5752                 Log.w(TAG, "Error calling masterVolumeChanged", e);
   5753             }
   5754         }
   5755 
   5756         public void postMasterMuteChanged(int flags) {
   5757             if (mController == null)
   5758                 return;
   5759             try {
   5760                 mController.masterMuteChanged(flags);
   5761             } catch (RemoteException e) {
   5762                 Log.w(TAG, "Error calling masterMuteChanged", e);
   5763             }
   5764         }
   5765 
   5766         public void setLayoutDirection(int layoutDirection) {
   5767             if (mController == null)
   5768                 return;
   5769             try {
   5770                 mController.setLayoutDirection(layoutDirection);
   5771             } catch (RemoteException e) {
   5772                 Log.w(TAG, "Error calling setLayoutDirection", e);
   5773             }
   5774         }
   5775 
   5776         public void postDismiss() {
   5777             if (mController == null)
   5778                 return;
   5779             try {
   5780                 mController.dismiss();
   5781             } catch (RemoteException e) {
   5782                 Log.w(TAG, "Error calling dismiss", e);
   5783             }
   5784         }
   5785     }
   5786 
   5787     /**
   5788      * Interface for system components to get some extra functionality through
   5789      * LocalServices.
   5790      */
   5791     final class AudioServiceInternal extends AudioManagerInternal {
   5792         @Override
   5793         public void setRingerModeDelegate(RingerModeDelegate delegate) {
   5794             mRingerModeDelegate = delegate;
   5795             if (mRingerModeDelegate != null) {
   5796                 setRingerModeInternal(getRingerModeInternal(), TAG + ".setRingerModeDelegate");
   5797             }
   5798         }
   5799 
   5800         @Override
   5801         public void adjustSuggestedStreamVolumeForUid(int streamType, int direction, int flags,
   5802                 String callingPackage, int uid) {
   5803             // direction and stream type swap here because the public
   5804             // adjustSuggested has a different order than the other methods.
   5805             adjustSuggestedStreamVolume(direction, streamType, flags, callingPackage, uid);
   5806         }
   5807 
   5808         @Override
   5809         public void adjustStreamVolumeForUid(int streamType, int direction, int flags,
   5810                 String callingPackage, int uid) {
   5811             adjustStreamVolume(streamType, direction, flags, callingPackage, uid);
   5812         }
   5813 
   5814         @Override
   5815         public void setStreamVolumeForUid(int streamType, int direction, int flags,
   5816                 String callingPackage, int uid) {
   5817             setStreamVolume(streamType, direction, flags, callingPackage, uid);
   5818         }
   5819 
   5820         @Override
   5821         public void adjustMasterVolumeForUid(int steps, int flags, String callingPackage,
   5822                 int uid) {
   5823             adjustMasterVolume(steps, flags, callingPackage, uid);
   5824         }
   5825 
   5826         @Override
   5827         public int getRingerModeInternal() {
   5828             return AudioService.this.getRingerModeInternal();
   5829         }
   5830 
   5831         @Override
   5832         public void setRingerModeInternal(int ringerMode, String caller) {
   5833             AudioService.this.setRingerModeInternal(ringerMode, caller);
   5834         }
   5835 
   5836         @Override
   5837         public void setMasterMuteForUid(boolean state, int flags, String callingPackage, IBinder cb,
   5838                 int uid) {
   5839             setMasterMuteInternal(state, flags, callingPackage, cb, uid);
   5840         }
   5841     }
   5842 
   5843     //==========================================================================================
   5844     // Audio policy management
   5845     //==========================================================================================
   5846     public String registerAudioPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb,
   5847             boolean hasFocusListener) {
   5848         if (DEBUG_AP) Log.d(TAG, "registerAudioPolicy for " + pcb.asBinder()
   5849                 + " with config:" + policyConfig);
   5850         String regId = null;
   5851         // error handling
   5852         boolean hasPermissionForPolicy =
   5853                 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
   5854                         android.Manifest.permission.MODIFY_AUDIO_ROUTING));
   5855         if (!hasPermissionForPolicy) {
   5856             Slog.w(TAG, "Can't register audio policy for pid " + Binder.getCallingPid() + " / uid "
   5857                     + Binder.getCallingUid() + ", need MODIFY_AUDIO_ROUTING");
   5858             return null;
   5859         }
   5860 
   5861         synchronized (mAudioPolicies) {
   5862             try {
   5863                 if (mAudioPolicies.containsKey(pcb.asBinder())) {
   5864                     Slog.e(TAG, "Cannot re-register policy");
   5865                     return null;
   5866                 }
   5867                 AudioPolicyProxy app = new AudioPolicyProxy(policyConfig, pcb, hasFocusListener);
   5868                 pcb.asBinder().linkToDeath(app, 0/*flags*/);
   5869                 regId = app.getRegistrationId();
   5870                 mAudioPolicies.put(pcb.asBinder(), app);
   5871             } catch (RemoteException e) {
   5872                 // audio policy owner has already died!
   5873                 Slog.w(TAG, "Audio policy registration failed, could not link to " + pcb +
   5874                         " binder death", e);
   5875                 return null;
   5876             }
   5877         }
   5878         return regId;
   5879     }
   5880 
   5881     public void unregisterAudioPolicyAsync(IAudioPolicyCallback pcb) {
   5882         if (DEBUG_AP) Log.d(TAG, "unregisterAudioPolicyAsync for " + pcb.asBinder());
   5883         synchronized (mAudioPolicies) {
   5884             AudioPolicyProxy app = mAudioPolicies.remove(pcb.asBinder());
   5885             if (app == null) {
   5886                 Slog.w(TAG, "Trying to unregister unknown audio policy for pid "
   5887                         + Binder.getCallingPid() + " / uid " + Binder.getCallingUid());
   5888                 return;
   5889             } else {
   5890                 pcb.asBinder().unlinkToDeath(app, 0/*flags*/);
   5891             }
   5892             app.release();
   5893         }
   5894         // TODO implement clearing mix attribute matching info in native audio policy
   5895     }
   5896 
   5897     public int setFocusPropertiesForPolicy(int duckingBehavior, IAudioPolicyCallback pcb) {
   5898         if (DEBUG_AP) Log.d(TAG, "setFocusPropertiesForPolicy() duck behavior=" + duckingBehavior
   5899                 + " policy " +  pcb.asBinder());
   5900         // error handling
   5901         boolean hasPermissionForPolicy =
   5902                 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
   5903                         android.Manifest.permission.MODIFY_AUDIO_ROUTING));
   5904         if (!hasPermissionForPolicy) {
   5905             Slog.w(TAG, "Cannot change audio policy ducking handling for pid " +
   5906                     + Binder.getCallingPid() + " / uid "
   5907                     + Binder.getCallingUid() + ", need MODIFY_AUDIO_ROUTING");
   5908             return AudioManager.ERROR;
   5909         }
   5910 
   5911         synchronized (mAudioPolicies) {
   5912             if (!mAudioPolicies.containsKey(pcb.asBinder())) {
   5913                 Slog.e(TAG, "Cannot change audio policy focus properties, unregistered policy");
   5914                 return AudioManager.ERROR;
   5915             }
   5916             final AudioPolicyProxy app = mAudioPolicies.get(pcb.asBinder());
   5917             if (duckingBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) {
   5918                 // is there already one policy managing ducking?
   5919                 for(AudioPolicyProxy policy : mAudioPolicies.values()) {
   5920                     if (policy.mFocusDuckBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) {
   5921                         Slog.e(TAG, "Cannot change audio policy ducking behavior, already handled");
   5922                         return AudioManager.ERROR;
   5923                     }
   5924                 }
   5925             }
   5926             app.mFocusDuckBehavior = duckingBehavior;
   5927             mMediaFocusControl.setDuckingInExtPolicyAvailable(
   5928                     duckingBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY);
   5929         }
   5930         return AudioManager.SUCCESS;
   5931     }
   5932 
   5933     private void dumpAudioPolicies(PrintWriter pw) {
   5934         pw.println("\nAudio policies:");
   5935         synchronized (mAudioPolicies) {
   5936             for(AudioPolicyProxy policy : mAudioPolicies.values()) {
   5937                 pw.println(policy.toLogFriendlyString());
   5938             }
   5939         }
   5940     }
   5941 
   5942     //======================
   5943     // Audio policy proxy
   5944     //======================
   5945     /**
   5946      * This internal class inherits from AudioPolicyConfig, each instance contains all the
   5947      * mixes of an AudioPolicy and their configurations.
   5948      */
   5949     public class AudioPolicyProxy extends AudioPolicyConfig implements IBinder.DeathRecipient {
   5950         private static final String TAG = "AudioPolicyProxy";
   5951         AudioPolicyConfig mConfig;
   5952         IAudioPolicyCallback mPolicyToken;
   5953         boolean mHasFocusListener;
   5954         /**
   5955          * Audio focus ducking behavior for an audio policy.
   5956          * This variable reflects the value that was successfully set in
   5957          * {@link AudioService#setFocusPropertiesForPolicy(int, IAudioPolicyCallback)}. This
   5958          * implies that a value of FOCUS_POLICY_DUCKING_IN_POLICY means the corresponding policy
   5959          * is handling ducking for audio focus.
   5960          */
   5961         int mFocusDuckBehavior = AudioPolicy.FOCUS_POLICY_DUCKING_DEFAULT;
   5962 
   5963         AudioPolicyProxy(AudioPolicyConfig config, IAudioPolicyCallback token,
   5964                 boolean hasFocusListener) {
   5965             super(config);
   5966             setRegistration(new String(config.hashCode() + ":ap:" + mAudioPolicyCounter++));
   5967             mPolicyToken = token;
   5968             mHasFocusListener = hasFocusListener;
   5969             if (mHasFocusListener) {
   5970                 mMediaFocusControl.addFocusFollower(mPolicyToken);
   5971             }
   5972             connectMixes();
   5973         }
   5974 
   5975         public void binderDied() {
   5976             synchronized (mAudioPolicies) {
   5977                 Log.i(TAG, "audio policy " + mPolicyToken + " died");
   5978                 release();
   5979                 mAudioPolicies.remove(mPolicyToken.asBinder());
   5980             }
   5981         }
   5982 
   5983         String getRegistrationId() {
   5984             return getRegistration();
   5985         }
   5986 
   5987         void release() {
   5988             if (mFocusDuckBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) {
   5989                 mMediaFocusControl.setDuckingInExtPolicyAvailable(false);
   5990             }
   5991             if (mHasFocusListener) {
   5992                 mMediaFocusControl.removeFocusFollower(mPolicyToken);
   5993             }
   5994             AudioSystem.registerPolicyMixes(mMixes, false);
   5995         }
   5996 
   5997         void connectMixes() {
   5998             AudioSystem.registerPolicyMixes(mMixes, true);
   5999         }
   6000     };
   6001 
   6002     private HashMap<IBinder, AudioPolicyProxy> mAudioPolicies =
   6003             new HashMap<IBinder, AudioPolicyProxy>();
   6004     private int mAudioPolicyCounter = 0; // always accessed synchronized on mAudioPolicies
   6005 }
   6006