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