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.Activity;
     25 import android.app.ActivityManager;
     26 import android.app.ActivityManagerNative;
     27 import android.app.AppOpsManager;
     28 import android.app.KeyguardManager;
     29 import android.app.PendingIntent;
     30 import android.app.PendingIntent.CanceledException;
     31 import android.bluetooth.BluetoothA2dp;
     32 import android.bluetooth.BluetoothAdapter;
     33 import android.bluetooth.BluetoothClass;
     34 import android.bluetooth.BluetoothDevice;
     35 import android.bluetooth.BluetoothHeadset;
     36 import android.bluetooth.BluetoothProfile;
     37 import android.content.ActivityNotFoundException;
     38 import android.content.BroadcastReceiver;
     39 import android.content.ComponentName;
     40 import android.content.ContentResolver;
     41 import android.content.Context;
     42 import android.content.Intent;
     43 import android.content.IntentFilter;
     44 import android.content.pm.PackageManager;
     45 import android.content.res.Configuration;
     46 import android.content.res.Resources;
     47 import android.content.res.XmlResourceParser;
     48 import android.database.ContentObserver;
     49 import android.media.MediaPlayer.OnCompletionListener;
     50 import android.media.MediaPlayer.OnErrorListener;
     51 import android.net.Uri;
     52 import android.net.http.CertificateChainValidator;
     53 import android.net.http.SslError;
     54 import android.os.Binder;
     55 import android.os.Build;
     56 import android.os.Bundle;
     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.ServiceManager;
     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.speech.RecognizerIntent;
     72 import android.telephony.PhoneStateListener;
     73 import android.telephony.TelephonyManager;
     74 import android.text.TextUtils;
     75 import android.util.Log;
     76 import android.view.KeyEvent;
     77 import android.view.Surface;
     78 import android.view.VolumePanel;
     79 import android.view.WindowManager;
     80 
     81 import com.android.internal.telephony.ITelephony;
     82 import com.android.internal.util.XmlUtils;
     83 
     84 import org.xmlpull.v1.XmlPullParserException;
     85 
     86 import java.io.ByteArrayInputStream;
     87 import java.io.FileDescriptor;
     88 import java.io.IOException;
     89 import java.io.PrintWriter;
     90 import java.lang.reflect.Field;
     91 import java.nio.ByteBuffer;
     92 import java.util.ArrayList;
     93 import java.util.concurrent.ConcurrentHashMap;
     94 import java.util.HashMap;
     95 import java.util.HashSet;
     96 import java.util.Iterator;
     97 import java.util.List;
     98 import java.util.Map;
     99 import java.util.NoSuchElementException;
    100 import java.util.Set;
    101 import java.util.Stack;
    102 
    103 /**
    104  * The implementation of the volume manager service.
    105  * <p>
    106  * This implementation focuses on delivering a responsive UI. Most methods are
    107  * asynchronous to external calls. For example, the task of setting a volume
    108  * will update our internal state, but in a separate thread will set the system
    109  * volume and later persist to the database. Similarly, setting the ringer mode
    110  * will update the state and broadcast a change and in a separate thread later
    111  * persist the ringer mode.
    112  *
    113  * @hide
    114  */
    115 public class AudioService extends IAudioService.Stub {
    116 
    117     private static final String TAG = "AudioService";
    118 
    119     /** Debug remote control client/display feature */
    120     protected static final boolean DEBUG_RC = false;
    121     /** Debug volumes */
    122     protected static final boolean DEBUG_VOL = false;
    123     /** Debug cert verification */
    124     private static final boolean DEBUG_CERTS = false;
    125 
    126     /** How long to delay before persisting a change in volume/ringer mode. */
    127     private static final int PERSIST_DELAY = 500;
    128 
    129     private final Context mContext;
    130     private final ContentResolver mContentResolver;
    131     private final AppOpsManager mAppOps;
    132     private final boolean mVoiceCapable;
    133 
    134     /** The UI */
    135     private VolumePanel mVolumePanel;
    136 
    137     // sendMsg() flags
    138     /** If the msg is already queued, replace it with this one. */
    139     private static final int SENDMSG_REPLACE = 0;
    140     /** If the msg is already queued, ignore this one and leave the old. */
    141     private static final int SENDMSG_NOOP = 1;
    142     /** If the msg is already queued, queue this one and leave the old. */
    143     private static final int SENDMSG_QUEUE = 2;
    144 
    145     // AudioHandler messages
    146     private static final int MSG_SET_DEVICE_VOLUME = 0;
    147     private static final int MSG_PERSIST_VOLUME = 1;
    148     private static final int MSG_PERSIST_MASTER_VOLUME = 2;
    149     private static final int MSG_PERSIST_RINGER_MODE = 3;
    150     private static final int MSG_MEDIA_SERVER_DIED = 4;
    151     private static final int MSG_PLAY_SOUND_EFFECT = 5;
    152     private static final int MSG_BTA2DP_DOCK_TIMEOUT = 6;
    153     private static final int MSG_LOAD_SOUND_EFFECTS = 7;
    154     private static final int MSG_SET_FORCE_USE = 8;
    155     private static final int MSG_BT_HEADSET_CNCT_FAILED = 9;
    156     private static final int MSG_SET_ALL_VOLUMES = 10;
    157     private static final int MSG_PERSIST_MASTER_VOLUME_MUTE = 11;
    158     private static final int MSG_REPORT_NEW_ROUTES = 12;
    159     private static final int MSG_SET_FORCE_BT_A2DP_USE = 13;
    160     private static final int MSG_CHECK_MUSIC_ACTIVE = 14;
    161     private static final int MSG_BROADCAST_AUDIO_BECOMING_NOISY = 15;
    162     private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME = 16;
    163     private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED = 17;
    164     private static final int MSG_PERSIST_SAFE_VOLUME_STATE = 18;
    165     private static final int MSG_BROADCAST_BT_CONNECTION_STATE = 19;
    166     private static final int MSG_UNLOAD_SOUND_EFFECTS = 20;
    167     // start of messages handled under wakelock
    168     //   these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(),
    169     //   and not with sendMsg(..., ..., SENDMSG_QUEUE, ...)
    170     private static final int MSG_SET_WIRED_DEVICE_CONNECTION_STATE = 100;
    171     private static final int MSG_SET_A2DP_CONNECTION_STATE = 101;
    172     // end of messages handled under wakelock
    173 
    174     private static final int BTA2DP_DOCK_TIMEOUT_MILLIS = 8000;
    175     // Timeout for connection to bluetooth headset service
    176     private static final int BT_HEADSET_CNCT_TIMEOUT_MS = 3000;
    177 
    178     /** @see AudioSystemThread */
    179     private AudioSystemThread mAudioSystemThread;
    180     /** @see AudioHandler */
    181     private AudioHandler mAudioHandler;
    182     /** @see VolumeStreamState */
    183     private VolumeStreamState[] mStreamStates;
    184     private SettingsObserver mSettingsObserver;
    185 
    186     private int mMode = AudioSystem.MODE_NORMAL;
    187     // protects mRingerMode
    188     private final Object mSettingsLock = new Object();
    189 
    190     private SoundPool mSoundPool;
    191     private final Object mSoundEffectsLock = new Object();
    192     private static final int NUM_SOUNDPOOL_CHANNELS = 4;
    193 
    194     // Internally master volume is a float in the 0.0 - 1.0 range,
    195     // but to support integer based AudioManager API we translate it to 0 - 100
    196     private static final int MAX_MASTER_VOLUME = 100;
    197 
    198     // Maximum volume adjust steps allowed in a single batch call.
    199     private static final int MAX_BATCH_VOLUME_ADJUST_STEPS = 4;
    200 
    201     /* Sound effect file names  */
    202     private static final String SOUND_EFFECTS_PATH = "/media/audio/ui/";
    203     private static final List<String> SOUND_EFFECT_FILES = new ArrayList<String>();
    204 
    205     /* Sound effect file name mapping sound effect id (AudioManager.FX_xxx) to
    206      * file index in SOUND_EFFECT_FILES[] (first column) and indicating if effect
    207      * uses soundpool (second column) */
    208     private final int[][] SOUND_EFFECT_FILES_MAP = new int[AudioManager.NUM_SOUND_EFFECTS][2];
    209 
    210    /** @hide Maximum volume index values for audio streams */
    211     private static final int[] MAX_STREAM_VOLUME = new int[] {
    212         5,  // STREAM_VOICE_CALL
    213         7,  // STREAM_SYSTEM
    214         7,  // STREAM_RING
    215         15, // STREAM_MUSIC
    216         7,  // STREAM_ALARM
    217         7,  // STREAM_NOTIFICATION
    218         15, // STREAM_BLUETOOTH_SCO
    219         7,  // STREAM_SYSTEM_ENFORCED
    220         15, // STREAM_DTMF
    221         15  // STREAM_TTS
    222     };
    223     /* mStreamVolumeAlias[] indicates for each stream if it uses the volume settings
    224      * of another stream: This avoids multiplying the volume settings for hidden
    225      * stream types that follow other stream behavior for volume settings
    226      * NOTE: do not create loops in aliases!
    227      * Some streams alias to different streams according to device category (phone or tablet) or
    228      * use case (in call vs off call...). See updateStreamVolumeAlias() for more details.
    229      *  mStreamVolumeAlias contains the default aliases for a voice capable device (phone) and
    230      *  STREAM_VOLUME_ALIAS_NON_VOICE for a non voice capable device (tablet).*/
    231     private final int[] STREAM_VOLUME_ALIAS = new int[] {
    232         AudioSystem.STREAM_VOICE_CALL,      // STREAM_VOICE_CALL
    233         AudioSystem.STREAM_RING,            // STREAM_SYSTEM
    234         AudioSystem.STREAM_RING,            // STREAM_RING
    235         AudioSystem.STREAM_MUSIC,           // STREAM_MUSIC
    236         AudioSystem.STREAM_ALARM,           // STREAM_ALARM
    237         AudioSystem.STREAM_RING,            // STREAM_NOTIFICATION
    238         AudioSystem.STREAM_BLUETOOTH_SCO,   // STREAM_BLUETOOTH_SCO
    239         AudioSystem.STREAM_RING,            // STREAM_SYSTEM_ENFORCED
    240         AudioSystem.STREAM_RING,            // STREAM_DTMF
    241         AudioSystem.STREAM_MUSIC            // STREAM_TTS
    242     };
    243     private final int[] STREAM_VOLUME_ALIAS_NON_VOICE = new int[] {
    244         AudioSystem.STREAM_VOICE_CALL,      // STREAM_VOICE_CALL
    245         AudioSystem.STREAM_MUSIC,           // STREAM_SYSTEM
    246         AudioSystem.STREAM_RING,            // STREAM_RING
    247         AudioSystem.STREAM_MUSIC,           // STREAM_MUSIC
    248         AudioSystem.STREAM_ALARM,           // STREAM_ALARM
    249         AudioSystem.STREAM_RING,            // STREAM_NOTIFICATION
    250         AudioSystem.STREAM_BLUETOOTH_SCO,   // STREAM_BLUETOOTH_SCO
    251         AudioSystem.STREAM_MUSIC,           // STREAM_SYSTEM_ENFORCED
    252         AudioSystem.STREAM_MUSIC,           // STREAM_DTMF
    253         AudioSystem.STREAM_MUSIC            // STREAM_TTS
    254     };
    255     private int[] mStreamVolumeAlias;
    256 
    257     /**
    258      * Map AudioSystem.STREAM_* constants to app ops.  This should be used
    259      * after mapping through mStreamVolumeAlias.
    260      */
    261     private static final int[] STEAM_VOLUME_OPS = new int[] {
    262         AppOpsManager.OP_AUDIO_VOICE_VOLUME,            // STREAM_VOICE_CALL
    263         AppOpsManager.OP_AUDIO_MEDIA_VOLUME,            // STREAM_SYSTEM
    264         AppOpsManager.OP_AUDIO_RING_VOLUME,             // STREAM_RING
    265         AppOpsManager.OP_AUDIO_MEDIA_VOLUME,            // STREAM_MUSIC
    266         AppOpsManager.OP_AUDIO_ALARM_VOLUME,            // STREAM_ALARM
    267         AppOpsManager.OP_AUDIO_NOTIFICATION_VOLUME,     // STREAM_NOTIFICATION
    268         AppOpsManager.OP_AUDIO_BLUETOOTH_VOLUME,        // STREAM_BLUETOOTH_SCO
    269         AppOpsManager.OP_AUDIO_MEDIA_VOLUME,            // STREAM_SYSTEM_ENFORCED
    270         AppOpsManager.OP_AUDIO_MEDIA_VOLUME,            // STREAM_DTMF
    271         AppOpsManager.OP_AUDIO_MEDIA_VOLUME,            // STREAM_TTS
    272     };
    273 
    274     private final boolean mUseFixedVolume;
    275 
    276     // stream names used by dumpStreamStates()
    277     private final String[] STREAM_NAMES = new String[] {
    278             "STREAM_VOICE_CALL",
    279             "STREAM_SYSTEM",
    280             "STREAM_RING",
    281             "STREAM_MUSIC",
    282             "STREAM_ALARM",
    283             "STREAM_NOTIFICATION",
    284             "STREAM_BLUETOOTH_SCO",
    285             "STREAM_SYSTEM_ENFORCED",
    286             "STREAM_DTMF",
    287             "STREAM_TTS"
    288     };
    289 
    290     private final AudioSystem.ErrorCallback mAudioSystemCallback = new AudioSystem.ErrorCallback() {
    291         public void onError(int error) {
    292             switch (error) {
    293             case AudioSystem.AUDIO_STATUS_SERVER_DIED:
    294                 sendMsg(mAudioHandler, MSG_MEDIA_SERVER_DIED,
    295                         SENDMSG_NOOP, 0, 0, null, 0);
    296                 break;
    297             default:
    298                 break;
    299             }
    300         }
    301     };
    302 
    303     /**
    304      * Current ringer mode from one of {@link AudioManager#RINGER_MODE_NORMAL},
    305      * {@link AudioManager#RINGER_MODE_SILENT}, or
    306      * {@link AudioManager#RINGER_MODE_VIBRATE}.
    307      */
    308     // protected by mSettingsLock
    309     private int mRingerMode;
    310 
    311     /** @see System#MODE_RINGER_STREAMS_AFFECTED */
    312     private int mRingerModeAffectedStreams = 0;
    313 
    314     // Streams currently muted by ringer mode
    315     private int mRingerModeMutedStreams;
    316 
    317     /** @see System#MUTE_STREAMS_AFFECTED */
    318     private int mMuteAffectedStreams;
    319 
    320     /**
    321      * NOTE: setVibrateSetting(), getVibrateSetting(), shouldVibrate() are deprecated.
    322      * mVibrateSetting is just maintained during deprecation period but vibration policy is
    323      * now only controlled by mHasVibrator and mRingerMode
    324      */
    325     private int mVibrateSetting;
    326 
    327     // Is there a vibrator
    328     private final boolean mHasVibrator;
    329 
    330     // Broadcast receiver for device connections intent broadcasts
    331     private final BroadcastReceiver mReceiver = new AudioServiceBroadcastReceiver();
    332 
    333     // Devices currently connected
    334     private final HashMap <Integer, String> mConnectedDevices = new HashMap <Integer, String>();
    335 
    336     // Forced device usage for communications
    337     private int mForcedUseForComm;
    338 
    339     // True if we have master volume support
    340     private final boolean mUseMasterVolume;
    341 
    342     private final int[] mMasterVolumeRamp;
    343 
    344     // List of binder death handlers for setMode() client processes.
    345     // The last process to have called setMode() is at the top of the list.
    346     private final ArrayList <SetModeDeathHandler> mSetModeDeathHandlers = new ArrayList <SetModeDeathHandler>();
    347 
    348     // List of clients having issued a SCO start request
    349     private final ArrayList <ScoClient> mScoClients = new ArrayList <ScoClient>();
    350 
    351     // BluetoothHeadset API to control SCO connection
    352     private BluetoothHeadset mBluetoothHeadset;
    353 
    354     // Bluetooth headset device
    355     private BluetoothDevice mBluetoothHeadsetDevice;
    356 
    357     // Indicate if SCO audio connection is currently active and if the initiator is
    358     // audio service (internal) or bluetooth headset (external)
    359     private int mScoAudioState;
    360     // SCO audio state is not active
    361     private static final int SCO_STATE_INACTIVE = 0;
    362     // SCO audio activation request waiting for headset service to connect
    363     private static final int SCO_STATE_ACTIVATE_REQ = 1;
    364     // SCO audio state is active or starting due to a request from AudioManager API
    365     private static final int SCO_STATE_ACTIVE_INTERNAL = 3;
    366     // SCO audio deactivation request waiting for headset service to connect
    367     private static final int SCO_STATE_DEACTIVATE_REQ = 5;
    368 
    369     // SCO audio state is active due to an action in BT handsfree (either voice recognition or
    370     // in call audio)
    371     private static final int SCO_STATE_ACTIVE_EXTERNAL = 2;
    372     // Deactivation request for all SCO connections (initiated by audio mode change)
    373     // waiting for headset service to connect
    374     private static final int SCO_STATE_DEACTIVATE_EXT_REQ = 4;
    375 
    376     // Indicates the mode used for SCO audio connection. The mode is virtual call if the request
    377     // originated from an app targeting an API version before JB MR2 and raw audio after that.
    378     private int mScoAudioMode;
    379     // SCO audio mode is virtual voice call (BluetoothHeadset.startScoUsingVirtualVoiceCall())
    380     private static final int SCO_MODE_VIRTUAL_CALL = 0;
    381     // SCO audio mode is raw audio (BluetoothHeadset.connectAudio())
    382     private static final int SCO_MODE_RAW = 1;
    383 
    384     // Current connection state indicated by bluetooth headset
    385     private int mScoConnectionState;
    386 
    387     // true if boot sequence has been completed
    388     private boolean mBootCompleted;
    389     // listener for SoundPool sample load completion indication
    390     private SoundPoolCallback mSoundPoolCallBack;
    391     // thread for SoundPool listener
    392     private SoundPoolListenerThread mSoundPoolListenerThread;
    393     // message looper for SoundPool listener
    394     private Looper mSoundPoolLooper = null;
    395     // volume applied to sound played with playSoundEffect()
    396     private static int sSoundEffectVolumeDb;
    397     // getActiveStreamType() will return:
    398     // - STREAM_NOTIFICATION on tablets during this period after a notification stopped
    399     // - STREAM_MUSIC on phones during this period after music or talkback/voice search prompt
    400     // stopped
    401     private static final int DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS = 5000;
    402     // previous volume adjustment direction received by checkForRingerModeChange()
    403     private int mPrevVolDirection = AudioManager.ADJUST_SAME;
    404     // Keyguard manager proxy
    405     private KeyguardManager mKeyguardManager;
    406     // mVolumeControlStream is set by VolumePanel to temporarily force the stream type which volume
    407     // is controlled by Vol keys.
    408     private int  mVolumeControlStream = -1;
    409     private final Object mForceControlStreamLock = new Object();
    410     // VolumePanel is currently the only client of forceVolumeControlStream() and runs in system
    411     // server process so in theory it is not necessary to monitor the client death.
    412     // However it is good to be ready for future evolutions.
    413     private ForceControlStreamClient mForceControlStreamClient = null;
    414     // Used to play ringtones outside system_server
    415     private volatile IRingtonePlayer mRingtonePlayer;
    416 
    417     private int mDeviceOrientation = Configuration.ORIENTATION_UNDEFINED;
    418     private int mDeviceRotation = Surface.ROTATION_0;
    419 
    420     // Request to override default use of A2DP for media.
    421     private boolean mBluetoothA2dpEnabled;
    422     private final Object mBluetoothA2dpEnabledLock = new Object();
    423 
    424     // Monitoring of audio routes.  Protected by mCurAudioRoutes.
    425     final AudioRoutesInfo mCurAudioRoutes = new AudioRoutesInfo();
    426     final RemoteCallbackList<IAudioRoutesObserver> mRoutesObservers
    427             = new RemoteCallbackList<IAudioRoutesObserver>();
    428 
    429     /**
    430      * A fake stream type to match the notion of remote media playback
    431      */
    432     public final static int STREAM_REMOTE_MUSIC = -200;
    433 
    434     // Devices for which the volume is fixed and VolumePanel slider should be disabled
    435     final int mFixedVolumeDevices = AudioSystem.DEVICE_OUT_AUX_DIGITAL |
    436             AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET |
    437             AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET |
    438             AudioSystem.DEVICE_OUT_ALL_USB;
    439 
    440     // TODO merge orientation and rotation
    441     private final boolean mMonitorOrientation;
    442     private final boolean mMonitorRotation;
    443 
    444     private boolean mDockAudioMediaEnabled = true;
    445 
    446     private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
    447 
    448     // Used when safe volume warning message display is requested by setStreamVolume(). In this
    449     // case, the new requested volume, stream type and device are stored in mPendingVolumeCommand
    450     // and used later when/if disableSafeMediaVolume() is called.
    451     private StreamVolumeCommand mPendingVolumeCommand;
    452 
    453     private PowerManager.WakeLock mAudioEventWakeLock;
    454 
    455     private final MediaFocusControl mMediaFocusControl;
    456 
    457     // Reference to BluetoothA2dp to query for AbsoluteVolume.
    458     private BluetoothA2dp mA2dp;
    459     private final Object mA2dpAvrcpLock = new Object();
    460     // If absolute volume is supported in AVRCP device
    461     private boolean mAvrcpAbsVolSupported = false;
    462 
    463     ///////////////////////////////////////////////////////////////////////////
    464     // Construction
    465     ///////////////////////////////////////////////////////////////////////////
    466 
    467     /** @hide */
    468     public AudioService(Context context) {
    469         mContext = context;
    470         mContentResolver = context.getContentResolver();
    471         mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
    472         mVoiceCapable = mContext.getResources().getBoolean(
    473                 com.android.internal.R.bool.config_voice_capable);
    474 
    475         PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
    476         mAudioEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "handleAudioEvent");
    477 
    478         Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
    479         mHasVibrator = vibrator == null ? false : vibrator.hasVibrator();
    480 
    481        // Intialized volume
    482         MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] = SystemProperties.getInt(
    483             "ro.config.vc_call_vol_steps",
    484            MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL]);
    485 
    486         sSoundEffectVolumeDb = context.getResources().getInteger(
    487                 com.android.internal.R.integer.config_soundEffectVolumeDb);
    488 
    489         mVolumePanel = new VolumePanel(context, this);
    490         mForcedUseForComm = AudioSystem.FORCE_NONE;
    491 
    492         createAudioSystemThread();
    493 
    494         mMediaFocusControl = new MediaFocusControl(mAudioHandler.getLooper(),
    495                 mContext, /*VolumeController*/ mVolumePanel, this);
    496 
    497         AudioSystem.setErrorCallback(mAudioSystemCallback);
    498 
    499         boolean cameraSoundForced = mContext.getResources().getBoolean(
    500                 com.android.internal.R.bool.config_camera_sound_forced);
    501         mCameraSoundForced = new Boolean(cameraSoundForced);
    502         sendMsg(mAudioHandler,
    503                 MSG_SET_FORCE_USE,
    504                 SENDMSG_QUEUE,
    505                 AudioSystem.FOR_SYSTEM,
    506                 cameraSoundForced ?
    507                         AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE,
    508                 null,
    509                 0);
    510 
    511         mSafeMediaVolumeState = new Integer(Settings.Global.getInt(mContentResolver,
    512                                                         Settings.Global.AUDIO_SAFE_VOLUME_STATE,
    513                                                         SAFE_MEDIA_VOLUME_NOT_CONFIGURED));
    514         // The default safe volume index read here will be replaced by the actual value when
    515         // the mcc is read by onConfigureSafeVolume()
    516         mSafeMediaVolumeIndex = mContext.getResources().getInteger(
    517                 com.android.internal.R.integer.config_safe_media_volume_index) * 10;
    518 
    519         mUseFixedVolume = mContext.getResources().getBoolean(
    520                 com.android.internal.R.bool.config_useFixedVolume);
    521 
    522         // must be called before readPersistedSettings() which needs a valid mStreamVolumeAlias[]
    523         // array initialized by updateStreamVolumeAlias()
    524         updateStreamVolumeAlias(false /*updateVolumes*/);
    525         readPersistedSettings();
    526         mSettingsObserver = new SettingsObserver();
    527         createStreamStates();
    528 
    529         readAndSetLowRamDevice();
    530 
    531         // Call setRingerModeInt() to apply correct mute
    532         // state on streams affected by ringer mode.
    533         mRingerModeMutedStreams = 0;
    534         setRingerModeInt(getRingerMode(), false);
    535 
    536         // Register for device connection intent broadcasts.
    537         IntentFilter intentFilter =
    538                 new IntentFilter(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
    539         intentFilter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
    540         intentFilter.addAction(Intent.ACTION_DOCK_EVENT);
    541         intentFilter.addAction(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG);
    542         intentFilter.addAction(Intent.ACTION_USB_AUDIO_DEVICE_PLUG);
    543         intentFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
    544         intentFilter.addAction(Intent.ACTION_SCREEN_ON);
    545         intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
    546         intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
    547 
    548         intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
    549         // TODO merge orientation and rotation
    550         mMonitorOrientation = SystemProperties.getBoolean("ro.audio.monitorOrientation", false);
    551         if (mMonitorOrientation) {
    552             Log.v(TAG, "monitoring device orientation");
    553             // initialize orientation in AudioSystem
    554             setOrientationForAudioSystem();
    555         }
    556         mMonitorRotation = SystemProperties.getBoolean("ro.audio.monitorRotation", false);
    557         if (mMonitorRotation) {
    558             mDeviceRotation = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE))
    559                     .getDefaultDisplay().getRotation();
    560             Log.v(TAG, "monitoring device rotation, initial=" + mDeviceRotation);
    561             // initialize rotation in AudioSystem
    562             setRotationForAudioSystem();
    563         }
    564 
    565         context.registerReceiver(mReceiver, intentFilter);
    566 
    567         mUseMasterVolume = context.getResources().getBoolean(
    568                 com.android.internal.R.bool.config_useMasterVolume);
    569         restoreMasterVolume();
    570 
    571         mMasterVolumeRamp = context.getResources().getIntArray(
    572                 com.android.internal.R.array.config_masterVolumeRamp);
    573 
    574     }
    575 
    576     private void createAudioSystemThread() {
    577         mAudioSystemThread = new AudioSystemThread();
    578         mAudioSystemThread.start();
    579         waitForAudioHandlerCreation();
    580     }
    581 
    582     /** Waits for the volume handler to be created by the other thread. */
    583     private void waitForAudioHandlerCreation() {
    584         synchronized(this) {
    585             while (mAudioHandler == null) {
    586                 try {
    587                     // Wait for mAudioHandler to be set by the other thread
    588                     wait();
    589                 } catch (InterruptedException e) {
    590                     Log.e(TAG, "Interrupted while waiting on volume handler.");
    591                 }
    592             }
    593         }
    594     }
    595 
    596     private void checkAllAliasStreamVolumes() {
    597         int numStreamTypes = AudioSystem.getNumStreamTypes();
    598         for (int streamType = 0; streamType < numStreamTypes; streamType++) {
    599             if (streamType != mStreamVolumeAlias[streamType]) {
    600                 mStreamStates[streamType].
    601                                     setAllIndexes(mStreamStates[mStreamVolumeAlias[streamType]]);
    602             }
    603             // apply stream volume
    604             if (!mStreamStates[streamType].isMuted()) {
    605                 mStreamStates[streamType].applyAllVolumes();
    606             }
    607         }
    608     }
    609 
    610     private void createStreamStates() {
    611         int numStreamTypes = AudioSystem.getNumStreamTypes();
    612         VolumeStreamState[] streams = mStreamStates = new VolumeStreamState[numStreamTypes];
    613 
    614         for (int i = 0; i < numStreamTypes; i++) {
    615             streams[i] = new VolumeStreamState(System.VOLUME_SETTINGS[mStreamVolumeAlias[i]], i);
    616         }
    617 
    618         checkAllAliasStreamVolumes();
    619     }
    620 
    621     private void dumpStreamStates(PrintWriter pw) {
    622         pw.println("\nStream volumes (device: index)");
    623         int numStreamTypes = AudioSystem.getNumStreamTypes();
    624         for (int i = 0; i < numStreamTypes; i++) {
    625             pw.println("- "+STREAM_NAMES[i]+":");
    626             mStreamStates[i].dump(pw);
    627             pw.println("");
    628         }
    629         pw.print("\n- mute affected streams = 0x");
    630         pw.println(Integer.toHexString(mMuteAffectedStreams));
    631     }
    632 
    633 
    634     private void updateStreamVolumeAlias(boolean updateVolumes) {
    635         int dtmfStreamAlias;
    636         if (mVoiceCapable) {
    637             mStreamVolumeAlias = STREAM_VOLUME_ALIAS;
    638             dtmfStreamAlias = AudioSystem.STREAM_RING;
    639         } else {
    640             mStreamVolumeAlias = STREAM_VOLUME_ALIAS_NON_VOICE;
    641             dtmfStreamAlias = AudioSystem.STREAM_MUSIC;
    642         }
    643         if (isInCommunication()) {
    644             dtmfStreamAlias = AudioSystem.STREAM_VOICE_CALL;
    645             mRingerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_DTMF);
    646         } else {
    647             mRingerModeAffectedStreams |= (1 << AudioSystem.STREAM_DTMF);
    648         }
    649         mStreamVolumeAlias[AudioSystem.STREAM_DTMF] = dtmfStreamAlias;
    650         if (updateVolumes) {
    651             mStreamStates[AudioSystem.STREAM_DTMF].setAllIndexes(mStreamStates[dtmfStreamAlias]);
    652             // apply stream mute states according to new value of mRingerModeAffectedStreams
    653             setRingerModeInt(getRingerMode(), false);
    654             sendMsg(mAudioHandler,
    655                     MSG_SET_ALL_VOLUMES,
    656                     SENDMSG_QUEUE,
    657                     0,
    658                     0,
    659                     mStreamStates[AudioSystem.STREAM_DTMF], 0);
    660         }
    661     }
    662 
    663     private void readDockAudioSettings(ContentResolver cr)
    664     {
    665         mDockAudioMediaEnabled = Settings.Global.getInt(
    666                                         cr, Settings.Global.DOCK_AUDIO_MEDIA_ENABLED, 0) == 1;
    667 
    668         if (mDockAudioMediaEnabled) {
    669             mBecomingNoisyIntentDevices |= AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET;
    670         } else {
    671             mBecomingNoisyIntentDevices &= ~AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET;
    672         }
    673 
    674         sendMsg(mAudioHandler,
    675                 MSG_SET_FORCE_USE,
    676                 SENDMSG_QUEUE,
    677                 AudioSystem.FOR_DOCK,
    678                 mDockAudioMediaEnabled ?
    679                         AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE,
    680                 null,
    681                 0);
    682     }
    683 
    684     private void readPersistedSettings() {
    685         final ContentResolver cr = mContentResolver;
    686 
    687         int ringerModeFromSettings =
    688                 Settings.Global.getInt(
    689                         cr, Settings.Global.MODE_RINGER, AudioManager.RINGER_MODE_NORMAL);
    690         int ringerMode = ringerModeFromSettings;
    691         // sanity check in case the settings are restored from a device with incompatible
    692         // ringer modes
    693         if (!AudioManager.isValidRingerMode(ringerMode)) {
    694             ringerMode = AudioManager.RINGER_MODE_NORMAL;
    695         }
    696         if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) {
    697             ringerMode = AudioManager.RINGER_MODE_SILENT;
    698         }
    699         if (ringerMode != ringerModeFromSettings) {
    700             Settings.Global.putInt(cr, Settings.Global.MODE_RINGER, ringerMode);
    701         }
    702         if (mUseFixedVolume) {
    703             ringerMode = AudioManager.RINGER_MODE_NORMAL;
    704         }
    705         synchronized(mSettingsLock) {
    706             mRingerMode = ringerMode;
    707 
    708             // System.VIBRATE_ON is not used any more but defaults for mVibrateSetting
    709             // are still needed while setVibrateSetting() and getVibrateSetting() are being
    710             // deprecated.
    711             mVibrateSetting = getValueForVibrateSetting(0,
    712                                             AudioManager.VIBRATE_TYPE_NOTIFICATION,
    713                                             mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT
    714                                                             : AudioManager.VIBRATE_SETTING_OFF);
    715             mVibrateSetting = getValueForVibrateSetting(mVibrateSetting,
    716                                             AudioManager.VIBRATE_TYPE_RINGER,
    717                                             mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT
    718                                                             : AudioManager.VIBRATE_SETTING_OFF);
    719 
    720             updateRingerModeAffectedStreams();
    721             readDockAudioSettings(cr);
    722         }
    723 
    724         mMuteAffectedStreams = System.getIntForUser(cr,
    725                 System.MUTE_STREAMS_AFFECTED,
    726                 ((1 << AudioSystem.STREAM_MUSIC)|
    727                  (1 << AudioSystem.STREAM_RING)|
    728                  (1 << AudioSystem.STREAM_SYSTEM)),
    729                  UserHandle.USER_CURRENT);
    730 
    731         boolean masterMute = System.getIntForUser(cr, System.VOLUME_MASTER_MUTE,
    732                                                   0, UserHandle.USER_CURRENT) == 1;
    733         if (mUseFixedVolume) {
    734             masterMute = false;
    735             AudioSystem.setMasterVolume(1.0f);
    736         }
    737         AudioSystem.setMasterMute(masterMute);
    738         broadcastMasterMuteStatus(masterMute);
    739 
    740         // Each stream will read its own persisted settings
    741 
    742         // Broadcast the sticky intent
    743         broadcastRingerMode(ringerMode);
    744 
    745         // Broadcast vibrate settings
    746         broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER);
    747         broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION);
    748 
    749         // Restore the default media button receiver from the system settings
    750         mMediaFocusControl.restoreMediaButtonReceiver();
    751     }
    752 
    753     private int rescaleIndex(int index, int srcStream, int dstStream) {
    754         return (index * mStreamStates[dstStream].getMaxIndex() + mStreamStates[srcStream].getMaxIndex() / 2) / mStreamStates[srcStream].getMaxIndex();
    755     }
    756 
    757     ///////////////////////////////////////////////////////////////////////////
    758     // IPC methods
    759     ///////////////////////////////////////////////////////////////////////////
    760     /** @see AudioManager#isLocalOrRemoteMusicActive() */
    761     public boolean isLocalOrRemoteMusicActive() {
    762         if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0)) {
    763             // local / wired / BT playback active
    764             if (DEBUG_VOL) Log.d(TAG, "isLocalOrRemoteMusicActive(): local");
    765             return true;
    766         }
    767         if (mMediaFocusControl.checkUpdateRemoteStateIfActive(AudioSystem.STREAM_MUSIC)) {
    768             // remote "cast-like" playback active
    769             if (DEBUG_VOL) Log.d(TAG, "isLocalOrRemoteMusicActive(): has PLAYBACK_TYPE_REMOTE");
    770             return true;
    771         }
    772         if (AudioSystem.isStreamActiveRemotely(AudioSystem.STREAM_MUSIC, 0)) {
    773             // remote submix playback active
    774             if (DEBUG_VOL) Log.d(TAG, "isLocalOrRemoteMusicActive(): remote submix");
    775             return true;
    776         }
    777         if (DEBUG_VOL) Log.d(TAG, "isLocalOrRemoteMusicActive(): no");
    778         return false;
    779     }
    780 
    781     /** @see AudioManager#adjustVolume(int, int) */
    782     public void adjustVolume(int direction, int flags, String callingPackage) {
    783         adjustSuggestedStreamVolume(direction, AudioManager.USE_DEFAULT_STREAM_TYPE, flags,
    784                 callingPackage);
    785     }
    786 
    787     /** @see AudioManager#adjustLocalOrRemoteStreamVolume(int, int) with current assumption
    788      *  on streamType: fixed to STREAM_MUSIC */
    789     public void adjustLocalOrRemoteStreamVolume(int streamType, int direction,
    790             String callingPackage) {
    791         if (DEBUG_VOL) Log.d(TAG, "adjustLocalOrRemoteStreamVolume(dir="+direction+")");
    792         if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0)) {
    793             adjustStreamVolume(AudioSystem.STREAM_MUSIC, direction, 0, callingPackage);
    794         } else if (mMediaFocusControl.checkUpdateRemoteStateIfActive(AudioSystem.STREAM_MUSIC)) {
    795             mMediaFocusControl.adjustRemoteVolume(AudioSystem.STREAM_MUSIC, direction, 0);
    796         }
    797     }
    798 
    799     /** @see AudioManager#adjustVolume(int, int) */
    800     public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
    801             String callingPackage) {
    802         if (DEBUG_VOL) Log.d(TAG, "adjustSuggestedStreamVolume() stream="+suggestedStreamType);
    803         int streamType;
    804         if (mVolumeControlStream != -1) {
    805             streamType = mVolumeControlStream;
    806         } else {
    807             streamType = getActiveStreamType(suggestedStreamType);
    808         }
    809 
    810         // Play sounds on STREAM_RING only and if lock screen is not on.
    811         if ((streamType != STREAM_REMOTE_MUSIC) &&
    812                 (flags & AudioManager.FLAG_PLAY_SOUND) != 0 &&
    813                 ((mStreamVolumeAlias[streamType] != AudioSystem.STREAM_RING)
    814                  || (mKeyguardManager != null && mKeyguardManager.isKeyguardLocked()))) {
    815             flags &= ~AudioManager.FLAG_PLAY_SOUND;
    816         }
    817 
    818         if (streamType == STREAM_REMOTE_MUSIC) {
    819             // don't play sounds for remote
    820             flags &= ~(AudioManager.FLAG_PLAY_SOUND|AudioManager.FLAG_FIXED_VOLUME);
    821             //if (DEBUG_VOL) Log.i(TAG, "Need to adjust remote volume: calling adjustRemoteVolume()");
    822             mMediaFocusControl.adjustRemoteVolume(AudioSystem.STREAM_MUSIC, direction, flags);
    823         } else {
    824             adjustStreamVolume(streamType, direction, flags, callingPackage);
    825         }
    826     }
    827 
    828     /** @see AudioManager#adjustStreamVolume(int, int, int) */
    829     public void adjustStreamVolume(int streamType, int direction, int flags,
    830             String callingPackage) {
    831         if (mUseFixedVolume) {
    832             return;
    833         }
    834         if (DEBUG_VOL) Log.d(TAG, "adjustStreamVolume() stream="+streamType+", dir="+direction);
    835 
    836         ensureValidDirection(direction);
    837         ensureValidStreamType(streamType);
    838 
    839         // use stream type alias here so that streams with same alias have the same behavior,
    840         // including with regard to silent mode control (e.g the use of STREAM_RING below and in
    841         // checkForRingerModeChange() in place of STREAM_RING or STREAM_NOTIFICATION)
    842         int streamTypeAlias = mStreamVolumeAlias[streamType];
    843         VolumeStreamState streamState = mStreamStates[streamTypeAlias];
    844 
    845         final int device = getDeviceForStream(streamTypeAlias);
    846 
    847         int aliasIndex = streamState.getIndex(device);
    848         boolean adjustVolume = true;
    849         int step;
    850 
    851         // skip a2dp absolute volume control request when the device
    852         // is not an a2dp device
    853         if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 &&
    854             (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
    855             return;
    856         }
    857 
    858         if (mAppOps.noteOp(STEAM_VOLUME_OPS[streamTypeAlias], Binder.getCallingUid(),
    859                 callingPackage) != AppOpsManager.MODE_ALLOWED) {
    860             return;
    861         }
    862 
    863         // reset any pending volume command
    864         synchronized (mSafeMediaVolumeState) {
    865             mPendingVolumeCommand = null;
    866         }
    867 
    868         flags &= ~AudioManager.FLAG_FIXED_VOLUME;
    869         if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
    870                ((device & mFixedVolumeDevices) != 0)) {
    871             flags |= AudioManager.FLAG_FIXED_VOLUME;
    872 
    873             // Always toggle between max safe volume and 0 for fixed volume devices where safe
    874             // volume is enforced, and max and 0 for the others.
    875             // This is simulated by stepping by the full allowed volume range
    876             if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE &&
    877                     (device & mSafeMediaVolumeDevices) != 0) {
    878                 step = mSafeMediaVolumeIndex;
    879             } else {
    880                 step = streamState.getMaxIndex();
    881             }
    882             if (aliasIndex != 0) {
    883                 aliasIndex = step;
    884             }
    885         } else {
    886             // convert one UI step (+/-1) into a number of internal units on the stream alias
    887             step = rescaleIndex(10, streamType, streamTypeAlias);
    888         }
    889 
    890         // If either the client forces allowing ringer modes for this adjustment,
    891         // or the stream type is one that is affected by ringer modes
    892         if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
    893                 (streamTypeAlias == getMasterStreamType())) {
    894             int ringerMode = getRingerMode();
    895             // do not vibrate if already in vibrate mode
    896             if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
    897                 flags &= ~AudioManager.FLAG_VIBRATE;
    898             }
    899             // Check if the ringer mode changes with this volume adjustment. If
    900             // it does, it will handle adjusting the volume, so we won't below
    901             adjustVolume = checkForRingerModeChange(aliasIndex, direction, step);
    902         }
    903 
    904         int oldIndex = mStreamStates[streamType].getIndex(device);
    905 
    906         if (adjustVolume && (direction != AudioManager.ADJUST_SAME)) {
    907 
    908             // Check if volume update should be send to AVRCP
    909             if (streamTypeAlias == AudioSystem.STREAM_MUSIC &&
    910                 (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
    911                 (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
    912                 synchronized (mA2dpAvrcpLock) {
    913                     if (mA2dp != null && mAvrcpAbsVolSupported) {
    914                         mA2dp.adjustAvrcpAbsoluteVolume(direction);
    915                     }
    916                 }
    917             }
    918 
    919             if ((direction == AudioManager.ADJUST_RAISE) &&
    920                     !checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) {
    921                 Log.e(TAG, "adjustStreamVolume() safe volume index = "+oldIndex);
    922                 mVolumePanel.postDisplaySafeVolumeWarning(flags);
    923             } else if (streamState.adjustIndex(direction * step, device)) {
    924                 // Post message to set system volume (it in turn will post a message
    925                 // to persist). Do not change volume if stream is muted.
    926                 sendMsg(mAudioHandler,
    927                         MSG_SET_DEVICE_VOLUME,
    928                         SENDMSG_QUEUE,
    929                         device,
    930                         0,
    931                         streamState,
    932                         0);
    933             }
    934         }
    935         int index = mStreamStates[streamType].getIndex(device);
    936         sendVolumeUpdate(streamType, oldIndex, index, flags);
    937     }
    938 
    939     /** @see AudioManager#adjustMasterVolume(int, int) */
    940     public void adjustMasterVolume(int steps, int flags, String callingPackage) {
    941         if (mUseFixedVolume) {
    942             return;
    943         }
    944         ensureValidSteps(steps);
    945         int volume = Math.round(AudioSystem.getMasterVolume() * MAX_MASTER_VOLUME);
    946         int delta = 0;
    947         int numSteps = Math.abs(steps);
    948         int direction = steps > 0 ? AudioManager.ADJUST_RAISE : AudioManager.ADJUST_LOWER;
    949         for (int i = 0; i < numSteps; ++i) {
    950             delta = findVolumeDelta(direction, volume);
    951             volume += delta;
    952         }
    953 
    954         //Log.d(TAG, "adjustMasterVolume volume: " + volume + " steps: " + steps);
    955         setMasterVolume(volume, flags, callingPackage);
    956     }
    957 
    958     // StreamVolumeCommand contains the information needed to defer the process of
    959     // setStreamVolume() in case the user has to acknowledge the safe volume warning message.
    960     class StreamVolumeCommand {
    961         public final int mStreamType;
    962         public final int mIndex;
    963         public final int mFlags;
    964         public final int mDevice;
    965 
    966         StreamVolumeCommand(int streamType, int index, int flags, int device) {
    967             mStreamType = streamType;
    968             mIndex = index;
    969             mFlags = flags;
    970             mDevice = device;
    971         }
    972     };
    973 
    974     private void onSetStreamVolume(int streamType, int index, int flags, int device) {
    975         setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, false);
    976         // setting volume on master stream type also controls silent mode
    977         if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
    978                 (mStreamVolumeAlias[streamType] == getMasterStreamType())) {
    979             int newRingerMode;
    980             if (index == 0) {
    981                 newRingerMode = mHasVibrator ? AudioManager.RINGER_MODE_VIBRATE
    982                                               : AudioManager.RINGER_MODE_SILENT;
    983             } else {
    984                 newRingerMode = AudioManager.RINGER_MODE_NORMAL;
    985             }
    986             setRingerMode(newRingerMode);
    987         }
    988     }
    989 
    990     /** @see AudioManager#setStreamVolume(int, int, int) */
    991     public void setStreamVolume(int streamType, int index, int flags, String callingPackage) {
    992         if (mUseFixedVolume) {
    993             return;
    994         }
    995 
    996         ensureValidStreamType(streamType);
    997         int streamTypeAlias = mStreamVolumeAlias[streamType];
    998         VolumeStreamState streamState = mStreamStates[streamTypeAlias];
    999 
   1000         final int device = getDeviceForStream(streamType);
   1001         int oldIndex;
   1002 
   1003         // skip a2dp absolute volume control request when the device
   1004         // is not an a2dp device
   1005         if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 &&
   1006             (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
   1007             return;
   1008         }
   1009 
   1010         if (mAppOps.noteOp(STEAM_VOLUME_OPS[streamTypeAlias], Binder.getCallingUid(),
   1011                 callingPackage) != AppOpsManager.MODE_ALLOWED) {
   1012             return;
   1013         }
   1014 
   1015         synchronized (mSafeMediaVolumeState) {
   1016             // reset any pending volume command
   1017             mPendingVolumeCommand = null;
   1018 
   1019             oldIndex = streamState.getIndex(device);
   1020 
   1021             index = rescaleIndex(index * 10, streamType, streamTypeAlias);
   1022 
   1023             if (streamTypeAlias == AudioSystem.STREAM_MUSIC &&
   1024                 (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
   1025                 (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
   1026                 synchronized (mA2dpAvrcpLock) {
   1027                     if (mA2dp != null && mAvrcpAbsVolSupported) {
   1028                         mA2dp.setAvrcpAbsoluteVolume(index / 10);
   1029                     }
   1030                 }
   1031             }
   1032 
   1033             flags &= ~AudioManager.FLAG_FIXED_VOLUME;
   1034             if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
   1035                     ((device & mFixedVolumeDevices) != 0)) {
   1036                 flags |= AudioManager.FLAG_FIXED_VOLUME;
   1037 
   1038                 // volume is either 0 or max allowed for fixed volume devices
   1039                 if (index != 0) {
   1040                     if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE &&
   1041                             (device & mSafeMediaVolumeDevices) != 0) {
   1042                         index = mSafeMediaVolumeIndex;
   1043                     } else {
   1044                         index = streamState.getMaxIndex();
   1045                     }
   1046                 }
   1047             }
   1048 
   1049             if (!checkSafeMediaVolume(streamTypeAlias, index, device)) {
   1050                 mVolumePanel.postDisplaySafeVolumeWarning(flags);
   1051                 mPendingVolumeCommand = new StreamVolumeCommand(
   1052                                                     streamType, index, flags, device);
   1053             } else {
   1054                 onSetStreamVolume(streamType, index, flags, device);
   1055                 index = mStreamStates[streamType].getIndex(device);
   1056             }
   1057         }
   1058         sendVolumeUpdate(streamType, oldIndex, index, flags);
   1059     }
   1060 
   1061     /** @see AudioManager#forceVolumeControlStream(int) */
   1062     public void forceVolumeControlStream(int streamType, IBinder cb) {
   1063         synchronized(mForceControlStreamLock) {
   1064             mVolumeControlStream = streamType;
   1065             if (mVolumeControlStream == -1) {
   1066                 if (mForceControlStreamClient != null) {
   1067                     mForceControlStreamClient.release();
   1068                     mForceControlStreamClient = null;
   1069                 }
   1070             } else {
   1071                 mForceControlStreamClient = new ForceControlStreamClient(cb);
   1072             }
   1073         }
   1074     }
   1075 
   1076     private class ForceControlStreamClient implements IBinder.DeathRecipient {
   1077         private IBinder mCb; // To be notified of client's death
   1078 
   1079         ForceControlStreamClient(IBinder cb) {
   1080             if (cb != null) {
   1081                 try {
   1082                     cb.linkToDeath(this, 0);
   1083                 } catch (RemoteException e) {
   1084                     // Client has died!
   1085                     Log.w(TAG, "ForceControlStreamClient() could not link to "+cb+" binder death");
   1086                     cb = null;
   1087                 }
   1088             }
   1089             mCb = cb;
   1090         }
   1091 
   1092         public void binderDied() {
   1093             synchronized(mForceControlStreamLock) {
   1094                 Log.w(TAG, "SCO client died");
   1095                 if (mForceControlStreamClient != this) {
   1096                     Log.w(TAG, "unregistered control stream client died");
   1097                 } else {
   1098                     mForceControlStreamClient = null;
   1099                     mVolumeControlStream = -1;
   1100                 }
   1101             }
   1102         }
   1103 
   1104         public void release() {
   1105             if (mCb != null) {
   1106                 mCb.unlinkToDeath(this, 0);
   1107                 mCb = null;
   1108             }
   1109         }
   1110     }
   1111 
   1112     private int findVolumeDelta(int direction, int volume) {
   1113         int delta = 0;
   1114         if (direction == AudioManager.ADJUST_RAISE) {
   1115             if (volume == MAX_MASTER_VOLUME) {
   1116                 return 0;
   1117             }
   1118             // This is the default value if we make it to the end
   1119             delta = mMasterVolumeRamp[1];
   1120             // If we're raising the volume move down the ramp array until we
   1121             // find the volume we're above and use that groups delta.
   1122             for (int i = mMasterVolumeRamp.length - 1; i > 1; i -= 2) {
   1123                 if (volume >= mMasterVolumeRamp[i - 1]) {
   1124                     delta = mMasterVolumeRamp[i];
   1125                     break;
   1126                 }
   1127             }
   1128         } else if (direction == AudioManager.ADJUST_LOWER){
   1129             if (volume == 0) {
   1130                 return 0;
   1131             }
   1132             int length = mMasterVolumeRamp.length;
   1133             // This is the default value if we make it to the end
   1134             delta = -mMasterVolumeRamp[length - 1];
   1135             // If we're lowering the volume move up the ramp array until we
   1136             // find the volume we're below and use the group below it's delta
   1137             for (int i = 2; i < length; i += 2) {
   1138                 if (volume <= mMasterVolumeRamp[i]) {
   1139                     delta = -mMasterVolumeRamp[i - 1];
   1140                     break;
   1141                 }
   1142             }
   1143         }
   1144         return delta;
   1145     }
   1146 
   1147     private void sendBroadcastToAll(Intent intent) {
   1148         final long ident = Binder.clearCallingIdentity();
   1149         try {
   1150             mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
   1151         } finally {
   1152             Binder.restoreCallingIdentity(ident);
   1153         }
   1154     }
   1155 
   1156     private void sendStickyBroadcastToAll(Intent intent) {
   1157         final long ident = Binder.clearCallingIdentity();
   1158         try {
   1159             mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
   1160         } finally {
   1161             Binder.restoreCallingIdentity(ident);
   1162         }
   1163     }
   1164 
   1165     // UI update and Broadcast Intent
   1166     private void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags) {
   1167         if (!mVoiceCapable && (streamType == AudioSystem.STREAM_RING)) {
   1168             streamType = AudioSystem.STREAM_NOTIFICATION;
   1169         }
   1170 
   1171         mVolumePanel.postVolumeChanged(streamType, flags);
   1172 
   1173         if ((flags & AudioManager.FLAG_FIXED_VOLUME) == 0) {
   1174             oldIndex = (oldIndex + 5) / 10;
   1175             index = (index + 5) / 10;
   1176             Intent intent = new Intent(AudioManager.VOLUME_CHANGED_ACTION);
   1177             intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, streamType);
   1178             intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, index);
   1179             intent.putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, oldIndex);
   1180             sendBroadcastToAll(intent);
   1181         }
   1182     }
   1183 
   1184     // UI update and Broadcast Intent
   1185     private void sendMasterVolumeUpdate(int flags, int oldVolume, int newVolume) {
   1186         mVolumePanel.postMasterVolumeChanged(flags);
   1187 
   1188         Intent intent = new Intent(AudioManager.MASTER_VOLUME_CHANGED_ACTION);
   1189         intent.putExtra(AudioManager.EXTRA_PREV_MASTER_VOLUME_VALUE, oldVolume);
   1190         intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_VALUE, newVolume);
   1191         sendBroadcastToAll(intent);
   1192     }
   1193 
   1194     // UI update and Broadcast Intent
   1195     private void sendMasterMuteUpdate(boolean muted, int flags) {
   1196         mVolumePanel.postMasterMuteChanged(flags);
   1197         broadcastMasterMuteStatus(muted);
   1198     }
   1199 
   1200     private void broadcastMasterMuteStatus(boolean muted) {
   1201         Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION);
   1202         intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, muted);
   1203         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
   1204                 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
   1205         sendStickyBroadcastToAll(intent);
   1206     }
   1207 
   1208     /**
   1209      * Sets the stream state's index, and posts a message to set system volume.
   1210      * This will not call out to the UI. Assumes a valid stream type.
   1211      *
   1212      * @param streamType Type of the stream
   1213      * @param index Desired volume index of the stream
   1214      * @param device the device whose volume must be changed
   1215      * @param force If true, set the volume even if the desired volume is same
   1216      * as the current volume.
   1217      */
   1218     private void setStreamVolumeInt(int streamType,
   1219                                     int index,
   1220                                     int device,
   1221                                     boolean force) {
   1222         VolumeStreamState streamState = mStreamStates[streamType];
   1223 
   1224         if (streamState.setIndex(index, device) || force) {
   1225             // Post message to set system volume (it in turn will post a message
   1226             // to persist).
   1227             sendMsg(mAudioHandler,
   1228                     MSG_SET_DEVICE_VOLUME,
   1229                     SENDMSG_QUEUE,
   1230                     device,
   1231                     0,
   1232                     streamState,
   1233                     0);
   1234         }
   1235     }
   1236 
   1237     /** @see AudioManager#setStreamSolo(int, boolean) */
   1238     public void setStreamSolo(int streamType, boolean state, IBinder cb) {
   1239         if (mUseFixedVolume) {
   1240             return;
   1241         }
   1242 
   1243         for (int stream = 0; stream < mStreamStates.length; stream++) {
   1244             if (!isStreamAffectedByMute(stream) || stream == streamType) continue;
   1245             mStreamStates[stream].mute(cb, state);
   1246          }
   1247     }
   1248 
   1249     /** @see AudioManager#setStreamMute(int, boolean) */
   1250     public void setStreamMute(int streamType, boolean state, IBinder cb) {
   1251         if (mUseFixedVolume) {
   1252             return;
   1253         }
   1254 
   1255         if (isStreamAffectedByMute(streamType)) {
   1256             mStreamStates[streamType].mute(cb, state);
   1257         }
   1258     }
   1259 
   1260     /** get stream mute state. */
   1261     public boolean isStreamMute(int streamType) {
   1262         return mStreamStates[streamType].isMuted();
   1263     }
   1264 
   1265     /** @see AudioManager#setMasterMute(boolean, int) */
   1266     public void setMasterMute(boolean state, int flags, IBinder cb) {
   1267         if (mUseFixedVolume) {
   1268             return;
   1269         }
   1270 
   1271         if (state != AudioSystem.getMasterMute()) {
   1272             AudioSystem.setMasterMute(state);
   1273             // Post a persist master volume msg
   1274             sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME_MUTE, SENDMSG_REPLACE, state ? 1
   1275                     : 0, 0, null, PERSIST_DELAY);
   1276             sendMasterMuteUpdate(state, flags);
   1277         }
   1278     }
   1279 
   1280     /** get master mute state. */
   1281     public boolean isMasterMute() {
   1282         return AudioSystem.getMasterMute();
   1283     }
   1284 
   1285     protected static int getMaxStreamVolume(int streamType) {
   1286         return MAX_STREAM_VOLUME[streamType];
   1287     }
   1288 
   1289     /** @see AudioManager#getStreamVolume(int) */
   1290     public int getStreamVolume(int streamType) {
   1291         ensureValidStreamType(streamType);
   1292         int device = getDeviceForStream(streamType);
   1293         int index = mStreamStates[streamType].getIndex(device);
   1294 
   1295         // by convention getStreamVolume() returns 0 when a stream is muted.
   1296         if (mStreamStates[streamType].isMuted()) {
   1297             index = 0;
   1298         }
   1299         if (index != 0 && (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
   1300                 (device & mFixedVolumeDevices) != 0) {
   1301             index = mStreamStates[streamType].getMaxIndex();
   1302         }
   1303         return (index + 5) / 10;
   1304     }
   1305 
   1306     public int getMasterVolume() {
   1307         if (isMasterMute()) return 0;
   1308         return getLastAudibleMasterVolume();
   1309     }
   1310 
   1311     public void setMasterVolume(int volume, int flags, String callingPackage) {
   1312         if (mUseFixedVolume) {
   1313             return;
   1314         }
   1315 
   1316         if (mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, Binder.getCallingUid(),
   1317                 callingPackage) != AppOpsManager.MODE_ALLOWED) {
   1318             return;
   1319         }
   1320 
   1321         if (volume < 0) {
   1322             volume = 0;
   1323         } else if (volume > MAX_MASTER_VOLUME) {
   1324             volume = MAX_MASTER_VOLUME;
   1325         }
   1326         doSetMasterVolume((float)volume / MAX_MASTER_VOLUME, flags);
   1327     }
   1328 
   1329     private void doSetMasterVolume(float volume, int flags) {
   1330         // don't allow changing master volume when muted
   1331         if (!AudioSystem.getMasterMute()) {
   1332             int oldVolume = getMasterVolume();
   1333             AudioSystem.setMasterVolume(volume);
   1334 
   1335             int newVolume = getMasterVolume();
   1336             if (newVolume != oldVolume) {
   1337                 // Post a persist master volume msg
   1338                 sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME, SENDMSG_REPLACE,
   1339                         Math.round(volume * (float)1000.0), 0, null, PERSIST_DELAY);
   1340             }
   1341             // Send the volume update regardless whether there was a change.
   1342             sendMasterVolumeUpdate(flags, oldVolume, newVolume);
   1343         }
   1344     }
   1345 
   1346     /** @see AudioManager#getStreamMaxVolume(int) */
   1347     public int getStreamMaxVolume(int streamType) {
   1348         ensureValidStreamType(streamType);
   1349         return (mStreamStates[streamType].getMaxIndex() + 5) / 10;
   1350     }
   1351 
   1352     public int getMasterMaxVolume() {
   1353         return MAX_MASTER_VOLUME;
   1354     }
   1355 
   1356     /** Get last audible volume before stream was muted. */
   1357     public int getLastAudibleStreamVolume(int streamType) {
   1358         ensureValidStreamType(streamType);
   1359         int device = getDeviceForStream(streamType);
   1360         return (mStreamStates[streamType].getIndex(device) + 5) / 10;
   1361     }
   1362 
   1363     /** Get last audible master volume before it was muted. */
   1364     public int getLastAudibleMasterVolume() {
   1365         return Math.round(AudioSystem.getMasterVolume() * MAX_MASTER_VOLUME);
   1366     }
   1367 
   1368     /** @see AudioManager#getMasterStreamType()  */
   1369     public int getMasterStreamType() {
   1370         if (mVoiceCapable) {
   1371             return AudioSystem.STREAM_RING;
   1372         } else {
   1373             return AudioSystem.STREAM_MUSIC;
   1374         }
   1375     }
   1376 
   1377     /** @see AudioManager#getRingerMode() */
   1378     public int getRingerMode() {
   1379         synchronized(mSettingsLock) {
   1380             return mRingerMode;
   1381         }
   1382     }
   1383 
   1384     private void ensureValidRingerMode(int ringerMode) {
   1385         if (!AudioManager.isValidRingerMode(ringerMode)) {
   1386             throw new IllegalArgumentException("Bad ringer mode " + ringerMode);
   1387         }
   1388     }
   1389 
   1390     /** @see AudioManager#setRingerMode(int) */
   1391     public void setRingerMode(int ringerMode) {
   1392         if (mUseFixedVolume) {
   1393             return;
   1394         }
   1395 
   1396         if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) {
   1397             ringerMode = AudioManager.RINGER_MODE_SILENT;
   1398         }
   1399         if (ringerMode != getRingerMode()) {
   1400             setRingerModeInt(ringerMode, true);
   1401             // Send sticky broadcast
   1402             broadcastRingerMode(ringerMode);
   1403         }
   1404     }
   1405 
   1406     private void setRingerModeInt(int ringerMode, boolean persist) {
   1407         synchronized(mSettingsLock) {
   1408             mRingerMode = ringerMode;
   1409         }
   1410 
   1411         // Mute stream if not previously muted by ringer mode and ringer mode
   1412         // is not RINGER_MODE_NORMAL and stream is affected by ringer mode.
   1413         // Unmute stream if previously muted by ringer mode and ringer mode
   1414         // is RINGER_MODE_NORMAL or stream is not affected by ringer mode.
   1415         int numStreamTypes = AudioSystem.getNumStreamTypes();
   1416         for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
   1417             if (isStreamMutedByRingerMode(streamType)) {
   1418                 if (!isStreamAffectedByRingerMode(streamType) ||
   1419                     ringerMode == AudioManager.RINGER_MODE_NORMAL) {
   1420                     // ring and notifications volume should never be 0 when not silenced
   1421                     // on voice capable devices
   1422                     if (mVoiceCapable &&
   1423                             mStreamVolumeAlias[streamType] == AudioSystem.STREAM_RING) {
   1424                         synchronized (mStreamStates[streamType]) {
   1425                             Set set = mStreamStates[streamType].mIndex.entrySet();
   1426                             Iterator i = set.iterator();
   1427                             while (i.hasNext()) {
   1428                                 Map.Entry entry = (Map.Entry)i.next();
   1429                                 if ((Integer)entry.getValue() == 0) {
   1430                                     entry.setValue(10);
   1431                                 }
   1432                             }
   1433                         }
   1434                     }
   1435                     mStreamStates[streamType].mute(null, false);
   1436                     mRingerModeMutedStreams &= ~(1 << streamType);
   1437                 }
   1438             } else {
   1439                 if (isStreamAffectedByRingerMode(streamType) &&
   1440                     ringerMode != AudioManager.RINGER_MODE_NORMAL) {
   1441                    mStreamStates[streamType].mute(null, true);
   1442                    mRingerModeMutedStreams |= (1 << streamType);
   1443                }
   1444             }
   1445         }
   1446 
   1447         // Post a persist ringer mode msg
   1448         if (persist) {
   1449             sendMsg(mAudioHandler, MSG_PERSIST_RINGER_MODE,
   1450                     SENDMSG_REPLACE, 0, 0, null, PERSIST_DELAY);
   1451         }
   1452     }
   1453 
   1454     private void restoreMasterVolume() {
   1455         if (mUseFixedVolume) {
   1456             AudioSystem.setMasterVolume(1.0f);
   1457             return;
   1458         }
   1459         if (mUseMasterVolume) {
   1460             float volume = Settings.System.getFloatForUser(mContentResolver,
   1461                     Settings.System.VOLUME_MASTER, -1.0f, UserHandle.USER_CURRENT);
   1462             if (volume >= 0.0f) {
   1463                 AudioSystem.setMasterVolume(volume);
   1464             }
   1465         }
   1466     }
   1467 
   1468     /** @see AudioManager#shouldVibrate(int) */
   1469     public boolean shouldVibrate(int vibrateType) {
   1470         if (!mHasVibrator) return false;
   1471 
   1472         switch (getVibrateSetting(vibrateType)) {
   1473 
   1474             case AudioManager.VIBRATE_SETTING_ON:
   1475                 return getRingerMode() != AudioManager.RINGER_MODE_SILENT;
   1476 
   1477             case AudioManager.VIBRATE_SETTING_ONLY_SILENT:
   1478                 return getRingerMode() == AudioManager.RINGER_MODE_VIBRATE;
   1479 
   1480             case AudioManager.VIBRATE_SETTING_OFF:
   1481                 // return false, even for incoming calls
   1482                 return false;
   1483 
   1484             default:
   1485                 return false;
   1486         }
   1487     }
   1488 
   1489     /** @see AudioManager#getVibrateSetting(int) */
   1490     public int getVibrateSetting(int vibrateType) {
   1491         if (!mHasVibrator) return AudioManager.VIBRATE_SETTING_OFF;
   1492         return (mVibrateSetting >> (vibrateType * 2)) & 3;
   1493     }
   1494 
   1495     /** @see AudioManager#setVibrateSetting(int, int) */
   1496     public void setVibrateSetting(int vibrateType, int vibrateSetting) {
   1497 
   1498         if (!mHasVibrator) return;
   1499 
   1500         mVibrateSetting = getValueForVibrateSetting(mVibrateSetting, vibrateType, vibrateSetting);
   1501 
   1502         // Broadcast change
   1503         broadcastVibrateSetting(vibrateType);
   1504 
   1505     }
   1506 
   1507     /**
   1508      * @see #setVibrateSetting(int, int)
   1509      */
   1510     public static int getValueForVibrateSetting(int existingValue, int vibrateType,
   1511             int vibrateSetting) {
   1512 
   1513         // First clear the existing setting. Each vibrate type has two bits in
   1514         // the value. Note '3' is '11' in binary.
   1515         existingValue &= ~(3 << (vibrateType * 2));
   1516 
   1517         // Set into the old value
   1518         existingValue |= (vibrateSetting & 3) << (vibrateType * 2);
   1519 
   1520         return existingValue;
   1521     }
   1522 
   1523     private class SetModeDeathHandler implements IBinder.DeathRecipient {
   1524         private IBinder mCb; // To be notified of client's death
   1525         private int mPid;
   1526         private int mMode = AudioSystem.MODE_NORMAL; // Current mode set by this client
   1527 
   1528         SetModeDeathHandler(IBinder cb, int pid) {
   1529             mCb = cb;
   1530             mPid = pid;
   1531         }
   1532 
   1533         public void binderDied() {
   1534             int newModeOwnerPid = 0;
   1535             synchronized(mSetModeDeathHandlers) {
   1536                 Log.w(TAG, "setMode() client died");
   1537                 int index = mSetModeDeathHandlers.indexOf(this);
   1538                 if (index < 0) {
   1539                     Log.w(TAG, "unregistered setMode() client died");
   1540                 } else {
   1541                     newModeOwnerPid = setModeInt(AudioSystem.MODE_NORMAL, mCb, mPid);
   1542                 }
   1543             }
   1544             // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
   1545             // SCO connections not started by the application changing the mode
   1546             if (newModeOwnerPid != 0) {
   1547                 final long ident = Binder.clearCallingIdentity();
   1548                 disconnectBluetoothSco(newModeOwnerPid);
   1549                 Binder.restoreCallingIdentity(ident);
   1550             }
   1551         }
   1552 
   1553         public int getPid() {
   1554             return mPid;
   1555         }
   1556 
   1557         public void setMode(int mode) {
   1558             mMode = mode;
   1559         }
   1560 
   1561         public int getMode() {
   1562             return mMode;
   1563         }
   1564 
   1565         public IBinder getBinder() {
   1566             return mCb;
   1567         }
   1568     }
   1569 
   1570     /** @see AudioManager#setMode(int) */
   1571     public void setMode(int mode, IBinder cb) {
   1572         if (!checkAudioSettingsPermission("setMode()")) {
   1573             return;
   1574         }
   1575 
   1576         if (mode < AudioSystem.MODE_CURRENT || mode >= AudioSystem.NUM_MODES) {
   1577             return;
   1578         }
   1579 
   1580         int newModeOwnerPid = 0;
   1581         synchronized(mSetModeDeathHandlers) {
   1582             if (mode == AudioSystem.MODE_CURRENT) {
   1583                 mode = mMode;
   1584             }
   1585             newModeOwnerPid = setModeInt(mode, cb, Binder.getCallingPid());
   1586         }
   1587         // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
   1588         // SCO connections not started by the application changing the mode
   1589         if (newModeOwnerPid != 0) {
   1590              disconnectBluetoothSco(newModeOwnerPid);
   1591         }
   1592     }
   1593 
   1594     // must be called synchronized on mSetModeDeathHandlers
   1595     // setModeInt() returns a valid PID if the audio mode was successfully set to
   1596     // any mode other than NORMAL.
   1597     int setModeInt(int mode, IBinder cb, int pid) {
   1598         int newModeOwnerPid = 0;
   1599         if (cb == null) {
   1600             Log.e(TAG, "setModeInt() called with null binder");
   1601             return newModeOwnerPid;
   1602         }
   1603 
   1604         SetModeDeathHandler hdlr = null;
   1605         Iterator iter = mSetModeDeathHandlers.iterator();
   1606         while (iter.hasNext()) {
   1607             SetModeDeathHandler h = (SetModeDeathHandler)iter.next();
   1608             if (h.getPid() == pid) {
   1609                 hdlr = h;
   1610                 // Remove from client list so that it is re-inserted at top of list
   1611                 iter.remove();
   1612                 hdlr.getBinder().unlinkToDeath(hdlr, 0);
   1613                 break;
   1614             }
   1615         }
   1616         int status = AudioSystem.AUDIO_STATUS_OK;
   1617         do {
   1618             if (mode == AudioSystem.MODE_NORMAL) {
   1619                 // get new mode from client at top the list if any
   1620                 if (!mSetModeDeathHandlers.isEmpty()) {
   1621                     hdlr = mSetModeDeathHandlers.get(0);
   1622                     cb = hdlr.getBinder();
   1623                     mode = hdlr.getMode();
   1624                 }
   1625             } else {
   1626                 if (hdlr == null) {
   1627                     hdlr = new SetModeDeathHandler(cb, pid);
   1628                 }
   1629                 // Register for client death notification
   1630                 try {
   1631                     cb.linkToDeath(hdlr, 0);
   1632                 } catch (RemoteException e) {
   1633                     // Client has died!
   1634                     Log.w(TAG, "setMode() could not link to "+cb+" binder death");
   1635                 }
   1636 
   1637                 // Last client to call setMode() is always at top of client list
   1638                 // as required by SetModeDeathHandler.binderDied()
   1639                 mSetModeDeathHandlers.add(0, hdlr);
   1640                 hdlr.setMode(mode);
   1641             }
   1642 
   1643             if (mode != mMode) {
   1644                 status = AudioSystem.setPhoneState(mode);
   1645                 if (status == AudioSystem.AUDIO_STATUS_OK) {
   1646                     mMode = mode;
   1647                 } else {
   1648                     if (hdlr != null) {
   1649                         mSetModeDeathHandlers.remove(hdlr);
   1650                         cb.unlinkToDeath(hdlr, 0);
   1651                     }
   1652                     // force reading new top of mSetModeDeathHandlers stack
   1653                     mode = AudioSystem.MODE_NORMAL;
   1654                 }
   1655             } else {
   1656                 status = AudioSystem.AUDIO_STATUS_OK;
   1657             }
   1658         } while (status != AudioSystem.AUDIO_STATUS_OK && !mSetModeDeathHandlers.isEmpty());
   1659 
   1660         if (status == AudioSystem.AUDIO_STATUS_OK) {
   1661             if (mode != AudioSystem.MODE_NORMAL) {
   1662                 if (mSetModeDeathHandlers.isEmpty()) {
   1663                     Log.e(TAG, "setMode() different from MODE_NORMAL with empty mode client stack");
   1664                 } else {
   1665                     newModeOwnerPid = mSetModeDeathHandlers.get(0).getPid();
   1666                 }
   1667             }
   1668             int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE);
   1669             if (streamType == STREAM_REMOTE_MUSIC) {
   1670                 // here handle remote media playback the same way as local playback
   1671                 streamType = AudioManager.STREAM_MUSIC;
   1672             }
   1673             int device = getDeviceForStream(streamType);
   1674             int index = mStreamStates[mStreamVolumeAlias[streamType]].getIndex(device);
   1675             setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, true);
   1676 
   1677             updateStreamVolumeAlias(true /*updateVolumes*/);
   1678         }
   1679         return newModeOwnerPid;
   1680     }
   1681 
   1682     /** @see AudioManager#getMode() */
   1683     public int getMode() {
   1684         return mMode;
   1685     }
   1686 
   1687     //==========================================================================================
   1688     // Sound Effects
   1689     //==========================================================================================
   1690 
   1691     private static final String TAG_AUDIO_ASSETS = "audio_assets";
   1692     private static final String ATTR_VERSION = "version";
   1693     private static final String TAG_GROUP = "group";
   1694     private static final String ATTR_GROUP_NAME = "name";
   1695     private static final String TAG_ASSET = "asset";
   1696     private static final String ATTR_ASSET_ID = "id";
   1697     private static final String ATTR_ASSET_FILE = "file";
   1698 
   1699     private static final String ASSET_FILE_VERSION = "1.0";
   1700     private static final String GROUP_TOUCH_SOUNDS = "touch_sounds";
   1701 
   1702     private static final int SOUND_EFECTS_LOAD_TIMEOUT_MS = 5000;
   1703 
   1704     class LoadSoundEffectReply {
   1705         public int mStatus = 1;
   1706     };
   1707 
   1708     private void loadTouchSoundAssetDefaults() {
   1709         SOUND_EFFECT_FILES.add("Effect_Tick.ogg");
   1710         for (int i = 0; i < AudioManager.NUM_SOUND_EFFECTS; i++) {
   1711             SOUND_EFFECT_FILES_MAP[i][0] = 0;
   1712             SOUND_EFFECT_FILES_MAP[i][1] = -1;
   1713         }
   1714     }
   1715 
   1716     private void loadTouchSoundAssets() {
   1717         XmlResourceParser parser = null;
   1718 
   1719         // only load assets once.
   1720         if (!SOUND_EFFECT_FILES.isEmpty()) {
   1721             return;
   1722         }
   1723 
   1724         loadTouchSoundAssetDefaults();
   1725 
   1726         try {
   1727             parser = mContext.getResources().getXml(com.android.internal.R.xml.audio_assets);
   1728 
   1729             XmlUtils.beginDocument(parser, TAG_AUDIO_ASSETS);
   1730             String version = parser.getAttributeValue(null, ATTR_VERSION);
   1731             boolean inTouchSoundsGroup = false;
   1732 
   1733             if (ASSET_FILE_VERSION.equals(version)) {
   1734                 while (true) {
   1735                     XmlUtils.nextElement(parser);
   1736                     String element = parser.getName();
   1737                     if (element == null) {
   1738                         break;
   1739                     }
   1740                     if (element.equals(TAG_GROUP)) {
   1741                         String name = parser.getAttributeValue(null, ATTR_GROUP_NAME);
   1742                         if (GROUP_TOUCH_SOUNDS.equals(name)) {
   1743                             inTouchSoundsGroup = true;
   1744                             break;
   1745                         }
   1746                     }
   1747                 }
   1748                 while (inTouchSoundsGroup) {
   1749                     XmlUtils.nextElement(parser);
   1750                     String element = parser.getName();
   1751                     if (element == null) {
   1752                         break;
   1753                     }
   1754                     if (element.equals(TAG_ASSET)) {
   1755                         String id = parser.getAttributeValue(null, ATTR_ASSET_ID);
   1756                         String file = parser.getAttributeValue(null, ATTR_ASSET_FILE);
   1757                         int fx;
   1758 
   1759                         try {
   1760                             Field field = AudioManager.class.getField(id);
   1761                             fx = field.getInt(null);
   1762                         } catch (Exception e) {
   1763                             Log.w(TAG, "Invalid touch sound ID: "+id);
   1764                             continue;
   1765                         }
   1766 
   1767                         int i = SOUND_EFFECT_FILES.indexOf(file);
   1768                         if (i == -1) {
   1769                             i = SOUND_EFFECT_FILES.size();
   1770                             SOUND_EFFECT_FILES.add(file);
   1771                         }
   1772                         SOUND_EFFECT_FILES_MAP[fx][0] = i;
   1773                     } else {
   1774                         break;
   1775                     }
   1776                 }
   1777             }
   1778         } catch (Resources.NotFoundException e) {
   1779             Log.w(TAG, "audio assets file not found", e);
   1780         } catch (XmlPullParserException e) {
   1781             Log.w(TAG, "XML parser exception reading touch sound assets", e);
   1782         } catch (IOException e) {
   1783             Log.w(TAG, "I/O exception reading touch sound assets", e);
   1784         } finally {
   1785             if (parser != null) {
   1786                 parser.close();
   1787             }
   1788         }
   1789     }
   1790 
   1791     /** @see AudioManager#playSoundEffect(int) */
   1792     public void playSoundEffect(int effectType) {
   1793         playSoundEffectVolume(effectType, -1.0f);
   1794     }
   1795 
   1796     /** @see AudioManager#playSoundEffect(int, float) */
   1797     public void playSoundEffectVolume(int effectType, float volume) {
   1798         sendMsg(mAudioHandler, MSG_PLAY_SOUND_EFFECT, SENDMSG_QUEUE,
   1799                 effectType, (int) (volume * 1000), null, 0);
   1800     }
   1801 
   1802     /**
   1803      * Loads samples into the soundpool.
   1804      * This method must be called at first when sound effects are enabled
   1805      */
   1806     public boolean loadSoundEffects() {
   1807         int attempts = 3;
   1808         LoadSoundEffectReply reply = new LoadSoundEffectReply();
   1809 
   1810         synchronized (reply) {
   1811             sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, reply, 0);
   1812             while ((reply.mStatus == 1) && (attempts-- > 0)) {
   1813                 try {
   1814                     reply.wait(SOUND_EFECTS_LOAD_TIMEOUT_MS);
   1815                 } catch (InterruptedException e) {
   1816                     Log.w(TAG, "loadSoundEffects Interrupted while waiting sound pool loaded.");
   1817                 }
   1818             }
   1819         }
   1820         return (reply.mStatus == 0);
   1821     }
   1822 
   1823     /**
   1824      *  Unloads samples from the sound pool.
   1825      *  This method can be called to free some memory when
   1826      *  sound effects are disabled.
   1827      */
   1828     public void unloadSoundEffects() {
   1829         sendMsg(mAudioHandler, MSG_UNLOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, null, 0);
   1830     }
   1831 
   1832     class SoundPoolListenerThread extends Thread {
   1833         public SoundPoolListenerThread() {
   1834             super("SoundPoolListenerThread");
   1835         }
   1836 
   1837         @Override
   1838         public void run() {
   1839 
   1840             Looper.prepare();
   1841             mSoundPoolLooper = Looper.myLooper();
   1842 
   1843             synchronized (mSoundEffectsLock) {
   1844                 if (mSoundPool != null) {
   1845                     mSoundPoolCallBack = new SoundPoolCallback();
   1846                     mSoundPool.setOnLoadCompleteListener(mSoundPoolCallBack);
   1847                 }
   1848                 mSoundEffectsLock.notify();
   1849             }
   1850             Looper.loop();
   1851         }
   1852     }
   1853 
   1854     private final class SoundPoolCallback implements
   1855             android.media.SoundPool.OnLoadCompleteListener {
   1856 
   1857         int mStatus = 1; // 1 means neither error nor last sample loaded yet
   1858         List<Integer> mSamples = new ArrayList<Integer>();
   1859 
   1860         public int status() {
   1861             return mStatus;
   1862         }
   1863 
   1864         public void setSamples(int[] samples) {
   1865             for (int i = 0; i < samples.length; i++) {
   1866                 // do not wait ack for samples rejected upfront by SoundPool
   1867                 if (samples[i] > 0) {
   1868                     mSamples.add(samples[i]);
   1869                 }
   1870             }
   1871         }
   1872 
   1873         public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
   1874             synchronized (mSoundEffectsLock) {
   1875                 int i = mSamples.indexOf(sampleId);
   1876                 if (i >= 0) {
   1877                     mSamples.remove(i);
   1878                 }
   1879                 if ((status != 0) || mSamples. isEmpty()) {
   1880                     mStatus = status;
   1881                     mSoundEffectsLock.notify();
   1882                 }
   1883             }
   1884         }
   1885     }
   1886 
   1887     /** @see AudioManager#reloadAudioSettings() */
   1888     public void reloadAudioSettings() {
   1889         readAudioSettings(false /*userSwitch*/);
   1890     }
   1891 
   1892     private void readAudioSettings(boolean userSwitch) {
   1893         // restore ringer mode, ringer mode affected streams, mute affected streams and vibrate settings
   1894         readPersistedSettings();
   1895 
   1896         // restore volume settings
   1897         int numStreamTypes = AudioSystem.getNumStreamTypes();
   1898         for (int streamType = 0; streamType < numStreamTypes; streamType++) {
   1899             VolumeStreamState streamState = mStreamStates[streamType];
   1900 
   1901             if (userSwitch && mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) {
   1902                 continue;
   1903             }
   1904 
   1905             synchronized (streamState) {
   1906                 streamState.readSettings();
   1907 
   1908                 // unmute stream that was muted but is not affect by mute anymore
   1909                 if (streamState.isMuted() && ((!isStreamAffectedByMute(streamType) &&
   1910                         !isStreamMutedByRingerMode(streamType)) || mUseFixedVolume)) {
   1911                     int size = streamState.mDeathHandlers.size();
   1912                     for (int i = 0; i < size; i++) {
   1913                         streamState.mDeathHandlers.get(i).mMuteCount = 1;
   1914                         streamState.mDeathHandlers.get(i).mute(false);
   1915                     }
   1916                 }
   1917             }
   1918         }
   1919 
   1920         // apply new ringer mode before checking volume for alias streams so that streams
   1921         // muted by ringer mode have the correct volume
   1922         setRingerModeInt(getRingerMode(), false);
   1923 
   1924         checkAllAliasStreamVolumes();
   1925 
   1926         synchronized (mSafeMediaVolumeState) {
   1927             if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) {
   1928                 enforceSafeMediaVolume();
   1929             }
   1930         }
   1931     }
   1932 
   1933     /** @see AudioManager#setSpeakerphoneOn(boolean) */
   1934     public void setSpeakerphoneOn(boolean on){
   1935         if (!checkAudioSettingsPermission("setSpeakerphoneOn()")) {
   1936             return;
   1937         }
   1938 
   1939         if (on) {
   1940             if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
   1941                     sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
   1942                             AudioSystem.FOR_RECORD, AudioSystem.FORCE_NONE, null, 0);
   1943             }
   1944             mForcedUseForComm = AudioSystem.FORCE_SPEAKER;
   1945         } else if (mForcedUseForComm == AudioSystem.FORCE_SPEAKER){
   1946             mForcedUseForComm = AudioSystem.FORCE_NONE;
   1947         }
   1948 
   1949         sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
   1950                 AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, null, 0);
   1951     }
   1952 
   1953     /** @see AudioManager#isSpeakerphoneOn() */
   1954     public boolean isSpeakerphoneOn() {
   1955         return (mForcedUseForComm == AudioSystem.FORCE_SPEAKER);
   1956     }
   1957 
   1958     /** @see AudioManager#setBluetoothScoOn(boolean) */
   1959     public void setBluetoothScoOn(boolean on){
   1960         if (!checkAudioSettingsPermission("setBluetoothScoOn()")) {
   1961             return;
   1962         }
   1963 
   1964         if (on) {
   1965             mForcedUseForComm = AudioSystem.FORCE_BT_SCO;
   1966         } else if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
   1967             mForcedUseForComm = AudioSystem.FORCE_NONE;
   1968         }
   1969 
   1970         sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
   1971                 AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, null, 0);
   1972         sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
   1973                 AudioSystem.FOR_RECORD, mForcedUseForComm, null, 0);
   1974     }
   1975 
   1976     /** @see AudioManager#isBluetoothScoOn() */
   1977     public boolean isBluetoothScoOn() {
   1978         return (mForcedUseForComm == AudioSystem.FORCE_BT_SCO);
   1979     }
   1980 
   1981     /** @see AudioManager#setBluetoothA2dpOn(boolean) */
   1982     public void setBluetoothA2dpOn(boolean on) {
   1983         synchronized (mBluetoothA2dpEnabledLock) {
   1984             mBluetoothA2dpEnabled = on;
   1985             sendMsg(mAudioHandler, MSG_SET_FORCE_BT_A2DP_USE, SENDMSG_QUEUE,
   1986                     AudioSystem.FOR_MEDIA,
   1987                     mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP,
   1988                     null, 0);
   1989         }
   1990     }
   1991 
   1992     /** @see AudioManager#isBluetoothA2dpOn() */
   1993     public boolean isBluetoothA2dpOn() {
   1994         synchronized (mBluetoothA2dpEnabledLock) {
   1995             return mBluetoothA2dpEnabled;
   1996         }
   1997     }
   1998 
   1999     /** @see AudioManager#startBluetoothSco() */
   2000     public void startBluetoothSco(IBinder cb, int targetSdkVersion){
   2001         if (!checkAudioSettingsPermission("startBluetoothSco()") ||
   2002                 !mBootCompleted) {
   2003             return;
   2004         }
   2005         ScoClient client = getScoClient(cb, true);
   2006         // The calling identity must be cleared before calling ScoClient.incCount().
   2007         // inCount() calls requestScoState() which in turn can call BluetoothHeadset APIs
   2008         // and this must be done on behalf of system server to make sure permissions are granted.
   2009         // The caller identity must be cleared after getScoClient() because it is needed if a new
   2010         // client is created.
   2011         final long ident = Binder.clearCallingIdentity();
   2012         client.incCount(targetSdkVersion);
   2013         Binder.restoreCallingIdentity(ident);
   2014     }
   2015 
   2016     /** @see AudioManager#stopBluetoothSco() */
   2017     public void stopBluetoothSco(IBinder cb){
   2018         if (!checkAudioSettingsPermission("stopBluetoothSco()") ||
   2019                 !mBootCompleted) {
   2020             return;
   2021         }
   2022         ScoClient client = getScoClient(cb, false);
   2023         // The calling identity must be cleared before calling ScoClient.decCount().
   2024         // decCount() calls requestScoState() which in turn can call BluetoothHeadset APIs
   2025         // and this must be done on behalf of system server to make sure permissions are granted.
   2026         final long ident = Binder.clearCallingIdentity();
   2027         if (client != null) {
   2028             client.decCount();
   2029         }
   2030         Binder.restoreCallingIdentity(ident);
   2031     }
   2032 
   2033 
   2034     private class ScoClient implements IBinder.DeathRecipient {
   2035         private IBinder mCb; // To be notified of client's death
   2036         private int mCreatorPid;
   2037         private int mStartcount; // number of SCO connections started by this client
   2038 
   2039         ScoClient(IBinder cb) {
   2040             mCb = cb;
   2041             mCreatorPid = Binder.getCallingPid();
   2042             mStartcount = 0;
   2043         }
   2044 
   2045         public void binderDied() {
   2046             synchronized(mScoClients) {
   2047                 Log.w(TAG, "SCO client died");
   2048                 int index = mScoClients.indexOf(this);
   2049                 if (index < 0) {
   2050                     Log.w(TAG, "unregistered SCO client died");
   2051                 } else {
   2052                     clearCount(true);
   2053                     mScoClients.remove(this);
   2054                 }
   2055             }
   2056         }
   2057 
   2058         public void incCount(int targetSdkVersion) {
   2059             synchronized(mScoClients) {
   2060                 requestScoState(BluetoothHeadset.STATE_AUDIO_CONNECTED, targetSdkVersion);
   2061                 if (mStartcount == 0) {
   2062                     try {
   2063                         mCb.linkToDeath(this, 0);
   2064                     } catch (RemoteException e) {
   2065                         // client has already died!
   2066                         Log.w(TAG, "ScoClient  incCount() could not link to "+mCb+" binder death");
   2067                     }
   2068                 }
   2069                 mStartcount++;
   2070             }
   2071         }
   2072 
   2073         public void decCount() {
   2074             synchronized(mScoClients) {
   2075                 if (mStartcount == 0) {
   2076                     Log.w(TAG, "ScoClient.decCount() already 0");
   2077                 } else {
   2078                     mStartcount--;
   2079                     if (mStartcount == 0) {
   2080                         try {
   2081                             mCb.unlinkToDeath(this, 0);
   2082                         } catch (NoSuchElementException e) {
   2083                             Log.w(TAG, "decCount() going to 0 but not registered to binder");
   2084                         }
   2085                     }
   2086                     requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, 0);
   2087                 }
   2088             }
   2089         }
   2090 
   2091         public void clearCount(boolean stopSco) {
   2092             synchronized(mScoClients) {
   2093                 if (mStartcount != 0) {
   2094                     try {
   2095                         mCb.unlinkToDeath(this, 0);
   2096                     } catch (NoSuchElementException e) {
   2097                         Log.w(TAG, "clearCount() mStartcount: "+mStartcount+" != 0 but not registered to binder");
   2098                     }
   2099                 }
   2100                 mStartcount = 0;
   2101                 if (stopSco) {
   2102                     requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, 0);
   2103                 }
   2104             }
   2105         }
   2106 
   2107         public int getCount() {
   2108             return mStartcount;
   2109         }
   2110 
   2111         public IBinder getBinder() {
   2112             return mCb;
   2113         }
   2114 
   2115         public int getPid() {
   2116             return mCreatorPid;
   2117         }
   2118 
   2119         public int totalCount() {
   2120             synchronized(mScoClients) {
   2121                 int count = 0;
   2122                 int size = mScoClients.size();
   2123                 for (int i = 0; i < size; i++) {
   2124                     count += mScoClients.get(i).getCount();
   2125                 }
   2126                 return count;
   2127             }
   2128         }
   2129 
   2130         private void requestScoState(int state, int targetSdkVersion) {
   2131             checkScoAudioState();
   2132             if (totalCount() == 0) {
   2133                 if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) {
   2134                     // Make sure that the state transitions to CONNECTING even if we cannot initiate
   2135                     // the connection.
   2136                     broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTING);
   2137                     // Accept SCO audio activation only in NORMAL audio mode or if the mode is
   2138                     // currently controlled by the same client process.
   2139                     synchronized(mSetModeDeathHandlers) {
   2140                         if ((mSetModeDeathHandlers.isEmpty() ||
   2141                                 mSetModeDeathHandlers.get(0).getPid() == mCreatorPid) &&
   2142                                 (mScoAudioState == SCO_STATE_INACTIVE ||
   2143                                  mScoAudioState == SCO_STATE_DEACTIVATE_REQ)) {
   2144                             if (mScoAudioState == SCO_STATE_INACTIVE) {
   2145                                 mScoAudioMode =
   2146                                         (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR2) ?
   2147                                                 SCO_MODE_VIRTUAL_CALL : SCO_MODE_RAW;
   2148                                 if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) {
   2149                                     boolean status;
   2150                                     if (mScoAudioMode == SCO_MODE_RAW) {
   2151                                         status = mBluetoothHeadset.connectAudio();
   2152                                     } else {
   2153                                         status = mBluetoothHeadset.startScoUsingVirtualVoiceCall(
   2154                                                                             mBluetoothHeadsetDevice);
   2155                                     }
   2156                                     if (status) {
   2157                                         mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
   2158                                     } else {
   2159                                         broadcastScoConnectionState(
   2160                                                 AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
   2161                                     }
   2162                                 } else if (getBluetoothHeadset()) {
   2163                                     mScoAudioState = SCO_STATE_ACTIVATE_REQ;
   2164                                 }
   2165                             } else {
   2166                                 mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
   2167                                 broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTED);
   2168                             }
   2169                         } else {
   2170                             broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
   2171                         }
   2172                     }
   2173                 } else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED &&
   2174                               (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL ||
   2175                                mScoAudioState == SCO_STATE_ACTIVATE_REQ)) {
   2176                     if (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL) {
   2177                         if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) {
   2178                             boolean status;
   2179                             if (mScoAudioMode == SCO_MODE_RAW) {
   2180                                 status = mBluetoothHeadset.disconnectAudio();
   2181                             } else {
   2182                                 status = mBluetoothHeadset.stopScoUsingVirtualVoiceCall(
   2183                                                                         mBluetoothHeadsetDevice);
   2184                             }
   2185                             if (!status) {
   2186                                 mScoAudioState = SCO_STATE_INACTIVE;
   2187                                 broadcastScoConnectionState(
   2188                                         AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
   2189                             }
   2190                         } else if (getBluetoothHeadset()) {
   2191                             mScoAudioState = SCO_STATE_DEACTIVATE_REQ;
   2192                         }
   2193                     } else {
   2194                         mScoAudioState = SCO_STATE_INACTIVE;
   2195                         broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
   2196                     }
   2197                 }
   2198             }
   2199         }
   2200     }
   2201 
   2202     private void checkScoAudioState() {
   2203         if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null &&
   2204                 mScoAudioState == SCO_STATE_INACTIVE &&
   2205                 mBluetoothHeadset.getAudioState(mBluetoothHeadsetDevice)
   2206                 != BluetoothHeadset.STATE_AUDIO_DISCONNECTED) {
   2207             mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL;
   2208         }
   2209     }
   2210 
   2211     private ScoClient getScoClient(IBinder cb, boolean create) {
   2212         synchronized(mScoClients) {
   2213             ScoClient client = null;
   2214             int size = mScoClients.size();
   2215             for (int i = 0; i < size; i++) {
   2216                 client = mScoClients.get(i);
   2217                 if (client.getBinder() == cb)
   2218                     return client;
   2219             }
   2220             if (create) {
   2221                 client = new ScoClient(cb);
   2222                 mScoClients.add(client);
   2223             }
   2224             return client;
   2225         }
   2226     }
   2227 
   2228     public void clearAllScoClients(int exceptPid, boolean stopSco) {
   2229         synchronized(mScoClients) {
   2230             ScoClient savedClient = null;
   2231             int size = mScoClients.size();
   2232             for (int i = 0; i < size; i++) {
   2233                 ScoClient cl = mScoClients.get(i);
   2234                 if (cl.getPid() != exceptPid) {
   2235                     cl.clearCount(stopSco);
   2236                 } else {
   2237                     savedClient = cl;
   2238                 }
   2239             }
   2240             mScoClients.clear();
   2241             if (savedClient != null) {
   2242                 mScoClients.add(savedClient);
   2243             }
   2244         }
   2245     }
   2246 
   2247     private boolean getBluetoothHeadset() {
   2248         boolean result = false;
   2249         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
   2250         if (adapter != null) {
   2251             result = adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
   2252                                     BluetoothProfile.HEADSET);
   2253         }
   2254         // If we could not get a bluetooth headset proxy, send a failure message
   2255         // without delay to reset the SCO audio state and clear SCO clients.
   2256         // If we could get a proxy, send a delayed failure message that will reset our state
   2257         // in case we don't receive onServiceConnected().
   2258         sendMsg(mAudioHandler, MSG_BT_HEADSET_CNCT_FAILED,
   2259                 SENDMSG_REPLACE, 0, 0, null, result ? BT_HEADSET_CNCT_TIMEOUT_MS : 0);
   2260         return result;
   2261     }
   2262 
   2263     private void disconnectBluetoothSco(int exceptPid) {
   2264         synchronized(mScoClients) {
   2265             checkScoAudioState();
   2266             if (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL ||
   2267                     mScoAudioState == SCO_STATE_DEACTIVATE_EXT_REQ) {
   2268                 if (mBluetoothHeadsetDevice != null) {
   2269                     if (mBluetoothHeadset != null) {
   2270                         if (!mBluetoothHeadset.stopVoiceRecognition(
   2271                                 mBluetoothHeadsetDevice)) {
   2272                             sendMsg(mAudioHandler, MSG_BT_HEADSET_CNCT_FAILED,
   2273                                     SENDMSG_REPLACE, 0, 0, null, 0);
   2274                         }
   2275                     } else if (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL &&
   2276                             getBluetoothHeadset()) {
   2277                         mScoAudioState = SCO_STATE_DEACTIVATE_EXT_REQ;
   2278                     }
   2279                 }
   2280             } else {
   2281                 clearAllScoClients(exceptPid, true);
   2282             }
   2283         }
   2284     }
   2285 
   2286     private void resetBluetoothSco() {
   2287         synchronized(mScoClients) {
   2288             clearAllScoClients(0, false);
   2289             mScoAudioState = SCO_STATE_INACTIVE;
   2290             broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
   2291         }
   2292     }
   2293 
   2294     private void broadcastScoConnectionState(int state) {
   2295         sendMsg(mAudioHandler, MSG_BROADCAST_BT_CONNECTION_STATE,
   2296                 SENDMSG_QUEUE, state, 0, null, 0);
   2297     }
   2298 
   2299     private void onBroadcastScoConnectionState(int state) {
   2300         if (state != mScoConnectionState) {
   2301             Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
   2302             newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, state);
   2303             newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_PREVIOUS_STATE,
   2304                     mScoConnectionState);
   2305             sendStickyBroadcastToAll(newIntent);
   2306             mScoConnectionState = state;
   2307         }
   2308     }
   2309 
   2310     private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
   2311         new BluetoothProfile.ServiceListener() {
   2312         public void onServiceConnected(int profile, BluetoothProfile proxy) {
   2313             BluetoothDevice btDevice;
   2314             List<BluetoothDevice> deviceList;
   2315             switch(profile) {
   2316             case BluetoothProfile.A2DP:
   2317                 synchronized (mA2dpAvrcpLock) {
   2318                     mA2dp = (BluetoothA2dp) proxy;
   2319                     deviceList = mA2dp.getConnectedDevices();
   2320                     if (deviceList.size() > 0) {
   2321                         btDevice = deviceList.get(0);
   2322                         synchronized (mConnectedDevices) {
   2323                             int state = mA2dp.getConnectionState(btDevice);
   2324                             int delay = checkSendBecomingNoisyIntent(
   2325                                                     AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
   2326                                                     (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0);
   2327                             queueMsgUnderWakeLock(mAudioHandler,
   2328                                     MSG_SET_A2DP_CONNECTION_STATE,
   2329                                     state,
   2330                                     0,
   2331                                     btDevice,
   2332                                     delay);
   2333                         }
   2334                     }
   2335                 }
   2336                 break;
   2337 
   2338             case BluetoothProfile.HEADSET:
   2339                 synchronized (mScoClients) {
   2340                     // Discard timeout message
   2341                     mAudioHandler.removeMessages(MSG_BT_HEADSET_CNCT_FAILED);
   2342                     mBluetoothHeadset = (BluetoothHeadset) proxy;
   2343                     deviceList = mBluetoothHeadset.getConnectedDevices();
   2344                     if (deviceList.size() > 0) {
   2345                         mBluetoothHeadsetDevice = deviceList.get(0);
   2346                     } else {
   2347                         mBluetoothHeadsetDevice = null;
   2348                     }
   2349                     // Refresh SCO audio state
   2350                     checkScoAudioState();
   2351                     // Continue pending action if any
   2352                     if (mScoAudioState == SCO_STATE_ACTIVATE_REQ ||
   2353                             mScoAudioState == SCO_STATE_DEACTIVATE_REQ ||
   2354                             mScoAudioState == SCO_STATE_DEACTIVATE_EXT_REQ) {
   2355                         boolean status = false;
   2356                         if (mBluetoothHeadsetDevice != null) {
   2357                             switch (mScoAudioState) {
   2358                             case SCO_STATE_ACTIVATE_REQ:
   2359                                 mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
   2360                                 if (mScoAudioMode == SCO_MODE_RAW) {
   2361                                     status = mBluetoothHeadset.connectAudio();
   2362                                 } else {
   2363                                     status = mBluetoothHeadset.startScoUsingVirtualVoiceCall(
   2364                                                                         mBluetoothHeadsetDevice);
   2365                                 }
   2366                                 break;
   2367                             case SCO_STATE_DEACTIVATE_REQ:
   2368                                 if (mScoAudioMode == SCO_MODE_RAW) {
   2369                                     status = mBluetoothHeadset.disconnectAudio();
   2370                                 } else {
   2371                                     status = mBluetoothHeadset.stopScoUsingVirtualVoiceCall(
   2372                                                                         mBluetoothHeadsetDevice);
   2373                                 }
   2374                                 break;
   2375                             case SCO_STATE_DEACTIVATE_EXT_REQ:
   2376                                 status = mBluetoothHeadset.stopVoiceRecognition(
   2377                                         mBluetoothHeadsetDevice);
   2378                             }
   2379                         }
   2380                         if (!status) {
   2381                             sendMsg(mAudioHandler, MSG_BT_HEADSET_CNCT_FAILED,
   2382                                     SENDMSG_REPLACE, 0, 0, null, 0);
   2383                         }
   2384                     }
   2385                 }
   2386                 break;
   2387 
   2388             default:
   2389                 break;
   2390             }
   2391         }
   2392         public void onServiceDisconnected(int profile) {
   2393             switch(profile) {
   2394             case BluetoothProfile.A2DP:
   2395                 synchronized (mA2dpAvrcpLock) {
   2396                     mA2dp = null;
   2397                     synchronized (mConnectedDevices) {
   2398                         if (mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP)) {
   2399                             makeA2dpDeviceUnavailableNow(
   2400                                     mConnectedDevices.get(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP));
   2401                         }
   2402                     }
   2403                 }
   2404                 break;
   2405 
   2406             case BluetoothProfile.HEADSET:
   2407                 synchronized (mScoClients) {
   2408                     mBluetoothHeadset = null;
   2409                 }
   2410                 break;
   2411 
   2412             default:
   2413                 break;
   2414             }
   2415         }
   2416     };
   2417 
   2418     private void onCheckMusicActive() {
   2419         synchronized (mSafeMediaVolumeState) {
   2420             if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE) {
   2421                 int device = getDeviceForStream(AudioSystem.STREAM_MUSIC);
   2422 
   2423                 if ((device & mSafeMediaVolumeDevices) != 0) {
   2424                     sendMsg(mAudioHandler,
   2425                             MSG_CHECK_MUSIC_ACTIVE,
   2426                             SENDMSG_REPLACE,
   2427                             0,
   2428                             0,
   2429                             null,
   2430                             MUSIC_ACTIVE_POLL_PERIOD_MS);
   2431                     int index = mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(device);
   2432                     if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0) &&
   2433                             (index > mSafeMediaVolumeIndex)) {
   2434                         // Approximate cumulative active music time
   2435                         mMusicActiveMs += MUSIC_ACTIVE_POLL_PERIOD_MS;
   2436                         if (mMusicActiveMs > UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX) {
   2437                             setSafeMediaVolumeEnabled(true);
   2438                             mMusicActiveMs = 0;
   2439                         }
   2440                     }
   2441                 }
   2442             }
   2443         }
   2444     }
   2445 
   2446     private void onConfigureSafeVolume(boolean force) {
   2447         synchronized (mSafeMediaVolumeState) {
   2448             int mcc = mContext.getResources().getConfiguration().mcc;
   2449             if ((mMcc != mcc) || ((mMcc == 0) && force)) {
   2450                 mSafeMediaVolumeIndex = mContext.getResources().getInteger(
   2451                         com.android.internal.R.integer.config_safe_media_volume_index) * 10;
   2452                 boolean safeMediaVolumeEnabled = mContext.getResources().getBoolean(
   2453                         com.android.internal.R.bool.config_safe_media_volume_enabled);
   2454 
   2455                 // The persisted state is either "disabled" or "active": this is the state applied
   2456                 // next time we boot and cannot be "inactive"
   2457                 int persistedState;
   2458                 if (safeMediaVolumeEnabled) {
   2459                     persistedState = SAFE_MEDIA_VOLUME_ACTIVE;
   2460                     // The state can already be "inactive" here if the user has forced it before
   2461                     // the 30 seconds timeout for forced configuration. In this case we don't reset
   2462                     // it to "active".
   2463                     if (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_INACTIVE) {
   2464                         mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE;
   2465                         enforceSafeMediaVolume();
   2466                     }
   2467                 } else {
   2468                     persistedState = SAFE_MEDIA_VOLUME_DISABLED;
   2469                     mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_DISABLED;
   2470                 }
   2471                 mMcc = mcc;
   2472                 sendMsg(mAudioHandler,
   2473                         MSG_PERSIST_SAFE_VOLUME_STATE,
   2474                         SENDMSG_QUEUE,
   2475                         persistedState,
   2476                         0,
   2477                         null,
   2478                         0);
   2479             }
   2480         }
   2481     }
   2482 
   2483     ///////////////////////////////////////////////////////////////////////////
   2484     // Internal methods
   2485     ///////////////////////////////////////////////////////////////////////////
   2486 
   2487     /**
   2488      * Checks if the adjustment should change ringer mode instead of just
   2489      * adjusting volume. If so, this will set the proper ringer mode and volume
   2490      * indices on the stream states.
   2491      */
   2492     private boolean checkForRingerModeChange(int oldIndex, int direction,  int step) {
   2493         boolean adjustVolumeIndex = true;
   2494         int ringerMode = getRingerMode();
   2495 
   2496         switch (ringerMode) {
   2497         case RINGER_MODE_NORMAL:
   2498             if (direction == AudioManager.ADJUST_LOWER) {
   2499                 if (mHasVibrator) {
   2500                     // "step" is the delta in internal index units corresponding to a
   2501                     // change of 1 in UI index units.
   2502                     // Because of rounding when rescaling from one stream index range to its alias
   2503                     // index range, we cannot simply test oldIndex == step:
   2504                     //   (step <= oldIndex < 2 * step) is equivalent to: (old UI index == 1)
   2505                     if (step <= oldIndex && oldIndex < 2 * step) {
   2506                         ringerMode = RINGER_MODE_VIBRATE;
   2507                     }
   2508                 } else {
   2509                     // (oldIndex < step) is equivalent to (old UI index == 0)
   2510                     if ((oldIndex < step) && mPrevVolDirection != AudioManager.ADJUST_LOWER) {
   2511                         ringerMode = RINGER_MODE_SILENT;
   2512                     }
   2513                 }
   2514             }
   2515             break;
   2516         case RINGER_MODE_VIBRATE:
   2517             if (!mHasVibrator) {
   2518                 Log.e(TAG, "checkForRingerModeChange() current ringer mode is vibrate" +
   2519                         "but no vibrator is present");
   2520                 break;
   2521             }
   2522             if ((direction == AudioManager.ADJUST_LOWER)) {
   2523                 if (mPrevVolDirection != AudioManager.ADJUST_LOWER) {
   2524                     ringerMode = RINGER_MODE_SILENT;
   2525                 }
   2526             } else if (direction == AudioManager.ADJUST_RAISE) {
   2527                 ringerMode = RINGER_MODE_NORMAL;
   2528             }
   2529             adjustVolumeIndex = false;
   2530             break;
   2531         case RINGER_MODE_SILENT:
   2532             if (direction == AudioManager.ADJUST_RAISE) {
   2533                 if (mHasVibrator) {
   2534                     ringerMode = RINGER_MODE_VIBRATE;
   2535                 } else {
   2536                     ringerMode = RINGER_MODE_NORMAL;
   2537                 }
   2538             }
   2539             adjustVolumeIndex = false;
   2540             break;
   2541         default:
   2542             Log.e(TAG, "checkForRingerModeChange() wrong ringer mode: "+ringerMode);
   2543             break;
   2544         }
   2545 
   2546         setRingerMode(ringerMode);
   2547 
   2548         mPrevVolDirection = direction;
   2549 
   2550         return adjustVolumeIndex;
   2551     }
   2552 
   2553     public boolean isStreamAffectedByRingerMode(int streamType) {
   2554         return (mRingerModeAffectedStreams & (1 << streamType)) != 0;
   2555     }
   2556 
   2557     private boolean isStreamMutedByRingerMode(int streamType) {
   2558         return (mRingerModeMutedStreams & (1 << streamType)) != 0;
   2559     }
   2560 
   2561     boolean updateRingerModeAffectedStreams() {
   2562         int ringerModeAffectedStreams;
   2563         // make sure settings for ringer mode are consistent with device type: non voice capable
   2564         // devices (tablets) include media stream in silent mode whereas phones don't.
   2565         ringerModeAffectedStreams = Settings.System.getIntForUser(mContentResolver,
   2566                 Settings.System.MODE_RINGER_STREAMS_AFFECTED,
   2567                 ((1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_NOTIFICATION)|
   2568                  (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)),
   2569                  UserHandle.USER_CURRENT);
   2570 
   2571         // ringtone, notification and system streams are always affected by ringer mode
   2572         ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_RING)|
   2573                                         (1 << AudioSystem.STREAM_NOTIFICATION)|
   2574                                         (1 << AudioSystem.STREAM_SYSTEM);
   2575 
   2576         if (mVoiceCapable) {
   2577             ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_MUSIC);
   2578         } else {
   2579             ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_MUSIC);
   2580         }
   2581         synchronized (mCameraSoundForced) {
   2582             if (mCameraSoundForced) {
   2583                 ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
   2584             } else {
   2585                 ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
   2586             }
   2587         }
   2588         if (mStreamVolumeAlias[AudioSystem.STREAM_DTMF] == AudioSystem.STREAM_RING) {
   2589             ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_DTMF);
   2590         } else {
   2591             ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_DTMF);
   2592         }
   2593 
   2594         if (ringerModeAffectedStreams != mRingerModeAffectedStreams) {
   2595             Settings.System.putIntForUser(mContentResolver,
   2596                     Settings.System.MODE_RINGER_STREAMS_AFFECTED,
   2597                     ringerModeAffectedStreams,
   2598                     UserHandle.USER_CURRENT);
   2599             mRingerModeAffectedStreams = ringerModeAffectedStreams;
   2600             return true;
   2601         }
   2602         return false;
   2603     }
   2604 
   2605     public boolean isStreamAffectedByMute(int streamType) {
   2606         return (mMuteAffectedStreams & (1 << streamType)) != 0;
   2607     }
   2608 
   2609     private void ensureValidDirection(int direction) {
   2610         if (direction < AudioManager.ADJUST_LOWER || direction > AudioManager.ADJUST_RAISE) {
   2611             throw new IllegalArgumentException("Bad direction " + direction);
   2612         }
   2613     }
   2614 
   2615     private void ensureValidSteps(int steps) {
   2616         if (Math.abs(steps) > MAX_BATCH_VOLUME_ADJUST_STEPS) {
   2617             throw new IllegalArgumentException("Bad volume adjust steps " + steps);
   2618         }
   2619     }
   2620 
   2621     private void ensureValidStreamType(int streamType) {
   2622         if (streamType < 0 || streamType >= mStreamStates.length) {
   2623             throw new IllegalArgumentException("Bad stream type " + streamType);
   2624         }
   2625     }
   2626 
   2627     private boolean isInCommunication() {
   2628         boolean isOffhook = false;
   2629 
   2630         if (mVoiceCapable) {
   2631             try {
   2632                 ITelephony phone = ITelephony.Stub.asInterface(ServiceManager.checkService("phone"));
   2633                 if (phone != null) isOffhook = phone.isOffhook();
   2634             } catch (RemoteException e) {
   2635                 Log.w(TAG, "Couldn't connect to phone service", e);
   2636             }
   2637         }
   2638         return (isOffhook || getMode() == AudioManager.MODE_IN_COMMUNICATION);
   2639     }
   2640 
   2641     /**
   2642      * For code clarity for getActiveStreamType(int)
   2643      * @param delay_ms max time since last STREAM_MUSIC activity to consider
   2644      * @return true if STREAM_MUSIC is active in streams handled by AudioFlinger now or
   2645      *     in the last "delay_ms" ms.
   2646      */
   2647     private boolean isAfMusicActiveRecently(int delay_ms) {
   2648         return AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, delay_ms)
   2649                 || AudioSystem.isStreamActiveRemotely(AudioSystem.STREAM_MUSIC, delay_ms);
   2650     }
   2651 
   2652     private int getActiveStreamType(int suggestedStreamType) {
   2653         if (mVoiceCapable) {
   2654             if (isInCommunication()) {
   2655                 if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION)
   2656                         == AudioSystem.FORCE_BT_SCO) {
   2657                     // Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO...");
   2658                     return AudioSystem.STREAM_BLUETOOTH_SCO;
   2659                 } else {
   2660                     // Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL...");
   2661                     return AudioSystem.STREAM_VOICE_CALL;
   2662                 }
   2663             } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
   2664                 if (isAfMusicActiveRecently(DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS)) {
   2665                     if (DEBUG_VOL)
   2666                         Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC stream active");
   2667                     return AudioSystem.STREAM_MUSIC;
   2668                 } else
   2669                     if (mMediaFocusControl.checkUpdateRemoteStateIfActive(AudioSystem.STREAM_MUSIC))
   2670                     {
   2671                         if (DEBUG_VOL)
   2672                             Log.v(TAG, "getActiveStreamType: Forcing STREAM_REMOTE_MUSIC");
   2673                         return STREAM_REMOTE_MUSIC;
   2674                     } else {
   2675                         if (DEBUG_VOL)
   2676                             Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING b/c default");
   2677                         return AudioSystem.STREAM_RING;
   2678                 }
   2679             } else if (isAfMusicActiveRecently(0)) {
   2680                 if (DEBUG_VOL)
   2681                     Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC stream active");
   2682                 return AudioSystem.STREAM_MUSIC;
   2683             } else {
   2684                 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Returning suggested type "
   2685                         + suggestedStreamType);
   2686                 return suggestedStreamType;
   2687             }
   2688         } else {
   2689             if (isInCommunication()) {
   2690                 if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION)
   2691                         == AudioSystem.FORCE_BT_SCO) {
   2692                     if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO");
   2693                     return AudioSystem.STREAM_BLUETOOTH_SCO;
   2694                 } else {
   2695                     if (DEBUG_VOL)  Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL");
   2696                     return AudioSystem.STREAM_VOICE_CALL;
   2697                 }
   2698             } else if (AudioSystem.isStreamActive(AudioSystem.STREAM_NOTIFICATION,
   2699                     DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS) ||
   2700                     AudioSystem.isStreamActive(AudioSystem.STREAM_RING,
   2701                             DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS)) {
   2702                 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION");
   2703                 return AudioSystem.STREAM_NOTIFICATION;
   2704             } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
   2705                 if (isAfMusicActiveRecently(DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS)) {
   2706                     if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: forcing STREAM_MUSIC");
   2707                     return AudioSystem.STREAM_MUSIC;
   2708                 } else
   2709                     if (mMediaFocusControl.checkUpdateRemoteStateIfActive(AudioSystem.STREAM_MUSIC))
   2710                     {
   2711                         if (DEBUG_VOL)
   2712                             Log.v(TAG, "getActiveStreamType: Forcing STREAM_REMOTE_MUSIC");
   2713                         return STREAM_REMOTE_MUSIC;
   2714                 } else {
   2715                     if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: using STREAM_MUSIC as default");
   2716                     return AudioSystem.STREAM_MUSIC;
   2717                 }
   2718             } else {
   2719                 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Returning suggested type "
   2720                         + suggestedStreamType);
   2721                 return suggestedStreamType;
   2722             }
   2723         }
   2724     }
   2725 
   2726     private void broadcastRingerMode(int ringerMode) {
   2727         // Send sticky broadcast
   2728         Intent broadcast = new Intent(AudioManager.RINGER_MODE_CHANGED_ACTION);
   2729         broadcast.putExtra(AudioManager.EXTRA_RINGER_MODE, ringerMode);
   2730         broadcast.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
   2731                 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
   2732         sendStickyBroadcastToAll(broadcast);
   2733     }
   2734 
   2735     private void broadcastVibrateSetting(int vibrateType) {
   2736         // Send broadcast
   2737         if (ActivityManagerNative.isSystemReady()) {
   2738             Intent broadcast = new Intent(AudioManager.VIBRATE_SETTING_CHANGED_ACTION);
   2739             broadcast.putExtra(AudioManager.EXTRA_VIBRATE_TYPE, vibrateType);
   2740             broadcast.putExtra(AudioManager.EXTRA_VIBRATE_SETTING, getVibrateSetting(vibrateType));
   2741             sendBroadcastToAll(broadcast);
   2742         }
   2743     }
   2744 
   2745     // Message helper methods
   2746     /**
   2747      * Queue a message on the given handler's message queue, after acquiring the service wake lock.
   2748      * Note that the wake lock needs to be released after the message has been handled.
   2749      */
   2750     private void queueMsgUnderWakeLock(Handler handler, int msg,
   2751             int arg1, int arg2, Object obj, int delay) {
   2752         final long ident = Binder.clearCallingIdentity();
   2753         // Always acquire the wake lock as AudioService because it is released by the
   2754         // message handler.
   2755         mAudioEventWakeLock.acquire();
   2756         Binder.restoreCallingIdentity(ident);
   2757         sendMsg(handler, msg, SENDMSG_QUEUE, arg1, arg2, obj, delay);
   2758     }
   2759 
   2760     private static void sendMsg(Handler handler, int msg,
   2761             int existingMsgPolicy, int arg1, int arg2, Object obj, int delay) {
   2762 
   2763         if (existingMsgPolicy == SENDMSG_REPLACE) {
   2764             handler.removeMessages(msg);
   2765         } else if (existingMsgPolicy == SENDMSG_NOOP && handler.hasMessages(msg)) {
   2766             return;
   2767         }
   2768 
   2769         handler.sendMessageDelayed(handler.obtainMessage(msg, arg1, arg2, obj), delay);
   2770     }
   2771 
   2772     boolean checkAudioSettingsPermission(String method) {
   2773         if (mContext.checkCallingOrSelfPermission("android.permission.MODIFY_AUDIO_SETTINGS")
   2774                 == PackageManager.PERMISSION_GRANTED) {
   2775             return true;
   2776         }
   2777         String msg = "Audio Settings Permission Denial: " + method + " from pid="
   2778                 + Binder.getCallingPid()
   2779                 + ", uid=" + Binder.getCallingUid();
   2780         Log.w(TAG, msg);
   2781         return false;
   2782     }
   2783 
   2784     private int getDeviceForStream(int stream) {
   2785         int device = AudioSystem.getDevicesForStream(stream);
   2786         if ((device & (device - 1)) != 0) {
   2787             // Multiple device selection is either:
   2788             //  - speaker + one other device: give priority to speaker in this case.
   2789             //  - one A2DP device + another device: happens with duplicated output. In this case
   2790             // retain the device on the A2DP output as the other must not correspond to an active
   2791             // selection if not the speaker.
   2792             if ((device & AudioSystem.DEVICE_OUT_SPEAKER) != 0) {
   2793                 device = AudioSystem.DEVICE_OUT_SPEAKER;
   2794             } else {
   2795                 device &= AudioSystem.DEVICE_OUT_ALL_A2DP;
   2796             }
   2797         }
   2798         return device;
   2799     }
   2800 
   2801     public void setWiredDeviceConnectionState(int device, int state, String name) {
   2802         synchronized (mConnectedDevices) {
   2803             int delay = checkSendBecomingNoisyIntent(device, state);
   2804             queueMsgUnderWakeLock(mAudioHandler,
   2805                     MSG_SET_WIRED_DEVICE_CONNECTION_STATE,
   2806                     device,
   2807                     state,
   2808                     name,
   2809                     delay);
   2810         }
   2811     }
   2812 
   2813     public int setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state)
   2814     {
   2815         int delay;
   2816         synchronized (mConnectedDevices) {
   2817             delay = checkSendBecomingNoisyIntent(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
   2818                                             (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0);
   2819             queueMsgUnderWakeLock(mAudioHandler,
   2820                     MSG_SET_A2DP_CONNECTION_STATE,
   2821                     state,
   2822                     0,
   2823                     device,
   2824                     delay);
   2825         }
   2826         return delay;
   2827     }
   2828 
   2829     ///////////////////////////////////////////////////////////////////////////
   2830     // Inner classes
   2831     ///////////////////////////////////////////////////////////////////////////
   2832 
   2833     public class VolumeStreamState {
   2834         private final int mStreamType;
   2835 
   2836         private String mVolumeIndexSettingName;
   2837         private int mIndexMax;
   2838         private final ConcurrentHashMap<Integer, Integer> mIndex =
   2839                                             new ConcurrentHashMap<Integer, Integer>(8, 0.75f, 4);
   2840         private ArrayList<VolumeDeathHandler> mDeathHandlers; //handles mute/solo clients death
   2841 
   2842         private VolumeStreamState(String settingName, int streamType) {
   2843 
   2844             mVolumeIndexSettingName = settingName;
   2845 
   2846             mStreamType = streamType;
   2847             mIndexMax = MAX_STREAM_VOLUME[streamType];
   2848             AudioSystem.initStreamVolume(streamType, 0, mIndexMax);
   2849             mIndexMax *= 10;
   2850 
   2851             // mDeathHandlers must be created before calling readSettings()
   2852             mDeathHandlers = new ArrayList<VolumeDeathHandler>();
   2853 
   2854             readSettings();
   2855         }
   2856 
   2857         public String getSettingNameForDevice(int device) {
   2858             String name = mVolumeIndexSettingName;
   2859             String suffix = AudioSystem.getDeviceName(device);
   2860             if (suffix.isEmpty()) {
   2861                 return name;
   2862             }
   2863             return name + "_" + suffix;
   2864         }
   2865 
   2866         public synchronized void readSettings() {
   2867             // force maximum volume on all streams if fixed volume property is set
   2868             if (mUseFixedVolume) {
   2869                 mIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, mIndexMax);
   2870                 return;
   2871             }
   2872             // do not read system stream volume from settings: this stream is always aliased
   2873             // to another stream type and its volume is never persisted. Values in settings can
   2874             // only be stale values
   2875             if ((mStreamType == AudioSystem.STREAM_SYSTEM) ||
   2876                     (mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED)) {
   2877                 int index = 10 * AudioManager.DEFAULT_STREAM_VOLUME[mStreamType];
   2878                 synchronized (mCameraSoundForced) {
   2879                     if (mCameraSoundForced) {
   2880                         index = mIndexMax;
   2881                     }
   2882                 }
   2883                 mIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, index);
   2884                 return;
   2885             }
   2886 
   2887             int remainingDevices = AudioSystem.DEVICE_OUT_ALL;
   2888 
   2889             for (int i = 0; remainingDevices != 0; i++) {
   2890                 int device = (1 << i);
   2891                 if ((device & remainingDevices) == 0) {
   2892                     continue;
   2893                 }
   2894                 remainingDevices &= ~device;
   2895 
   2896                 // retrieve current volume for device
   2897                 String name = getSettingNameForDevice(device);
   2898                 // if no volume stored for current stream and device, use default volume if default
   2899                 // device, continue otherwise
   2900                 int defaultIndex = (device == AudioSystem.DEVICE_OUT_DEFAULT) ?
   2901                                         AudioManager.DEFAULT_STREAM_VOLUME[mStreamType] : -1;
   2902                 int index = Settings.System.getIntForUser(
   2903                         mContentResolver, name, defaultIndex, UserHandle.USER_CURRENT);
   2904                 if (index == -1) {
   2905                     continue;
   2906                 }
   2907 
   2908                 // ignore settings for fixed volume devices: volume should always be at max or 0
   2909                 if ((mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_MUSIC) &&
   2910                         ((device & mFixedVolumeDevices) != 0)) {
   2911                     mIndex.put(device, (index != 0) ? mIndexMax : 0);
   2912                 } else {
   2913                     mIndex.put(device, getValidIndex(10 * index));
   2914                 }
   2915             }
   2916         }
   2917 
   2918         public void applyDeviceVolume(int device) {
   2919             int index;
   2920             if (isMuted()) {
   2921                 index = 0;
   2922             } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
   2923                        mAvrcpAbsVolSupported) {
   2924                 index = (mIndexMax + 5)/10;
   2925             } else {
   2926                 index = (getIndex(device) + 5)/10;
   2927             }
   2928             AudioSystem.setStreamVolumeIndex(mStreamType, index, device);
   2929         }
   2930 
   2931         public synchronized void applyAllVolumes() {
   2932             // apply default volume first: by convention this will reset all
   2933             // devices volumes in audio policy manager to the supplied value
   2934             int index;
   2935             if (isMuted()) {
   2936                 index = 0;
   2937             } else {
   2938                 index = (getIndex(AudioSystem.DEVICE_OUT_DEFAULT) + 5)/10;
   2939             }
   2940             AudioSystem.setStreamVolumeIndex(mStreamType, index, AudioSystem.DEVICE_OUT_DEFAULT);
   2941             // then apply device specific volumes
   2942             Set set = mIndex.entrySet();
   2943             Iterator i = set.iterator();
   2944             while (i.hasNext()) {
   2945                 Map.Entry entry = (Map.Entry)i.next();
   2946                 int device = ((Integer)entry.getKey()).intValue();
   2947                 if (device != AudioSystem.DEVICE_OUT_DEFAULT) {
   2948                     if (isMuted()) {
   2949                         index = 0;
   2950                     } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
   2951                             mAvrcpAbsVolSupported) {
   2952                         index = (mIndexMax + 5)/10;
   2953                     } else {
   2954                         index = ((Integer)entry.getValue() + 5)/10;
   2955                     }
   2956                     AudioSystem.setStreamVolumeIndex(mStreamType, index, device);
   2957                 }
   2958             }
   2959         }
   2960 
   2961         public boolean adjustIndex(int deltaIndex, int device) {
   2962             return setIndex(getIndex(device) + deltaIndex,
   2963                             device);
   2964         }
   2965 
   2966         public synchronized boolean setIndex(int index, int device) {
   2967             int oldIndex = getIndex(device);
   2968             index = getValidIndex(index);
   2969             synchronized (mCameraSoundForced) {
   2970                 if ((mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED) && mCameraSoundForced) {
   2971                     index = mIndexMax;
   2972                 }
   2973             }
   2974             mIndex.put(device, index);
   2975 
   2976             if (oldIndex != index) {
   2977                 // Apply change to all streams using this one as alias
   2978                 // if changing volume of current device, also change volume of current
   2979                 // device on aliased stream
   2980                 boolean currentDevice = (device == getDeviceForStream(mStreamType));
   2981                 int numStreamTypes = AudioSystem.getNumStreamTypes();
   2982                 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
   2983                     if (streamType != mStreamType &&
   2984                             mStreamVolumeAlias[streamType] == mStreamType) {
   2985                         int scaledIndex = rescaleIndex(index, mStreamType, streamType);
   2986                         mStreamStates[streamType].setIndex(scaledIndex,
   2987                                                            device);
   2988                         if (currentDevice) {
   2989                             mStreamStates[streamType].setIndex(scaledIndex,
   2990                                                                getDeviceForStream(streamType));
   2991                         }
   2992                     }
   2993                 }
   2994                 return true;
   2995             } else {
   2996                 return false;
   2997             }
   2998         }
   2999 
   3000         public synchronized int getIndex(int device) {
   3001             Integer index = mIndex.get(device);
   3002             if (index == null) {
   3003                 // there is always an entry for AudioSystem.DEVICE_OUT_DEFAULT
   3004                 index = mIndex.get(AudioSystem.DEVICE_OUT_DEFAULT);
   3005             }
   3006             return index.intValue();
   3007         }
   3008 
   3009         public int getMaxIndex() {
   3010             return mIndexMax;
   3011         }
   3012 
   3013         public synchronized void setAllIndexes(VolumeStreamState srcStream) {
   3014             int srcStreamType = srcStream.getStreamType();
   3015             // apply default device volume from source stream to all devices first in case
   3016             // some devices are present in this stream state but not in source stream state
   3017             int index = srcStream.getIndex(AudioSystem.DEVICE_OUT_DEFAULT);
   3018             index = rescaleIndex(index, srcStreamType, mStreamType);
   3019             Set set = mIndex.entrySet();
   3020             Iterator i = set.iterator();
   3021             while (i.hasNext()) {
   3022                 Map.Entry entry = (Map.Entry)i.next();
   3023                 entry.setValue(index);
   3024             }
   3025             // Now apply actual volume for devices in source stream state
   3026             set = srcStream.mIndex.entrySet();
   3027             i = set.iterator();
   3028             while (i.hasNext()) {
   3029                 Map.Entry entry = (Map.Entry)i.next();
   3030                 int device = ((Integer)entry.getKey()).intValue();
   3031                 index = ((Integer)entry.getValue()).intValue();
   3032                 index = rescaleIndex(index, srcStreamType, mStreamType);
   3033 
   3034                 setIndex(index, device);
   3035             }
   3036         }
   3037 
   3038         public synchronized void setAllIndexesToMax() {
   3039             Set set = mIndex.entrySet();
   3040             Iterator i = set.iterator();
   3041             while (i.hasNext()) {
   3042                 Map.Entry entry = (Map.Entry)i.next();
   3043                 entry.setValue(mIndexMax);
   3044             }
   3045         }
   3046 
   3047         public synchronized void mute(IBinder cb, boolean state) {
   3048             VolumeDeathHandler handler = getDeathHandler(cb, state);
   3049             if (handler == null) {
   3050                 Log.e(TAG, "Could not get client death handler for stream: "+mStreamType);
   3051                 return;
   3052             }
   3053             handler.mute(state);
   3054         }
   3055 
   3056         public int getStreamType() {
   3057             return mStreamType;
   3058         }
   3059 
   3060         private int getValidIndex(int index) {
   3061             if (index < 0) {
   3062                 return 0;
   3063             } else if (mUseFixedVolume || index > mIndexMax) {
   3064                 return mIndexMax;
   3065             }
   3066 
   3067             return index;
   3068         }
   3069 
   3070         private class VolumeDeathHandler implements IBinder.DeathRecipient {
   3071             private IBinder mICallback; // To be notified of client's death
   3072             private int mMuteCount; // Number of active mutes for this client
   3073 
   3074             VolumeDeathHandler(IBinder cb) {
   3075                 mICallback = cb;
   3076             }
   3077 
   3078             // must be called while synchronized on parent VolumeStreamState
   3079             public void mute(boolean state) {
   3080                 boolean updateVolume = false;
   3081                 if (state) {
   3082                     if (mMuteCount == 0) {
   3083                         // Register for client death notification
   3084                         try {
   3085                             // mICallback can be 0 if muted by AudioService
   3086                             if (mICallback != null) {
   3087                                 mICallback.linkToDeath(this, 0);
   3088                             }
   3089                             VolumeStreamState.this.mDeathHandlers.add(this);
   3090                             // If the stream is not yet muted by any client, set level to 0
   3091                             if (!VolumeStreamState.this.isMuted()) {
   3092                                 updateVolume = true;
   3093                             }
   3094                         } catch (RemoteException e) {
   3095                             // Client has died!
   3096                             binderDied();
   3097                             return;
   3098                         }
   3099                     } else {
   3100                         Log.w(TAG, "stream: "+mStreamType+" was already muted by this client");
   3101                     }
   3102                     mMuteCount++;
   3103                 } else {
   3104                     if (mMuteCount == 0) {
   3105                         Log.e(TAG, "unexpected unmute for stream: "+mStreamType);
   3106                     } else {
   3107                         mMuteCount--;
   3108                         if (mMuteCount == 0) {
   3109                             // Unregister from client death notification
   3110                             VolumeStreamState.this.mDeathHandlers.remove(this);
   3111                             // mICallback can be 0 if muted by AudioService
   3112                             if (mICallback != null) {
   3113                                 mICallback.unlinkToDeath(this, 0);
   3114                             }
   3115                             if (!VolumeStreamState.this.isMuted()) {
   3116                                 updateVolume = true;
   3117                             }
   3118                         }
   3119                     }
   3120                 }
   3121                 if (updateVolume) {
   3122                     sendMsg(mAudioHandler,
   3123                             MSG_SET_ALL_VOLUMES,
   3124                             SENDMSG_QUEUE,
   3125                             0,
   3126                             0,
   3127                             VolumeStreamState.this, 0);
   3128                 }
   3129             }
   3130 
   3131             public void binderDied() {
   3132                 Log.w(TAG, "Volume service client died for stream: "+mStreamType);
   3133                 if (mMuteCount != 0) {
   3134                     // Reset all active mute requests from this client.
   3135                     mMuteCount = 1;
   3136                     mute(false);
   3137                 }
   3138             }
   3139         }
   3140 
   3141         private synchronized int muteCount() {
   3142             int count = 0;
   3143             int size = mDeathHandlers.size();
   3144             for (int i = 0; i < size; i++) {
   3145                 count += mDeathHandlers.get(i).mMuteCount;
   3146             }
   3147             return count;
   3148         }
   3149 
   3150         private synchronized boolean isMuted() {
   3151             return muteCount() != 0;
   3152         }
   3153 
   3154         // only called by mute() which is already synchronized
   3155         private VolumeDeathHandler getDeathHandler(IBinder cb, boolean state) {
   3156             VolumeDeathHandler handler;
   3157             int size = mDeathHandlers.size();
   3158             for (int i = 0; i < size; i++) {
   3159                 handler = mDeathHandlers.get(i);
   3160                 if (cb == handler.mICallback) {
   3161                     return handler;
   3162                 }
   3163             }
   3164             // If this is the first mute request for this client, create a new
   3165             // client death handler. Otherwise, it is an out of sequence unmute request.
   3166             if (state) {
   3167                 handler = new VolumeDeathHandler(cb);
   3168             } else {
   3169                 Log.w(TAG, "stream was not muted by this client");
   3170                 handler = null;
   3171             }
   3172             return handler;
   3173         }
   3174 
   3175         private void dump(PrintWriter pw) {
   3176             pw.print("   Mute count: ");
   3177             pw.println(muteCount());
   3178             pw.print("   Current: ");
   3179             Set set = mIndex.entrySet();
   3180             Iterator i = set.iterator();
   3181             while (i.hasNext()) {
   3182                 Map.Entry entry = (Map.Entry)i.next();
   3183                 pw.print(Integer.toHexString(((Integer)entry.getKey()).intValue())
   3184                              + ": " + ((((Integer)entry.getValue()).intValue() + 5) / 10)+", ");
   3185             }
   3186         }
   3187     }
   3188 
   3189     /** Thread that handles native AudioSystem control. */
   3190     private class AudioSystemThread extends Thread {
   3191         AudioSystemThread() {
   3192             super("AudioService");
   3193         }
   3194 
   3195         @Override
   3196         public void run() {
   3197             // Set this thread up so the handler will work on it
   3198             Looper.prepare();
   3199 
   3200             synchronized(AudioService.this) {
   3201                 mAudioHandler = new AudioHandler();
   3202 
   3203                 // Notify that the handler has been created
   3204                 AudioService.this.notify();
   3205             }
   3206 
   3207             // Listen for volume change requests that are set by VolumePanel
   3208             Looper.loop();
   3209         }
   3210     }
   3211 
   3212     /** Handles internal volume messages in separate volume thread. */
   3213     private class AudioHandler extends Handler {
   3214 
   3215         private void setDeviceVolume(VolumeStreamState streamState, int device) {
   3216 
   3217             // Apply volume
   3218             streamState.applyDeviceVolume(device);
   3219 
   3220             // Apply change to all streams using this one as alias
   3221             int numStreamTypes = AudioSystem.getNumStreamTypes();
   3222             for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
   3223                 if (streamType != streamState.mStreamType &&
   3224                         mStreamVolumeAlias[streamType] == streamState.mStreamType) {
   3225                     // Make sure volume is also maxed out on A2DP device for aliased stream
   3226                     // that may have a different device selected
   3227                     int streamDevice = getDeviceForStream(streamType);
   3228                     if ((device != streamDevice) && mAvrcpAbsVolSupported &&
   3229                             ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0)) {
   3230                         mStreamStates[streamType].applyDeviceVolume(device);
   3231                     }
   3232                     mStreamStates[streamType].applyDeviceVolume(streamDevice);
   3233                 }
   3234             }
   3235 
   3236             // Post a persist volume msg
   3237             sendMsg(mAudioHandler,
   3238                     MSG_PERSIST_VOLUME,
   3239                     SENDMSG_QUEUE,
   3240                     device,
   3241                     0,
   3242                     streamState,
   3243                     PERSIST_DELAY);
   3244 
   3245         }
   3246 
   3247         private void setAllVolumes(VolumeStreamState streamState) {
   3248 
   3249             // Apply volume
   3250             streamState.applyAllVolumes();
   3251 
   3252             // Apply change to all streams using this one as alias
   3253             int numStreamTypes = AudioSystem.getNumStreamTypes();
   3254             for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
   3255                 if (streamType != streamState.mStreamType &&
   3256                         mStreamVolumeAlias[streamType] == streamState.mStreamType) {
   3257                     mStreamStates[streamType].applyAllVolumes();
   3258                 }
   3259             }
   3260         }
   3261 
   3262         private void persistVolume(VolumeStreamState streamState, int device) {
   3263             if (mUseFixedVolume) {
   3264                 return;
   3265             }
   3266             System.putIntForUser(mContentResolver,
   3267                       streamState.getSettingNameForDevice(device),
   3268                       (streamState.getIndex(device) + 5)/ 10,
   3269                       UserHandle.USER_CURRENT);
   3270         }
   3271 
   3272         private void persistRingerMode(int ringerMode) {
   3273             if (mUseFixedVolume) {
   3274                 return;
   3275             }
   3276             Settings.Global.putInt(mContentResolver, Settings.Global.MODE_RINGER, ringerMode);
   3277         }
   3278 
   3279         private boolean onLoadSoundEffects() {
   3280             int status;
   3281 
   3282             synchronized (mSoundEffectsLock) {
   3283                 if (!mBootCompleted) {
   3284                     Log.w(TAG, "onLoadSoundEffects() called before boot complete");
   3285                     return false;
   3286                 }
   3287 
   3288                 if (mSoundPool != null) {
   3289                     return true;
   3290                 }
   3291 
   3292                 loadTouchSoundAssets();
   3293 
   3294                 mSoundPool = new SoundPool(NUM_SOUNDPOOL_CHANNELS, AudioSystem.STREAM_SYSTEM, 0);
   3295                 mSoundPoolCallBack = null;
   3296                 mSoundPoolListenerThread = new SoundPoolListenerThread();
   3297                 mSoundPoolListenerThread.start();
   3298                 int attempts = 3;
   3299                 while ((mSoundPoolCallBack == null) && (attempts-- > 0)) {
   3300                     try {
   3301                         // Wait for mSoundPoolCallBack to be set by the other thread
   3302                         mSoundEffectsLock.wait(SOUND_EFECTS_LOAD_TIMEOUT_MS);
   3303                     } catch (InterruptedException e) {
   3304                         Log.w(TAG, "Interrupted while waiting sound pool listener thread.");
   3305                     }
   3306                 }
   3307 
   3308                 if (mSoundPoolCallBack == null) {
   3309                     Log.w(TAG, "onLoadSoundEffects() SoundPool listener or thread creation error");
   3310                     if (mSoundPoolLooper != null) {
   3311                         mSoundPoolLooper.quit();
   3312                         mSoundPoolLooper = null;
   3313                     }
   3314                     mSoundPoolListenerThread = null;
   3315                     mSoundPool.release();
   3316                     mSoundPool = null;
   3317                     return false;
   3318                 }
   3319                 /*
   3320                  * poolId table: The value -1 in this table indicates that corresponding
   3321                  * file (same index in SOUND_EFFECT_FILES[] has not been loaded.
   3322                  * Once loaded, the value in poolId is the sample ID and the same
   3323                  * sample can be reused for another effect using the same file.
   3324                  */
   3325                 int[] poolId = new int[SOUND_EFFECT_FILES.size()];
   3326                 for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) {
   3327                     poolId[fileIdx] = -1;
   3328                 }
   3329                 /*
   3330                  * Effects whose value in SOUND_EFFECT_FILES_MAP[effect][1] is -1 must be loaded.
   3331                  * If load succeeds, value in SOUND_EFFECT_FILES_MAP[effect][1] is > 0:
   3332                  * this indicates we have a valid sample loaded for this effect.
   3333                  */
   3334 
   3335                 int numSamples = 0;
   3336                 for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
   3337                     // Do not load sample if this effect uses the MediaPlayer
   3338                     if (SOUND_EFFECT_FILES_MAP[effect][1] == 0) {
   3339                         continue;
   3340                     }
   3341                     if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == -1) {
   3342                         String filePath = Environment.getRootDirectory()
   3343                                 + SOUND_EFFECTS_PATH
   3344                                 + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effect][0]);
   3345                         int sampleId = mSoundPool.load(filePath, 0);
   3346                         if (sampleId <= 0) {
   3347                             Log.w(TAG, "Soundpool could not load file: "+filePath);
   3348                         } else {
   3349                             SOUND_EFFECT_FILES_MAP[effect][1] = sampleId;
   3350                             poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = sampleId;
   3351                             numSamples++;
   3352                         }
   3353                     } else {
   3354                         SOUND_EFFECT_FILES_MAP[effect][1] =
   3355                                 poolId[SOUND_EFFECT_FILES_MAP[effect][0]];
   3356                     }
   3357                 }
   3358                 // wait for all samples to be loaded
   3359                 if (numSamples > 0) {
   3360                     mSoundPoolCallBack.setSamples(poolId);
   3361 
   3362                     attempts = 3;
   3363                     status = 1;
   3364                     while ((status == 1) && (attempts-- > 0)) {
   3365                         try {
   3366                             mSoundEffectsLock.wait(SOUND_EFECTS_LOAD_TIMEOUT_MS);
   3367                             status = mSoundPoolCallBack.status();
   3368                         } catch (InterruptedException e) {
   3369                             Log.w(TAG, "Interrupted while waiting sound pool callback.");
   3370                         }
   3371                     }
   3372                 } else {
   3373                     status = -1;
   3374                 }
   3375 
   3376                 if (mSoundPoolLooper != null) {
   3377                     mSoundPoolLooper.quit();
   3378                     mSoundPoolLooper = null;
   3379                 }
   3380                 mSoundPoolListenerThread = null;
   3381                 if (status != 0) {
   3382                     Log.w(TAG,
   3383                             "onLoadSoundEffects(), Error "+status+ " while loading samples");
   3384                     for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
   3385                         if (SOUND_EFFECT_FILES_MAP[effect][1] > 0) {
   3386                             SOUND_EFFECT_FILES_MAP[effect][1] = -1;
   3387                         }
   3388                     }
   3389 
   3390                     mSoundPool.release();
   3391                     mSoundPool = null;
   3392                 }
   3393             }
   3394             return (status == 0);
   3395         }
   3396 
   3397         /**
   3398          *  Unloads samples from the sound pool.
   3399          *  This method can be called to free some memory when
   3400          *  sound effects are disabled.
   3401          */
   3402         private void onUnloadSoundEffects() {
   3403             synchronized (mSoundEffectsLock) {
   3404                 if (mSoundPool == null) {
   3405                     return;
   3406                 }
   3407 
   3408                 int[] poolId = new int[SOUND_EFFECT_FILES.size()];
   3409                 for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) {
   3410                     poolId[fileIdx] = 0;
   3411                 }
   3412 
   3413                 for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
   3414                     if (SOUND_EFFECT_FILES_MAP[effect][1] <= 0) {
   3415                         continue;
   3416                     }
   3417                     if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == 0) {
   3418                         mSoundPool.unload(SOUND_EFFECT_FILES_MAP[effect][1]);
   3419                         SOUND_EFFECT_FILES_MAP[effect][1] = -1;
   3420                         poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = -1;
   3421                     }
   3422                 }
   3423                 mSoundPool.release();
   3424                 mSoundPool = null;
   3425             }
   3426         }
   3427 
   3428         private void onPlaySoundEffect(int effectType, int volume) {
   3429             synchronized (mSoundEffectsLock) {
   3430 
   3431                 onLoadSoundEffects();
   3432 
   3433                 if (mSoundPool == null) {
   3434                     return;
   3435                 }
   3436                 float volFloat;
   3437                 // use default if volume is not specified by caller
   3438                 if (volume < 0) {
   3439                     volFloat = (float)Math.pow(10, (float)sSoundEffectVolumeDb/20);
   3440                 } else {
   3441                     volFloat = (float) volume / 1000.0f;
   3442                 }
   3443 
   3444                 if (SOUND_EFFECT_FILES_MAP[effectType][1] > 0) {
   3445                     mSoundPool.play(SOUND_EFFECT_FILES_MAP[effectType][1],
   3446                                         volFloat, volFloat, 0, 0, 1.0f);
   3447                 } else {
   3448                     MediaPlayer mediaPlayer = new MediaPlayer();
   3449                     try {
   3450                         String filePath = Environment.getRootDirectory() + SOUND_EFFECTS_PATH +
   3451                                     SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]);
   3452                         mediaPlayer.setDataSource(filePath);
   3453                         mediaPlayer.setAudioStreamType(AudioSystem.STREAM_SYSTEM);
   3454                         mediaPlayer.prepare();
   3455                         mediaPlayer.setVolume(volFloat);
   3456                         mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
   3457                             public void onCompletion(MediaPlayer mp) {
   3458                                 cleanupPlayer(mp);
   3459                             }
   3460                         });
   3461                         mediaPlayer.setOnErrorListener(new OnErrorListener() {
   3462                             public boolean onError(MediaPlayer mp, int what, int extra) {
   3463                                 cleanupPlayer(mp);
   3464                                 return true;
   3465                             }
   3466                         });
   3467                         mediaPlayer.start();
   3468                     } catch (IOException ex) {
   3469                         Log.w(TAG, "MediaPlayer IOException: "+ex);
   3470                     } catch (IllegalArgumentException ex) {
   3471                         Log.w(TAG, "MediaPlayer IllegalArgumentException: "+ex);
   3472                     } catch (IllegalStateException ex) {
   3473                         Log.w(TAG, "MediaPlayer IllegalStateException: "+ex);
   3474                     }
   3475                 }
   3476             }
   3477         }
   3478 
   3479         private void cleanupPlayer(MediaPlayer mp) {
   3480             if (mp != null) {
   3481                 try {
   3482                     mp.stop();
   3483                     mp.release();
   3484                 } catch (IllegalStateException ex) {
   3485                     Log.w(TAG, "MediaPlayer IllegalStateException: "+ex);
   3486                 }
   3487             }
   3488         }
   3489 
   3490         private void setForceUse(int usage, int config) {
   3491             AudioSystem.setForceUse(usage, config);
   3492         }
   3493 
   3494         private void onPersistSafeVolumeState(int state) {
   3495             Settings.Global.putInt(mContentResolver,
   3496                     Settings.Global.AUDIO_SAFE_VOLUME_STATE,
   3497                     state);
   3498         }
   3499 
   3500         @Override
   3501         public void handleMessage(Message msg) {
   3502 
   3503             switch (msg.what) {
   3504 
   3505                 case MSG_SET_DEVICE_VOLUME:
   3506                     setDeviceVolume((VolumeStreamState) msg.obj, msg.arg1);
   3507                     break;
   3508 
   3509                 case MSG_SET_ALL_VOLUMES:
   3510                     setAllVolumes((VolumeStreamState) msg.obj);
   3511                     break;
   3512 
   3513                 case MSG_PERSIST_VOLUME:
   3514                     persistVolume((VolumeStreamState) msg.obj, msg.arg1);
   3515                     break;
   3516 
   3517                 case MSG_PERSIST_MASTER_VOLUME:
   3518                     if (mUseFixedVolume) {
   3519                         return;
   3520                     }
   3521                     Settings.System.putFloatForUser(mContentResolver,
   3522                                                     Settings.System.VOLUME_MASTER,
   3523                                                     (float)msg.arg1 / (float)1000.0,
   3524                                                     UserHandle.USER_CURRENT);
   3525                     break;
   3526 
   3527                 case MSG_PERSIST_MASTER_VOLUME_MUTE:
   3528                     if (mUseFixedVolume) {
   3529                         return;
   3530                     }
   3531                     Settings.System.putIntForUser(mContentResolver,
   3532                                                  Settings.System.VOLUME_MASTER_MUTE,
   3533                                                  msg.arg1,
   3534                                                  UserHandle.USER_CURRENT);
   3535                     break;
   3536 
   3537                 case MSG_PERSIST_RINGER_MODE:
   3538                     // note that the value persisted is the current ringer mode, not the
   3539                     // value of ringer mode as of the time the request was made to persist
   3540                     persistRingerMode(getRingerMode());
   3541                     break;
   3542 
   3543                 case MSG_MEDIA_SERVER_DIED:
   3544                     if (AudioSystem.checkAudioFlinger() != AudioSystem.AUDIO_STATUS_OK) {
   3545                         Log.e(TAG, "Media server died.");
   3546                         sendMsg(mAudioHandler, MSG_MEDIA_SERVER_DIED, SENDMSG_NOOP, 0, 0,
   3547                                 null, 500);
   3548                         break;
   3549                     }
   3550                     Log.e(TAG, "Media server started.");
   3551 
   3552                     // indicate to audio HAL that we start the reconfiguration phase after a media
   3553                     // server crash
   3554                     // Note that we only execute this when the media server
   3555                     // process restarts after a crash, not the first time it is started.
   3556                     AudioSystem.setParameters("restarting=true");
   3557 
   3558                     readAndSetLowRamDevice();
   3559 
   3560                     // Restore device connection states
   3561                     synchronized (mConnectedDevices) {
   3562                         Set set = mConnectedDevices.entrySet();
   3563                         Iterator i = set.iterator();
   3564                         while (i.hasNext()) {
   3565                             Map.Entry device = (Map.Entry)i.next();
   3566                             AudioSystem.setDeviceConnectionState(
   3567                                                             ((Integer)device.getKey()).intValue(),
   3568                                                             AudioSystem.DEVICE_STATE_AVAILABLE,
   3569                                                             (String)device.getValue());
   3570                         }
   3571                     }
   3572                     // Restore call state
   3573                     AudioSystem.setPhoneState(mMode);
   3574 
   3575                     // Restore forced usage for communcations and record
   3576                     AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm);
   3577                     AudioSystem.setForceUse(AudioSystem.FOR_RECORD, mForcedUseForComm);
   3578                     AudioSystem.setForceUse(AudioSystem.FOR_SYSTEM, mCameraSoundForced ?
   3579                                     AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE);
   3580 
   3581                     // Restore stream volumes
   3582                     int numStreamTypes = AudioSystem.getNumStreamTypes();
   3583                     for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
   3584                         VolumeStreamState streamState = mStreamStates[streamType];
   3585                         AudioSystem.initStreamVolume(streamType, 0, (streamState.mIndexMax + 5) / 10);
   3586 
   3587                         streamState.applyAllVolumes();
   3588                     }
   3589 
   3590                     // Restore ringer mode
   3591                     setRingerModeInt(getRingerMode(), false);
   3592 
   3593                     // Restore master volume
   3594                     restoreMasterVolume();
   3595 
   3596                     // Reset device orientation (if monitored for this device)
   3597                     if (mMonitorOrientation) {
   3598                         setOrientationForAudioSystem();
   3599                     }
   3600                     if (mMonitorRotation) {
   3601                         setRotationForAudioSystem();
   3602                     }
   3603 
   3604                     synchronized (mBluetoothA2dpEnabledLock) {
   3605                         AudioSystem.setForceUse(AudioSystem.FOR_MEDIA,
   3606                                 mBluetoothA2dpEnabled ?
   3607                                         AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP);
   3608                     }
   3609 
   3610                     synchronized (mSettingsLock) {
   3611                         AudioSystem.setForceUse(AudioSystem.FOR_DOCK,
   3612                                 mDockAudioMediaEnabled ?
   3613                                         AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE);
   3614                     }
   3615 
   3616                     // indicate the end of reconfiguration phase to audio HAL
   3617                     AudioSystem.setParameters("restarting=false");
   3618                     break;
   3619 
   3620                 case MSG_UNLOAD_SOUND_EFFECTS:
   3621                     onUnloadSoundEffects();
   3622                     break;
   3623 
   3624                 case MSG_LOAD_SOUND_EFFECTS:
   3625                     //FIXME: onLoadSoundEffects() should be executed in a separate thread as it
   3626                     // can take several dozens of milliseconds to complete
   3627                     boolean loaded = onLoadSoundEffects();
   3628                     if (msg.obj != null) {
   3629                         LoadSoundEffectReply reply = (LoadSoundEffectReply)msg.obj;
   3630                         synchronized (reply) {
   3631                             reply.mStatus = loaded ? 0 : -1;
   3632                             reply.notify();
   3633                         }
   3634                     }
   3635                     break;
   3636 
   3637                 case MSG_PLAY_SOUND_EFFECT:
   3638                     onPlaySoundEffect(msg.arg1, msg.arg2);
   3639                     break;
   3640 
   3641                 case MSG_BTA2DP_DOCK_TIMEOUT:
   3642                     // msg.obj  == address of BTA2DP device
   3643                     synchronized (mConnectedDevices) {
   3644                         makeA2dpDeviceUnavailableNow( (String) msg.obj );
   3645                     }
   3646                     break;
   3647 
   3648                 case MSG_SET_FORCE_USE:
   3649                 case MSG_SET_FORCE_BT_A2DP_USE:
   3650                     setForceUse(msg.arg1, msg.arg2);
   3651                     break;
   3652 
   3653                 case MSG_BT_HEADSET_CNCT_FAILED:
   3654                     resetBluetoothSco();
   3655                     break;
   3656 
   3657                 case MSG_SET_WIRED_DEVICE_CONNECTION_STATE:
   3658                     onSetWiredDeviceConnectionState(msg.arg1, msg.arg2, (String)msg.obj);
   3659                     mAudioEventWakeLock.release();
   3660                     break;
   3661 
   3662                 case MSG_SET_A2DP_CONNECTION_STATE:
   3663                     onSetA2dpConnectionState((BluetoothDevice)msg.obj, msg.arg1);
   3664                     mAudioEventWakeLock.release();
   3665                     break;
   3666 
   3667                 case MSG_REPORT_NEW_ROUTES: {
   3668                     int N = mRoutesObservers.beginBroadcast();
   3669                     if (N > 0) {
   3670                         AudioRoutesInfo routes;
   3671                         synchronized (mCurAudioRoutes) {
   3672                             routes = new AudioRoutesInfo(mCurAudioRoutes);
   3673                         }
   3674                         while (N > 0) {
   3675                             N--;
   3676                             IAudioRoutesObserver obs = mRoutesObservers.getBroadcastItem(N);
   3677                             try {
   3678                                 obs.dispatchAudioRoutesChanged(routes);
   3679                             } catch (RemoteException e) {
   3680                             }
   3681                         }
   3682                     }
   3683                     mRoutesObservers.finishBroadcast();
   3684                     break;
   3685                 }
   3686 
   3687                 case MSG_CHECK_MUSIC_ACTIVE:
   3688                     onCheckMusicActive();
   3689                     break;
   3690 
   3691                 case MSG_BROADCAST_AUDIO_BECOMING_NOISY:
   3692                     onSendBecomingNoisyIntent();
   3693                     break;
   3694 
   3695                 case MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED:
   3696                 case MSG_CONFIGURE_SAFE_MEDIA_VOLUME:
   3697                     onConfigureSafeVolume((msg.what == MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED));
   3698                     break;
   3699                 case MSG_PERSIST_SAFE_VOLUME_STATE:
   3700                     onPersistSafeVolumeState(msg.arg1);
   3701                     break;
   3702 
   3703                 case MSG_BROADCAST_BT_CONNECTION_STATE:
   3704                     onBroadcastScoConnectionState(msg.arg1);
   3705                     break;
   3706             }
   3707         }
   3708     }
   3709 
   3710     private class SettingsObserver extends ContentObserver {
   3711 
   3712         SettingsObserver() {
   3713             super(new Handler());
   3714             mContentResolver.registerContentObserver(Settings.System.getUriFor(
   3715                 Settings.System.MODE_RINGER_STREAMS_AFFECTED), false, this);
   3716             mContentResolver.registerContentObserver(Settings.Global.getUriFor(
   3717                 Settings.Global.DOCK_AUDIO_MEDIA_ENABLED), false, this);
   3718         }
   3719 
   3720         @Override
   3721         public void onChange(boolean selfChange) {
   3722             super.onChange(selfChange);
   3723             // FIXME This synchronized is not necessary if mSettingsLock only protects mRingerMode.
   3724             //       However there appear to be some missing locks around mRingerModeMutedStreams
   3725             //       and mRingerModeAffectedStreams, so will leave this synchronized for now.
   3726             //       mRingerModeMutedStreams and mMuteAffectedStreams are safe (only accessed once).
   3727             synchronized (mSettingsLock) {
   3728                 if (updateRingerModeAffectedStreams()) {
   3729                     /*
   3730                      * Ensure all stream types that should be affected by ringer mode
   3731                      * are in the proper state.
   3732                      */
   3733                     setRingerModeInt(getRingerMode(), false);
   3734                 }
   3735                 readDockAudioSettings(mContentResolver);
   3736             }
   3737         }
   3738     }
   3739 
   3740     // must be called synchronized on mConnectedDevices
   3741     private void makeA2dpDeviceAvailable(String address) {
   3742         // enable A2DP before notifying A2DP connection to avoid unecessary processing in
   3743         // audio policy manager
   3744         VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC];
   3745         sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE,
   3746                 AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0, streamState, 0);
   3747         setBluetoothA2dpOnInt(true);
   3748         AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
   3749                 AudioSystem.DEVICE_STATE_AVAILABLE,
   3750                 address);
   3751         // Reset A2DP suspend state each time a new sink is connected
   3752         AudioSystem.setParameters("A2dpSuspended=false");
   3753         mConnectedDevices.put( new Integer(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP),
   3754                 address);
   3755     }
   3756 
   3757     private void onSendBecomingNoisyIntent() {
   3758         sendBroadcastToAll(new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY));
   3759     }
   3760 
   3761     // must be called synchronized on mConnectedDevices
   3762     private void makeA2dpDeviceUnavailableNow(String address) {
   3763         synchronized (mA2dpAvrcpLock) {
   3764             mAvrcpAbsVolSupported = false;
   3765         }
   3766         AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
   3767                 AudioSystem.DEVICE_STATE_UNAVAILABLE,
   3768                 address);
   3769         mConnectedDevices.remove(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
   3770     }
   3771 
   3772     // must be called synchronized on mConnectedDevices
   3773     private void makeA2dpDeviceUnavailableLater(String address) {
   3774         // prevent any activity on the A2DP audio output to avoid unwanted
   3775         // reconnection of the sink.
   3776         AudioSystem.setParameters("A2dpSuspended=true");
   3777         // the device will be made unavailable later, so consider it disconnected right away
   3778         mConnectedDevices.remove(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
   3779         // send the delayed message to make the device unavailable later
   3780         Message msg = mAudioHandler.obtainMessage(MSG_BTA2DP_DOCK_TIMEOUT, address);
   3781         mAudioHandler.sendMessageDelayed(msg, BTA2DP_DOCK_TIMEOUT_MILLIS);
   3782 
   3783     }
   3784 
   3785     // must be called synchronized on mConnectedDevices
   3786     private void cancelA2dpDeviceTimeout() {
   3787         mAudioHandler.removeMessages(MSG_BTA2DP_DOCK_TIMEOUT);
   3788     }
   3789 
   3790     // must be called synchronized on mConnectedDevices
   3791     private boolean hasScheduledA2dpDockTimeout() {
   3792         return mAudioHandler.hasMessages(MSG_BTA2DP_DOCK_TIMEOUT);
   3793     }
   3794 
   3795     private void onSetA2dpConnectionState(BluetoothDevice btDevice, int state)
   3796     {
   3797         if (DEBUG_VOL) Log.d(TAG, "onSetA2dpConnectionState btDevice="+btDevice+" state="+state);
   3798         if (btDevice == null) {
   3799             return;
   3800         }
   3801         String address = btDevice.getAddress();
   3802         if (!BluetoothAdapter.checkBluetoothAddress(address)) {
   3803             address = "";
   3804         }
   3805 
   3806         synchronized (mConnectedDevices) {
   3807             boolean isConnected =
   3808                 (mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) &&
   3809                  mConnectedDevices.get(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP).equals(address));
   3810 
   3811             if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
   3812                 if (btDevice.isBluetoothDock()) {
   3813                     if (state == BluetoothProfile.STATE_DISCONNECTED) {
   3814                         // introduction of a delay for transient disconnections of docks when
   3815                         // power is rapidly turned off/on, this message will be canceled if
   3816                         // we reconnect the dock under a preset delay
   3817                         makeA2dpDeviceUnavailableLater(address);
   3818                         // the next time isConnected is evaluated, it will be false for the dock
   3819                     }
   3820                 } else {
   3821                     makeA2dpDeviceUnavailableNow(address);
   3822                 }
   3823                 synchronized (mCurAudioRoutes) {
   3824                     if (mCurAudioRoutes.mBluetoothName != null) {
   3825                         mCurAudioRoutes.mBluetoothName = null;
   3826                         sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES,
   3827                                 SENDMSG_NOOP, 0, 0, null, 0);
   3828                     }
   3829                 }
   3830             } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
   3831                 if (btDevice.isBluetoothDock()) {
   3832                     // this could be a reconnection after a transient disconnection
   3833                     cancelA2dpDeviceTimeout();
   3834                     mDockAddress = address;
   3835                 } else {
   3836                     // this could be a connection of another A2DP device before the timeout of
   3837                     // a dock: cancel the dock timeout, and make the dock unavailable now
   3838                     if(hasScheduledA2dpDockTimeout()) {
   3839                         cancelA2dpDeviceTimeout();
   3840                         makeA2dpDeviceUnavailableNow(mDockAddress);
   3841                     }
   3842                 }
   3843                 makeA2dpDeviceAvailable(address);
   3844                 synchronized (mCurAudioRoutes) {
   3845                     String name = btDevice.getAliasName();
   3846                     if (!TextUtils.equals(mCurAudioRoutes.mBluetoothName, name)) {
   3847                         mCurAudioRoutes.mBluetoothName = name;
   3848                         sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES,
   3849                                 SENDMSG_NOOP, 0, 0, null, 0);
   3850                     }
   3851                 }
   3852             }
   3853         }
   3854     }
   3855 
   3856     public void avrcpSupportsAbsoluteVolume(String address, boolean support) {
   3857         // address is not used for now, but may be used when multiple a2dp devices are supported
   3858         synchronized (mA2dpAvrcpLock) {
   3859             mAvrcpAbsVolSupported = support;
   3860             sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE,
   3861                     AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0,
   3862                     mStreamStates[AudioSystem.STREAM_MUSIC], 0);
   3863             sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE,
   3864                     AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0,
   3865                     mStreamStates[AudioSystem.STREAM_RING], 0);
   3866         }
   3867     }
   3868 
   3869     private boolean handleDeviceConnection(boolean connected, int device, String params) {
   3870         synchronized (mConnectedDevices) {
   3871             boolean isConnected = (mConnectedDevices.containsKey(device) &&
   3872                     (params.isEmpty() || mConnectedDevices.get(device).equals(params)));
   3873 
   3874             if (isConnected && !connected) {
   3875                 AudioSystem.setDeviceConnectionState(device,
   3876                                               AudioSystem.DEVICE_STATE_UNAVAILABLE,
   3877                                               mConnectedDevices.get(device));
   3878                  mConnectedDevices.remove(device);
   3879                  return true;
   3880             } else if (!isConnected && connected) {
   3881                  AudioSystem.setDeviceConnectionState(device,
   3882                                                       AudioSystem.DEVICE_STATE_AVAILABLE,
   3883                                                       params);
   3884                  mConnectedDevices.put(new Integer(device), params);
   3885                  return true;
   3886             }
   3887         }
   3888         return false;
   3889     }
   3890 
   3891     // Devices which removal triggers intent ACTION_AUDIO_BECOMING_NOISY. The intent is only
   3892     // sent if none of these devices is connected.
   3893     int mBecomingNoisyIntentDevices =
   3894             AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE |
   3895             AudioSystem.DEVICE_OUT_ALL_A2DP | AudioSystem.DEVICE_OUT_AUX_DIGITAL |
   3896             AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET | AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET |
   3897             AudioSystem.DEVICE_OUT_ALL_USB;
   3898 
   3899     // must be called before removing the device from mConnectedDevices
   3900     private int checkSendBecomingNoisyIntent(int device, int state) {
   3901         int delay = 0;
   3902         if ((state == 0) && ((device & mBecomingNoisyIntentDevices) != 0)) {
   3903             int devices = 0;
   3904             for (int dev : mConnectedDevices.keySet()) {
   3905                 if ((dev & mBecomingNoisyIntentDevices) != 0) {
   3906                    devices |= dev;
   3907                 }
   3908             }
   3909             if (devices == device) {
   3910                 sendMsg(mAudioHandler,
   3911                         MSG_BROADCAST_AUDIO_BECOMING_NOISY,
   3912                         SENDMSG_REPLACE,
   3913                         0,
   3914                         0,
   3915                         null,
   3916                         0);
   3917                 delay = 1000;
   3918             }
   3919         }
   3920 
   3921         if (mAudioHandler.hasMessages(MSG_SET_A2DP_CONNECTION_STATE) ||
   3922                 mAudioHandler.hasMessages(MSG_SET_WIRED_DEVICE_CONNECTION_STATE)) {
   3923             delay = 1000;
   3924         }
   3925         return delay;
   3926     }
   3927 
   3928     private void sendDeviceConnectionIntent(int device, int state, String name)
   3929     {
   3930         Intent intent = new Intent();
   3931 
   3932         intent.putExtra("state", state);
   3933         intent.putExtra("name", name);
   3934         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
   3935 
   3936         int connType = 0;
   3937 
   3938         if (device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) {
   3939             connType = AudioRoutesInfo.MAIN_HEADSET;
   3940             intent.setAction(Intent.ACTION_HEADSET_PLUG);
   3941             intent.putExtra("microphone", 1);
   3942         } else if (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE) {
   3943             connType = AudioRoutesInfo.MAIN_HEADPHONES;
   3944             intent.setAction(Intent.ACTION_HEADSET_PLUG);
   3945             intent.putExtra("microphone", 0);
   3946         } else if (device == AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET) {
   3947             connType = AudioRoutesInfo.MAIN_DOCK_SPEAKERS;
   3948             intent.setAction(Intent.ACTION_ANALOG_AUDIO_DOCK_PLUG);
   3949         } else if (device == AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET) {
   3950             connType = AudioRoutesInfo.MAIN_DOCK_SPEAKERS;
   3951             intent.setAction(Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG);
   3952         } else if (device == AudioSystem.DEVICE_OUT_AUX_DIGITAL) {
   3953             connType = AudioRoutesInfo.MAIN_HDMI;
   3954             intent.setAction(Intent.ACTION_HDMI_AUDIO_PLUG);
   3955         }
   3956 
   3957         synchronized (mCurAudioRoutes) {
   3958             if (connType != 0) {
   3959                 int newConn = mCurAudioRoutes.mMainType;
   3960                 if (state != 0) {
   3961                     newConn |= connType;
   3962                 } else {
   3963                     newConn &= ~connType;
   3964                 }
   3965                 if (newConn != mCurAudioRoutes.mMainType) {
   3966                     mCurAudioRoutes.mMainType = newConn;
   3967                     sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES,
   3968                             SENDMSG_NOOP, 0, 0, null, 0);
   3969                 }
   3970             }
   3971         }
   3972 
   3973         final long ident = Binder.clearCallingIdentity();
   3974         try {
   3975             ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.USER_ALL);
   3976         } finally {
   3977             Binder.restoreCallingIdentity(ident);
   3978         }
   3979     }
   3980 
   3981     private void onSetWiredDeviceConnectionState(int device, int state, String name)
   3982     {
   3983         synchronized (mConnectedDevices) {
   3984             if ((state == 0) && ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) ||
   3985                     (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE))) {
   3986                 setBluetoothA2dpOnInt(true);
   3987             }
   3988             boolean isUsb = ((device & AudioSystem.DEVICE_OUT_ALL_USB) != 0);
   3989             handleDeviceConnection((state == 1), device, (isUsb ? name : ""));
   3990             if (state != 0) {
   3991                 if ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) ||
   3992                     (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE)) {
   3993                     setBluetoothA2dpOnInt(false);
   3994                 }
   3995                 if ((device & mSafeMediaVolumeDevices) != 0) {
   3996                     sendMsg(mAudioHandler,
   3997                             MSG_CHECK_MUSIC_ACTIVE,
   3998                             SENDMSG_REPLACE,
   3999                             0,
   4000                             0,
   4001                             null,
   4002                             MUSIC_ACTIVE_POLL_PERIOD_MS);
   4003                 }
   4004             }
   4005             if (!isUsb) {
   4006                 sendDeviceConnectionIntent(device, state, name);
   4007             }
   4008         }
   4009     }
   4010 
   4011     /* cache of the address of the last dock the device was connected to */
   4012     private String mDockAddress;
   4013 
   4014     /**
   4015      * Receiver for misc intent broadcasts the Phone app cares about.
   4016      */
   4017     private class AudioServiceBroadcastReceiver extends BroadcastReceiver {
   4018         @Override
   4019         public void onReceive(Context context, Intent intent) {
   4020             String action = intent.getAction();
   4021             int device;
   4022             int state;
   4023 
   4024             if (action.equals(Intent.ACTION_DOCK_EVENT)) {
   4025                 int dockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
   4026                         Intent.EXTRA_DOCK_STATE_UNDOCKED);
   4027                 int config;
   4028                 switch (dockState) {
   4029                     case Intent.EXTRA_DOCK_STATE_DESK:
   4030                         config = AudioSystem.FORCE_BT_DESK_DOCK;
   4031                         break;
   4032                     case Intent.EXTRA_DOCK_STATE_CAR:
   4033                         config = AudioSystem.FORCE_BT_CAR_DOCK;
   4034                         break;
   4035                     case Intent.EXTRA_DOCK_STATE_LE_DESK:
   4036                         config = AudioSystem.FORCE_ANALOG_DOCK;
   4037                         break;
   4038                     case Intent.EXTRA_DOCK_STATE_HE_DESK:
   4039                         config = AudioSystem.FORCE_DIGITAL_DOCK;
   4040                         break;
   4041                     case Intent.EXTRA_DOCK_STATE_UNDOCKED:
   4042                     default:
   4043                         config = AudioSystem.FORCE_NONE;
   4044                 }
   4045                 // Low end docks have a menu to enable or disable audio
   4046                 // (see mDockAudioMediaEnabled)
   4047                 if (!((dockState == Intent.EXTRA_DOCK_STATE_LE_DESK) ||
   4048                       ((dockState == Intent.EXTRA_DOCK_STATE_UNDOCKED) &&
   4049                        (mDockState == Intent.EXTRA_DOCK_STATE_LE_DESK)))) {
   4050                     AudioSystem.setForceUse(AudioSystem.FOR_DOCK, config);
   4051                 }
   4052                 mDockState = dockState;
   4053             } else if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) {
   4054                 state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE,
   4055                                                BluetoothProfile.STATE_DISCONNECTED);
   4056                 device = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO;
   4057                 String address = null;
   4058 
   4059                 BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
   4060                 if (btDevice == null) {
   4061                     return;
   4062                 }
   4063 
   4064                 address = btDevice.getAddress();
   4065                 BluetoothClass btClass = btDevice.getBluetoothClass();
   4066                 if (btClass != null) {
   4067                     switch (btClass.getDeviceClass()) {
   4068                     case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET:
   4069                     case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE:
   4070                         device = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
   4071                         break;
   4072                     case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO:
   4073                         device = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
   4074                         break;
   4075                     }
   4076                 }
   4077 
   4078                 if (!BluetoothAdapter.checkBluetoothAddress(address)) {
   4079                     address = "";
   4080                 }
   4081 
   4082                 boolean connected = (state == BluetoothProfile.STATE_CONNECTED);
   4083                 if (handleDeviceConnection(connected, device, address)) {
   4084                     synchronized (mScoClients) {
   4085                         if (connected) {
   4086                             mBluetoothHeadsetDevice = btDevice;
   4087                         } else {
   4088                             mBluetoothHeadsetDevice = null;
   4089                             resetBluetoothSco();
   4090                         }
   4091                     }
   4092                 }
   4093             } else if (action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) ||
   4094                            action.equals(Intent.ACTION_USB_AUDIO_DEVICE_PLUG)) {
   4095                 state = intent.getIntExtra("state", 0);
   4096                 int alsaCard = intent.getIntExtra("card", -1);
   4097                 int alsaDevice = intent.getIntExtra("device", -1);
   4098                 String params = (alsaCard == -1 && alsaDevice == -1 ? ""
   4099                                     : "card=" + alsaCard + ";device=" + alsaDevice);
   4100                 device = action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) ?
   4101                         AudioSystem.DEVICE_OUT_USB_ACCESSORY : AudioSystem.DEVICE_OUT_USB_DEVICE;
   4102                 Log.v(TAG, "Broadcast Receiver: Got "
   4103                         + (action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) ?
   4104                               "ACTION_USB_AUDIO_ACCESSORY_PLUG" : "ACTION_USB_AUDIO_DEVICE_PLUG")
   4105                         + ", state = " + state + ", card: " + alsaCard + ", device: " + alsaDevice);
   4106                 setWiredDeviceConnectionState(device, state, params);
   4107             } else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
   4108                 boolean broadcast = false;
   4109                 int scoAudioState = AudioManager.SCO_AUDIO_STATE_ERROR;
   4110                 synchronized (mScoClients) {
   4111                     int btState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
   4112                     // broadcast intent if the connection was initated by AudioService
   4113                     if (!mScoClients.isEmpty() &&
   4114                             (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL ||
   4115                              mScoAudioState == SCO_STATE_ACTIVATE_REQ ||
   4116                              mScoAudioState == SCO_STATE_DEACTIVATE_REQ)) {
   4117                         broadcast = true;
   4118                     }
   4119                     switch (btState) {
   4120                     case BluetoothHeadset.STATE_AUDIO_CONNECTED:
   4121                         scoAudioState = AudioManager.SCO_AUDIO_STATE_CONNECTED;
   4122                         if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL &&
   4123                             mScoAudioState != SCO_STATE_DEACTIVATE_REQ &&
   4124                             mScoAudioState != SCO_STATE_DEACTIVATE_EXT_REQ) {
   4125                             mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL;
   4126                         }
   4127                         break;
   4128                     case BluetoothHeadset.STATE_AUDIO_DISCONNECTED:
   4129                         scoAudioState = AudioManager.SCO_AUDIO_STATE_DISCONNECTED;
   4130                         mScoAudioState = SCO_STATE_INACTIVE;
   4131                         clearAllScoClients(0, false);
   4132                         break;
   4133                     case BluetoothHeadset.STATE_AUDIO_CONNECTING:
   4134                         if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL &&
   4135                             mScoAudioState != SCO_STATE_DEACTIVATE_REQ &&
   4136                             mScoAudioState != SCO_STATE_DEACTIVATE_EXT_REQ) {
   4137                             mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL;
   4138                         }
   4139                     default:
   4140                         // do not broadcast CONNECTING or invalid state
   4141                         broadcast = false;
   4142                         break;
   4143                     }
   4144                 }
   4145                 if (broadcast) {
   4146                     broadcastScoConnectionState(scoAudioState);
   4147                     //FIXME: this is to maintain compatibility with deprecated intent
   4148                     // AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. Remove when appropriate.
   4149                     Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED);
   4150                     newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, scoAudioState);
   4151                     sendStickyBroadcastToAll(newIntent);
   4152                 }
   4153             } else if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
   4154                 mBootCompleted = true;
   4155                 sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE,
   4156                         0, 0, null, 0);
   4157 
   4158                 mKeyguardManager =
   4159                         (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
   4160                 mScoConnectionState = AudioManager.SCO_AUDIO_STATE_ERROR;
   4161                 resetBluetoothSco();
   4162                 getBluetoothHeadset();
   4163                 //FIXME: this is to maintain compatibility with deprecated intent
   4164                 // AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. Remove when appropriate.
   4165                 Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED);
   4166                 newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE,
   4167                         AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
   4168                 sendStickyBroadcastToAll(newIntent);
   4169 
   4170                 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
   4171                 if (adapter != null) {
   4172                     adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
   4173                                             BluetoothProfile.A2DP);
   4174                 }
   4175 
   4176                 sendMsg(mAudioHandler,
   4177                         MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED,
   4178                         SENDMSG_REPLACE,
   4179                         0,
   4180                         0,
   4181                         null,
   4182                         SAFE_VOLUME_CONFIGURE_TIMEOUT_MS);
   4183             } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
   4184                 AudioSystem.setParameters("screen_state=on");
   4185             } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
   4186                 AudioSystem.setParameters("screen_state=off");
   4187             } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
   4188                 handleConfigurationChanged(context);
   4189             } else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
   4190                 // attempt to stop music playback for background user
   4191                 sendMsg(mAudioHandler,
   4192                         MSG_BROADCAST_AUDIO_BECOMING_NOISY,
   4193                         SENDMSG_REPLACE,
   4194                         0,
   4195                         0,
   4196                         null,
   4197                         0);
   4198                 // the current audio focus owner is no longer valid
   4199                 mMediaFocusControl.discardAudioFocusOwner();
   4200 
   4201                 // load volume settings for new user
   4202                 readAudioSettings(true /*userSwitch*/);
   4203                 // preserve STREAM_MUSIC volume from one user to the next.
   4204                 sendMsg(mAudioHandler,
   4205                         MSG_SET_ALL_VOLUMES,
   4206                         SENDMSG_QUEUE,
   4207                         0,
   4208                         0,
   4209                         mStreamStates[AudioSystem.STREAM_MUSIC], 0);
   4210             }
   4211         }
   4212     }
   4213 
   4214     //==========================================================================================
   4215     // RemoteControlDisplay / RemoteControlClient / Remote info
   4216     //==========================================================================================
   4217     public boolean registerRemoteController(IRemoteControlDisplay rcd, int w, int h,
   4218             ComponentName listenerComp) {
   4219         return mMediaFocusControl.registerRemoteController(rcd, w, h, listenerComp);
   4220     }
   4221 
   4222     public boolean registerRemoteControlDisplay(IRemoteControlDisplay rcd, int w, int h) {
   4223         return mMediaFocusControl.registerRemoteControlDisplay(rcd, w, h);
   4224     }
   4225 
   4226     public void unregisterRemoteControlDisplay(IRemoteControlDisplay rcd) {
   4227         mMediaFocusControl.unregisterRemoteControlDisplay(rcd);
   4228     }
   4229 
   4230     public void remoteControlDisplayUsesBitmapSize(IRemoteControlDisplay rcd, int w, int h) {
   4231         mMediaFocusControl.remoteControlDisplayUsesBitmapSize(rcd, w, h);
   4232     }
   4233 
   4234     public void remoteControlDisplayWantsPlaybackPositionSync(IRemoteControlDisplay rcd,
   4235             boolean wantsSync) {
   4236         mMediaFocusControl.remoteControlDisplayWantsPlaybackPositionSync(rcd, wantsSync);
   4237     }
   4238 
   4239     public void registerMediaButtonEventReceiverForCalls(ComponentName c) {
   4240         mMediaFocusControl.registerMediaButtonEventReceiverForCalls(c);
   4241     }
   4242 
   4243     public void unregisterMediaButtonEventReceiverForCalls() {
   4244         mMediaFocusControl.unregisterMediaButtonEventReceiverForCalls();
   4245     }
   4246 
   4247     public void registerMediaButtonIntent(PendingIntent pi, ComponentName c, IBinder token) {
   4248         mMediaFocusControl.registerMediaButtonIntent(pi, c, token);
   4249     }
   4250 
   4251     public void unregisterMediaButtonIntent(PendingIntent pi) {
   4252         mMediaFocusControl.unregisterMediaButtonIntent(pi);
   4253     }
   4254 
   4255     public int registerRemoteControlClient(PendingIntent mediaIntent,
   4256             IRemoteControlClient rcClient, String callingPckg) {
   4257         return mMediaFocusControl.registerRemoteControlClient(mediaIntent, rcClient, callingPckg);
   4258     }
   4259 
   4260     public void unregisterRemoteControlClient(PendingIntent mediaIntent,
   4261             IRemoteControlClient rcClient) {
   4262         mMediaFocusControl.unregisterRemoteControlClient(mediaIntent, rcClient);
   4263     }
   4264 
   4265     public void setRemoteControlClientPlaybackPosition(int generationId, long timeMs) {
   4266         mMediaFocusControl.setRemoteControlClientPlaybackPosition(generationId, timeMs);
   4267     }
   4268 
   4269     public void updateRemoteControlClientMetadata(int generationId, int key, Rating value) {
   4270         mMediaFocusControl.updateRemoteControlClientMetadata(generationId, key, value);
   4271     }
   4272 
   4273     public void registerRemoteVolumeObserverForRcc(int rccId, IRemoteVolumeObserver rvo) {
   4274         mMediaFocusControl.registerRemoteVolumeObserverForRcc(rccId, rvo);
   4275     }
   4276 
   4277     public int getRemoteStreamVolume() {
   4278         return mMediaFocusControl.getRemoteStreamVolume();
   4279     }
   4280 
   4281     public int getRemoteStreamMaxVolume() {
   4282         return mMediaFocusControl.getRemoteStreamMaxVolume();
   4283     }
   4284 
   4285     public void setRemoteStreamVolume(int index) {
   4286         mMediaFocusControl.setRemoteStreamVolume(index);
   4287     }
   4288 
   4289     public void setPlaybackStateForRcc(int rccId, int state, long timeMs, float speed) {
   4290         mMediaFocusControl.setPlaybackStateForRcc(rccId, state, timeMs, speed);
   4291     }
   4292 
   4293     public void setPlaybackInfoForRcc(int rccId, int what, int value) {
   4294         mMediaFocusControl.setPlaybackInfoForRcc(rccId, what, value);
   4295     }
   4296 
   4297     public void dispatchMediaKeyEvent(KeyEvent keyEvent) {
   4298         mMediaFocusControl.dispatchMediaKeyEvent(keyEvent);
   4299     }
   4300 
   4301     public void dispatchMediaKeyEventUnderWakelock(KeyEvent keyEvent) {
   4302         mMediaFocusControl.dispatchMediaKeyEventUnderWakelock(keyEvent);
   4303     }
   4304 
   4305     //==========================================================================================
   4306     // Audio Focus
   4307     //==========================================================================================
   4308     public int requestAudioFocus(int mainStreamType, int durationHint, IBinder cb,
   4309             IAudioFocusDispatcher fd, String clientId, String callingPackageName) {
   4310         return mMediaFocusControl.requestAudioFocus(mainStreamType, durationHint, cb, fd,
   4311                 clientId, callingPackageName);
   4312     }
   4313 
   4314     public int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId) {
   4315         return mMediaFocusControl.abandonAudioFocus(fd, clientId);
   4316     }
   4317 
   4318     public void unregisterAudioFocusClient(String clientId) {
   4319         mMediaFocusControl.unregisterAudioFocusClient(clientId);
   4320     }
   4321 
   4322     public int getCurrentAudioFocus() {
   4323         return mMediaFocusControl.getCurrentAudioFocus();
   4324     }
   4325 
   4326     //==========================================================================================
   4327     // Device orientation
   4328     //==========================================================================================
   4329     /**
   4330      * Handles device configuration changes that may map to a change in the orientation
   4331      * or orientation.
   4332      * Monitoring orientation and rotation is optional, and is defined by the definition and value
   4333      * of the "ro.audio.monitorOrientation" and "ro.audio.monitorRotation" system properties.
   4334      */
   4335     private void handleConfigurationChanged(Context context) {
   4336         try {
   4337             // reading new orientation "safely" (i.e. under try catch) in case anything
   4338             // goes wrong when obtaining resources and configuration
   4339             Configuration config = context.getResources().getConfiguration();
   4340             // TODO merge rotation and orientation
   4341             if (mMonitorOrientation) {
   4342                 int newOrientation = config.orientation;
   4343                 if (newOrientation != mDeviceOrientation) {
   4344                     mDeviceOrientation = newOrientation;
   4345                     setOrientationForAudioSystem();
   4346                 }
   4347             }
   4348             if (mMonitorRotation) {
   4349                 int newRotation = ((WindowManager) context.getSystemService(
   4350                         Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
   4351                 if (newRotation != mDeviceRotation) {
   4352                     mDeviceRotation = newRotation;
   4353                     setRotationForAudioSystem();
   4354                 }
   4355             }
   4356             sendMsg(mAudioHandler,
   4357                     MSG_CONFIGURE_SAFE_MEDIA_VOLUME,
   4358                     SENDMSG_REPLACE,
   4359                     0,
   4360                     0,
   4361                     null,
   4362                     0);
   4363 
   4364             boolean cameraSoundForced = mContext.getResources().getBoolean(
   4365                     com.android.internal.R.bool.config_camera_sound_forced);
   4366             synchronized (mSettingsLock) {
   4367                 synchronized (mCameraSoundForced) {
   4368                     if (cameraSoundForced != mCameraSoundForced) {
   4369                         mCameraSoundForced = cameraSoundForced;
   4370 
   4371                         VolumeStreamState s = mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED];
   4372                         if (cameraSoundForced) {
   4373                             s.setAllIndexesToMax();
   4374                             mRingerModeAffectedStreams &=
   4375                                     ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
   4376                         } else {
   4377                             s.setAllIndexes(mStreamStates[AudioSystem.STREAM_SYSTEM]);
   4378                             mRingerModeAffectedStreams |=
   4379                                     (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
   4380                         }
   4381                         // take new state into account for streams muted by ringer mode
   4382                         setRingerModeInt(getRingerMode(), false);
   4383 
   4384                         sendMsg(mAudioHandler,
   4385                                 MSG_SET_FORCE_USE,
   4386                                 SENDMSG_QUEUE,
   4387                                 AudioSystem.FOR_SYSTEM,
   4388                                 cameraSoundForced ?
   4389                                         AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE,
   4390                                 null,
   4391                                 0);
   4392 
   4393                         sendMsg(mAudioHandler,
   4394                                 MSG_SET_ALL_VOLUMES,
   4395                                 SENDMSG_QUEUE,
   4396                                 0,
   4397                                 0,
   4398                                 mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED], 0);
   4399                     }
   4400                 }
   4401             }
   4402             mVolumePanel.setLayoutDirection(config.getLayoutDirection());
   4403         } catch (Exception e) {
   4404             Log.e(TAG, "Error handling configuration change: ", e);
   4405         }
   4406     }
   4407 
   4408     private void setOrientationForAudioSystem() {
   4409         switch (mDeviceOrientation) {
   4410             case Configuration.ORIENTATION_LANDSCAPE:
   4411                 //Log.i(TAG, "orientation is landscape");
   4412                 AudioSystem.setParameters("orientation=landscape");
   4413                 break;
   4414             case Configuration.ORIENTATION_PORTRAIT:
   4415                 //Log.i(TAG, "orientation is portrait");
   4416                 AudioSystem.setParameters("orientation=portrait");
   4417                 break;
   4418             case Configuration.ORIENTATION_SQUARE:
   4419                 //Log.i(TAG, "orientation is square");
   4420                 AudioSystem.setParameters("orientation=square");
   4421                 break;
   4422             case Configuration.ORIENTATION_UNDEFINED:
   4423                 //Log.i(TAG, "orientation is undefined");
   4424                 AudioSystem.setParameters("orientation=undefined");
   4425                 break;
   4426             default:
   4427                 Log.e(TAG, "Unknown orientation");
   4428         }
   4429     }
   4430 
   4431     private void setRotationForAudioSystem() {
   4432         switch (mDeviceRotation) {
   4433             case Surface.ROTATION_0:
   4434                 AudioSystem.setParameters("rotation=0");
   4435                 break;
   4436             case Surface.ROTATION_90:
   4437                 AudioSystem.setParameters("rotation=90");
   4438                 break;
   4439             case Surface.ROTATION_180:
   4440                 AudioSystem.setParameters("rotation=180");
   4441                 break;
   4442             case Surface.ROTATION_270:
   4443                 AudioSystem.setParameters("rotation=270");
   4444                 break;
   4445             default:
   4446                 Log.e(TAG, "Unknown device rotation");
   4447         }
   4448     }
   4449 
   4450 
   4451     // Handles request to override default use of A2DP for media.
   4452     public void setBluetoothA2dpOnInt(boolean on) {
   4453         synchronized (mBluetoothA2dpEnabledLock) {
   4454             mBluetoothA2dpEnabled = on;
   4455             mAudioHandler.removeMessages(MSG_SET_FORCE_BT_A2DP_USE);
   4456             AudioSystem.setForceUse(AudioSystem.FOR_MEDIA,
   4457                     mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP);
   4458         }
   4459     }
   4460 
   4461     @Override
   4462     public void setRingtonePlayer(IRingtonePlayer player) {
   4463         mContext.enforceCallingOrSelfPermission(REMOTE_AUDIO_PLAYBACK, null);
   4464         mRingtonePlayer = player;
   4465     }
   4466 
   4467     @Override
   4468     public IRingtonePlayer getRingtonePlayer() {
   4469         return mRingtonePlayer;
   4470     }
   4471 
   4472     @Override
   4473     public AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) {
   4474         synchronized (mCurAudioRoutes) {
   4475             AudioRoutesInfo routes = new AudioRoutesInfo(mCurAudioRoutes);
   4476             mRoutesObservers.register(observer);
   4477             return routes;
   4478         }
   4479     }
   4480 
   4481 
   4482     //==========================================================================================
   4483     // Safe media volume management.
   4484     // MUSIC stream volume level is limited when headphones are connected according to safety
   4485     // regulation. When the user attempts to raise the volume above the limit, a warning is
   4486     // displayed and the user has to acknowlegde before the volume is actually changed.
   4487     // The volume index corresponding to the limit is stored in config_safe_media_volume_index
   4488     // property. Platforms with a different limit must set this property accordingly in their
   4489     // overlay.
   4490     //==========================================================================================
   4491 
   4492     // mSafeMediaVolumeState indicates whether the media volume is limited over headphones.
   4493     // It is SAFE_MEDIA_VOLUME_NOT_CONFIGURED at boot time until a network service is connected
   4494     // or the configure time is elapsed. It is then set to SAFE_MEDIA_VOLUME_ACTIVE or
   4495     // SAFE_MEDIA_VOLUME_DISABLED according to country option. If not SAFE_MEDIA_VOLUME_DISABLED, it
   4496     // can be set to SAFE_MEDIA_VOLUME_INACTIVE by calling AudioService.disableSafeMediaVolume()
   4497     // (when user opts out).
   4498     private final int SAFE_MEDIA_VOLUME_NOT_CONFIGURED = 0;
   4499     private final int SAFE_MEDIA_VOLUME_DISABLED = 1;
   4500     private final int SAFE_MEDIA_VOLUME_INACTIVE = 2;
   4501     private final int SAFE_MEDIA_VOLUME_ACTIVE = 3;
   4502     private Integer mSafeMediaVolumeState;
   4503 
   4504     private int mMcc = 0;
   4505     // mSafeMediaVolumeIndex is the cached value of config_safe_media_volume_index property
   4506     private int mSafeMediaVolumeIndex;
   4507     // mSafeMediaVolumeDevices lists the devices for which safe media volume is enforced,
   4508     private final int mSafeMediaVolumeDevices = AudioSystem.DEVICE_OUT_WIRED_HEADSET |
   4509                                                 AudioSystem.DEVICE_OUT_WIRED_HEADPHONE;
   4510     // mMusicActiveMs is the cumulative time of music activity since safe volume was disabled.
   4511     // When this time reaches UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX, the safe media volume is re-enabled
   4512     // automatically. mMusicActiveMs is rounded to a multiple of MUSIC_ACTIVE_POLL_PERIOD_MS.
   4513     private int mMusicActiveMs;
   4514     private static final int UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX = (20 * 3600 * 1000); // 20 hours
   4515     private static final int MUSIC_ACTIVE_POLL_PERIOD_MS = 60000;  // 1 minute polling interval
   4516     private static final int SAFE_VOLUME_CONFIGURE_TIMEOUT_MS = 30000;  // 30s after boot completed
   4517 
   4518     private void setSafeMediaVolumeEnabled(boolean on) {
   4519         synchronized (mSafeMediaVolumeState) {
   4520             if ((mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_NOT_CONFIGURED) &&
   4521                     (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_DISABLED)) {
   4522                 if (on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE)) {
   4523                     mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE;
   4524                     enforceSafeMediaVolume();
   4525                 } else if (!on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE)) {
   4526                     mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE;
   4527                     mMusicActiveMs = 0;
   4528                     sendMsg(mAudioHandler,
   4529                             MSG_CHECK_MUSIC_ACTIVE,
   4530                             SENDMSG_REPLACE,
   4531                             0,
   4532                             0,
   4533                             null,
   4534                             MUSIC_ACTIVE_POLL_PERIOD_MS);
   4535                 }
   4536             }
   4537         }
   4538     }
   4539 
   4540     private void enforceSafeMediaVolume() {
   4541         VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC];
   4542         int devices = mSafeMediaVolumeDevices;
   4543         int i = 0;
   4544 
   4545         while (devices != 0) {
   4546             int device = 1 << i++;
   4547             if ((device & devices) == 0) {
   4548                 continue;
   4549             }
   4550             int index = streamState.getIndex(device);
   4551             if (index > mSafeMediaVolumeIndex) {
   4552                 streamState.setIndex(mSafeMediaVolumeIndex, device);
   4553                 sendMsg(mAudioHandler,
   4554                         MSG_SET_DEVICE_VOLUME,
   4555                         SENDMSG_QUEUE,
   4556                         device,
   4557                         0,
   4558                         streamState,
   4559                         0);
   4560             }
   4561             devices &= ~device;
   4562         }
   4563     }
   4564 
   4565     private boolean checkSafeMediaVolume(int streamType, int index, int device) {
   4566         synchronized (mSafeMediaVolumeState) {
   4567             if ((mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) &&
   4568                     (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
   4569                     ((device & mSafeMediaVolumeDevices) != 0) &&
   4570                     (index > mSafeMediaVolumeIndex)) {
   4571                 return false;
   4572             }
   4573             return true;
   4574         }
   4575     }
   4576 
   4577     public void disableSafeMediaVolume() {
   4578         synchronized (mSafeMediaVolumeState) {
   4579             setSafeMediaVolumeEnabled(false);
   4580             if (mPendingVolumeCommand != null) {
   4581                 onSetStreamVolume(mPendingVolumeCommand.mStreamType,
   4582                                   mPendingVolumeCommand.mIndex,
   4583                                   mPendingVolumeCommand.mFlags,
   4584                                   mPendingVolumeCommand.mDevice);
   4585                 mPendingVolumeCommand = null;
   4586             }
   4587         }
   4588     }
   4589 
   4590     public int verifyX509CertChain(int numcerts, byte [] chain, String domain, String authType) {
   4591 
   4592         if (DEBUG_CERTS) {
   4593             Log.v(TAG, "java side verify for "
   4594                     + numcerts + " certificates (" + chain.length + " bytes"
   4595                             + ")for "+ domain + "/" + authType);
   4596         }
   4597 
   4598         byte[][] certChain = new byte[numcerts][];
   4599 
   4600         ByteBuffer buf = ByteBuffer.wrap(chain);
   4601         for (int i = 0; i < numcerts; i++) {
   4602             int certlen = buf.getInt();
   4603             if (DEBUG_CERTS) {
   4604                 Log.i(TAG, "cert " + i +": " + certlen);
   4605             }
   4606             certChain[i] = new byte[certlen];
   4607             buf.get(certChain[i]);
   4608         }
   4609 
   4610         try {
   4611             SslError err = CertificateChainValidator.verifyServerCertificates(certChain,
   4612                     domain, authType);
   4613             if (DEBUG_CERTS) {
   4614                 Log.i(TAG, "verified: " + err);
   4615             }
   4616             if (err == null) {
   4617                 return -1;
   4618             } else {
   4619                 return err.getPrimaryError();
   4620             }
   4621         } catch (Exception e) {
   4622             Log.e(TAG, "failed to verify chain: " + e);
   4623         }
   4624         return SslError.SSL_INVALID;
   4625     }
   4626 
   4627 
   4628     //==========================================================================================
   4629     // Camera shutter sound policy.
   4630     // config_camera_sound_forced configuration option in config.xml defines if the camera shutter
   4631     // sound is forced (sound even if the device is in silent mode) or not. This option is false by
   4632     // default and can be overridden by country specific overlay in values-mccXXX/config.xml.
   4633     //==========================================================================================
   4634 
   4635     // cached value of com.android.internal.R.bool.config_camera_sound_forced
   4636     private Boolean mCameraSoundForced;
   4637 
   4638     // called by android.hardware.Camera to populate CameraInfo.canDisableShutterSound
   4639     public boolean isCameraSoundForced() {
   4640         synchronized (mCameraSoundForced) {
   4641             return mCameraSoundForced;
   4642         }
   4643     }
   4644 
   4645     private static final String[] RINGER_MODE_NAMES = new String[] {
   4646             "SILENT",
   4647             "VIBRATE",
   4648             "NORMAL"
   4649     };
   4650 
   4651     private void dumpRingerMode(PrintWriter pw) {
   4652         pw.println("\nRinger mode: ");
   4653         pw.println("- mode: "+RINGER_MODE_NAMES[mRingerMode]);
   4654         pw.print("- ringer mode affected streams = 0x");
   4655         pw.println(Integer.toHexString(mRingerModeAffectedStreams));
   4656         pw.print("- ringer mode muted streams = 0x");
   4657         pw.println(Integer.toHexString(mRingerModeMutedStreams));
   4658     }
   4659 
   4660     @Override
   4661     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
   4662         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
   4663 
   4664         mMediaFocusControl.dump(pw);
   4665         dumpStreamStates(pw);
   4666         dumpRingerMode(pw);
   4667         pw.println("\nAudio routes:");
   4668         pw.print("  mMainType=0x"); pw.println(Integer.toHexString(mCurAudioRoutes.mMainType));
   4669         pw.print("  mBluetoothName="); pw.println(mCurAudioRoutes.mBluetoothName);
   4670     }
   4671 
   4672     // Inform AudioFlinger of our device's low RAM attribute
   4673     private static void readAndSetLowRamDevice()
   4674     {
   4675         int status = AudioSystem.setLowRamDevice(ActivityManager.isLowRamDeviceStatic());
   4676         if (status != 0) {
   4677             Log.w(TAG, "AudioFlinger informed of device's low RAM attribute; status " + status);
   4678         }
   4679     }
   4680 }
   4681