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