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