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