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