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