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