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