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