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