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