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