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