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