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