1/* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.media; 18 19import static android.Manifest.permission.REMOTE_AUDIO_PLAYBACK; 20import static android.media.AudioManager.RINGER_MODE_NORMAL; 21import static android.media.AudioManager.RINGER_MODE_SILENT; 22import static android.media.AudioManager.RINGER_MODE_VIBRATE; 23 24import android.app.Activity; 25import android.app.ActivityManager; 26import android.app.ActivityManagerNative; 27import android.app.AppOpsManager; 28import android.app.KeyguardManager; 29import android.app.PendingIntent; 30import android.app.PendingIntent.CanceledException; 31import android.bluetooth.BluetoothA2dp; 32import android.bluetooth.BluetoothAdapter; 33import android.bluetooth.BluetoothClass; 34import android.bluetooth.BluetoothDevice; 35import android.bluetooth.BluetoothHeadset; 36import android.bluetooth.BluetoothProfile; 37import android.content.ActivityNotFoundException; 38import android.content.BroadcastReceiver; 39import android.content.ComponentName; 40import android.content.ContentResolver; 41import android.content.Context; 42import android.content.Intent; 43import android.content.IntentFilter; 44import android.content.pm.PackageManager; 45import android.content.res.Configuration; 46import android.content.res.Resources; 47import android.content.res.XmlResourceParser; 48import android.database.ContentObserver; 49import android.media.MediaPlayer.OnCompletionListener; 50import android.media.MediaPlayer.OnErrorListener; 51import android.net.Uri; 52import android.os.Binder; 53import android.os.Build; 54import android.os.Bundle; 55import android.os.Environment; 56import android.os.Handler; 57import android.os.IBinder; 58import android.os.Looper; 59import android.os.Message; 60import android.os.PowerManager; 61import android.os.RemoteCallbackList; 62import android.os.RemoteException; 63import android.os.ServiceManager; 64import android.os.SystemProperties; 65import android.os.UserHandle; 66import android.os.Vibrator; 67import android.provider.Settings; 68import android.provider.Settings.System; 69import android.speech.RecognizerIntent; 70import android.telephony.PhoneStateListener; 71import android.telephony.TelephonyManager; 72import android.text.TextUtils; 73import android.util.Log; 74import android.view.KeyEvent; 75import android.view.Surface; 76import android.view.VolumePanel; 77import android.view.WindowManager; 78 79import com.android.internal.telephony.ITelephony; 80import com.android.internal.util.XmlUtils; 81 82import org.xmlpull.v1.XmlPullParserException; 83 84import java.io.FileDescriptor; 85import java.io.IOException; 86import java.io.PrintWriter; 87import java.lang.reflect.Field; 88import java.util.ArrayList; 89import java.util.concurrent.ConcurrentHashMap; 90import java.util.HashMap; 91import java.util.HashSet; 92import java.util.Iterator; 93import java.util.List; 94import java.util.Map; 95import java.util.NoSuchElementException; 96import java.util.Set; 97import java.util.Stack; 98 99/** 100 * The implementation of the volume manager service. 101 * <p> 102 * This implementation focuses on delivering a responsive UI. Most methods are 103 * asynchronous to external calls. For example, the task of setting a volume 104 * will update our internal state, but in a separate thread will set the system 105 * volume and later persist to the database. Similarly, setting the ringer mode 106 * will update the state and broadcast a change and in a separate thread later 107 * persist the ringer mode. 108 * 109 * @hide 110 */ 111public class AudioService extends IAudioService.Stub { 112 113 private static final String TAG = "AudioService"; 114 115 /** Debug remote control client/display feature */ 116 protected static final boolean DEBUG_RC = false; 117 /** Debug volumes */ 118 protected static final boolean DEBUG_VOL = false; 119 120 /** How long to delay before persisting a change in volume/ringer mode. */ 121 private static final int PERSIST_DELAY = 500; 122 123 private final Context mContext; 124 private final ContentResolver mContentResolver; 125 private final AppOpsManager mAppOps; 126 private final boolean mVoiceCapable; 127 128 /** The UI */ 129 private VolumePanel mVolumePanel; 130 131 // sendMsg() flags 132 /** If the msg is already queued, replace it with this one. */ 133 private static final int SENDMSG_REPLACE = 0; 134 /** If the msg is already queued, ignore this one and leave the old. */ 135 private static final int SENDMSG_NOOP = 1; 136 /** If the msg is already queued, queue this one and leave the old. */ 137 private static final int SENDMSG_QUEUE = 2; 138 139 // AudioHandler messages 140 private static final int MSG_SET_DEVICE_VOLUME = 0; 141 private static final int MSG_PERSIST_VOLUME = 1; 142 private static final int MSG_PERSIST_MASTER_VOLUME = 2; 143 private static final int MSG_PERSIST_RINGER_MODE = 3; 144 private static final int MSG_MEDIA_SERVER_DIED = 4; 145 private static final int MSG_PLAY_SOUND_EFFECT = 5; 146 private static final int MSG_BTA2DP_DOCK_TIMEOUT = 6; 147 private static final int MSG_LOAD_SOUND_EFFECTS = 7; 148 private static final int MSG_SET_FORCE_USE = 8; 149 private static final int MSG_BT_HEADSET_CNCT_FAILED = 9; 150 private static final int MSG_SET_ALL_VOLUMES = 10; 151 private static final int MSG_PERSIST_MASTER_VOLUME_MUTE = 11; 152 private static final int MSG_REPORT_NEW_ROUTES = 12; 153 private static final int MSG_SET_FORCE_BT_A2DP_USE = 13; 154 private static final int MSG_CHECK_MUSIC_ACTIVE = 14; 155 private static final int MSG_BROADCAST_AUDIO_BECOMING_NOISY = 15; 156 private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME = 16; 157 private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED = 17; 158 private static final int MSG_PERSIST_SAFE_VOLUME_STATE = 18; 159 private static final int MSG_BROADCAST_BT_CONNECTION_STATE = 19; 160 private static final int MSG_UNLOAD_SOUND_EFFECTS = 20; 161 // start of messages handled under wakelock 162 // these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(), 163 // and not with sendMsg(..., ..., SENDMSG_QUEUE, ...) 164 private static final int MSG_SET_WIRED_DEVICE_CONNECTION_STATE = 100; 165 private static final int MSG_SET_A2DP_CONNECTION_STATE = 101; 166 // end of messages handled under wakelock 167 168 private static final int BTA2DP_DOCK_TIMEOUT_MILLIS = 8000; 169 // Timeout for connection to bluetooth headset service 170 private static final int BT_HEADSET_CNCT_TIMEOUT_MS = 3000; 171 172 /** @see AudioSystemThread */ 173 private AudioSystemThread mAudioSystemThread; 174 /** @see AudioHandler */ 175 private AudioHandler mAudioHandler; 176 /** @see VolumeStreamState */ 177 private VolumeStreamState[] mStreamStates; 178 private SettingsObserver mSettingsObserver; 179 180 private int mMode = AudioSystem.MODE_NORMAL; 181 // protects mRingerMode 182 private final Object mSettingsLock = new Object(); 183 184 private SoundPool mSoundPool; 185 private final Object mSoundEffectsLock = new Object(); 186 private static final int NUM_SOUNDPOOL_CHANNELS = 4; 187 188 // Internally master volume is a float in the 0.0 - 1.0 range, 189 // but to support integer based AudioManager API we translate it to 0 - 100 190 private static final int MAX_MASTER_VOLUME = 100; 191 192 // Maximum volume adjust steps allowed in a single batch call. 193 private static final int MAX_BATCH_VOLUME_ADJUST_STEPS = 4; 194 195 /* Sound effect file names */ 196 private static final String SOUND_EFFECTS_PATH = "/media/audio/ui/"; 197 private static final List<String> SOUND_EFFECT_FILES = new ArrayList<String>(); 198 199 /* Sound effect file name mapping sound effect id (AudioManager.FX_xxx) to 200 * file index in SOUND_EFFECT_FILES[] (first column) and indicating if effect 201 * uses soundpool (second column) */ 202 private final int[][] SOUND_EFFECT_FILES_MAP = new int[AudioManager.NUM_SOUND_EFFECTS][2]; 203 204 /** @hide Maximum volume index values for audio streams */ 205 private static final int[] MAX_STREAM_VOLUME = new int[] { 206 5, // STREAM_VOICE_CALL 207 7, // STREAM_SYSTEM 208 7, // STREAM_RING 209 15, // STREAM_MUSIC 210 7, // STREAM_ALARM 211 7, // STREAM_NOTIFICATION 212 15, // STREAM_BLUETOOTH_SCO 213 7, // STREAM_SYSTEM_ENFORCED 214 15, // STREAM_DTMF 215 15 // STREAM_TTS 216 }; 217 /* mStreamVolumeAlias[] indicates for each stream if it uses the volume settings 218 * of another stream: This avoids multiplying the volume settings for hidden 219 * stream types that follow other stream behavior for volume settings 220 * NOTE: do not create loops in aliases! 221 * Some streams alias to different streams according to device category (phone or tablet) or 222 * use case (in call vs off call...). See updateStreamVolumeAlias() for more details. 223 * mStreamVolumeAlias contains the default aliases for a voice capable device (phone) and 224 * STREAM_VOLUME_ALIAS_NON_VOICE for a non voice capable device (tablet).*/ 225 private final int[] STREAM_VOLUME_ALIAS = new int[] { 226 AudioSystem.STREAM_VOICE_CALL, // STREAM_VOICE_CALL 227 AudioSystem.STREAM_RING, // STREAM_SYSTEM 228 AudioSystem.STREAM_RING, // STREAM_RING 229 AudioSystem.STREAM_MUSIC, // STREAM_MUSIC 230 AudioSystem.STREAM_ALARM, // STREAM_ALARM 231 AudioSystem.STREAM_RING, // STREAM_NOTIFICATION 232 AudioSystem.STREAM_BLUETOOTH_SCO, // STREAM_BLUETOOTH_SCO 233 AudioSystem.STREAM_RING, // STREAM_SYSTEM_ENFORCED 234 AudioSystem.STREAM_RING, // STREAM_DTMF 235 AudioSystem.STREAM_MUSIC // STREAM_TTS 236 }; 237 private final int[] STREAM_VOLUME_ALIAS_NON_VOICE = new int[] { 238 AudioSystem.STREAM_VOICE_CALL, // STREAM_VOICE_CALL 239 AudioSystem.STREAM_MUSIC, // STREAM_SYSTEM 240 AudioSystem.STREAM_RING, // STREAM_RING 241 AudioSystem.STREAM_MUSIC, // STREAM_MUSIC 242 AudioSystem.STREAM_ALARM, // STREAM_ALARM 243 AudioSystem.STREAM_RING, // STREAM_NOTIFICATION 244 AudioSystem.STREAM_BLUETOOTH_SCO, // STREAM_BLUETOOTH_SCO 245 AudioSystem.STREAM_MUSIC, // STREAM_SYSTEM_ENFORCED 246 AudioSystem.STREAM_MUSIC, // STREAM_DTMF 247 AudioSystem.STREAM_MUSIC // STREAM_TTS 248 }; 249 private int[] mStreamVolumeAlias; 250 251 /** 252 * Map AudioSystem.STREAM_* constants to app ops. This should be used 253 * after mapping through mStreamVolumeAlias. 254 */ 255 private static final int[] STEAM_VOLUME_OPS = new int[] { 256 AppOpsManager.OP_AUDIO_VOICE_VOLUME, // STREAM_VOICE_CALL 257 AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_SYSTEM 258 AppOpsManager.OP_AUDIO_RING_VOLUME, // STREAM_RING 259 AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_MUSIC 260 AppOpsManager.OP_AUDIO_ALARM_VOLUME, // STREAM_ALARM 261 AppOpsManager.OP_AUDIO_NOTIFICATION_VOLUME, // STREAM_NOTIFICATION 262 AppOpsManager.OP_AUDIO_BLUETOOTH_VOLUME, // STREAM_BLUETOOTH_SCO 263 AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_SYSTEM_ENFORCED 264 AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_DTMF 265 AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_TTS 266 }; 267 268 private final boolean mUseFixedVolume; 269 270 // stream names used by dumpStreamStates() 271 private final String[] STREAM_NAMES = new String[] { 272 "STREAM_VOICE_CALL", 273 "STREAM_SYSTEM", 274 "STREAM_RING", 275 "STREAM_MUSIC", 276 "STREAM_ALARM", 277 "STREAM_NOTIFICATION", 278 "STREAM_BLUETOOTH_SCO", 279 "STREAM_SYSTEM_ENFORCED", 280 "STREAM_DTMF", 281 "STREAM_TTS" 282 }; 283 284 private final AudioSystem.ErrorCallback mAudioSystemCallback = new AudioSystem.ErrorCallback() { 285 public void onError(int error) { 286 switch (error) { 287 case AudioSystem.AUDIO_STATUS_SERVER_DIED: 288 sendMsg(mAudioHandler, MSG_MEDIA_SERVER_DIED, 289 SENDMSG_NOOP, 0, 0, null, 0); 290 break; 291 default: 292 break; 293 } 294 } 295 }; 296 297 /** 298 * Current ringer mode from one of {@link AudioManager#RINGER_MODE_NORMAL}, 299 * {@link AudioManager#RINGER_MODE_SILENT}, or 300 * {@link AudioManager#RINGER_MODE_VIBRATE}. 301 */ 302 // protected by mSettingsLock 303 private int mRingerMode; 304 305 /** @see System#MODE_RINGER_STREAMS_AFFECTED */ 306 private int mRingerModeAffectedStreams = 0; 307 308 // Streams currently muted by ringer mode 309 private int mRingerModeMutedStreams; 310 311 /** @see System#MUTE_STREAMS_AFFECTED */ 312 private int mMuteAffectedStreams; 313 314 /** 315 * NOTE: setVibrateSetting(), getVibrateSetting(), shouldVibrate() are deprecated. 316 * mVibrateSetting is just maintained during deprecation period but vibration policy is 317 * now only controlled by mHasVibrator and mRingerMode 318 */ 319 private int mVibrateSetting; 320 321 // Is there a vibrator 322 private final boolean mHasVibrator; 323 324 // Broadcast receiver for device connections intent broadcasts 325 private final BroadcastReceiver mReceiver = new AudioServiceBroadcastReceiver(); 326 327 // Devices currently connected 328 private final HashMap <Integer, String> mConnectedDevices = new HashMap <Integer, String>(); 329 330 // Forced device usage for communications 331 private int mForcedUseForComm; 332 333 // True if we have master volume support 334 private final boolean mUseMasterVolume; 335 336 private final int[] mMasterVolumeRamp; 337 338 // List of binder death handlers for setMode() client processes. 339 // The last process to have called setMode() is at the top of the list. 340 private final ArrayList <SetModeDeathHandler> mSetModeDeathHandlers = new ArrayList <SetModeDeathHandler>(); 341 342 // List of clients having issued a SCO start request 343 private final ArrayList <ScoClient> mScoClients = new ArrayList <ScoClient>(); 344 345 // BluetoothHeadset API to control SCO connection 346 private BluetoothHeadset mBluetoothHeadset; 347 348 // Bluetooth headset device 349 private BluetoothDevice mBluetoothHeadsetDevice; 350 351 // Indicate if SCO audio connection is currently active and if the initiator is 352 // audio service (internal) or bluetooth headset (external) 353 private int mScoAudioState; 354 // SCO audio state is not active 355 private static final int SCO_STATE_INACTIVE = 0; 356 // SCO audio activation request waiting for headset service to connect 357 private static final int SCO_STATE_ACTIVATE_REQ = 1; 358 // SCO audio state is active or starting due to a request from AudioManager API 359 private static final int SCO_STATE_ACTIVE_INTERNAL = 3; 360 // SCO audio deactivation request waiting for headset service to connect 361 private static final int SCO_STATE_DEACTIVATE_REQ = 5; 362 363 // SCO audio state is active due to an action in BT handsfree (either voice recognition or 364 // in call audio) 365 private static final int SCO_STATE_ACTIVE_EXTERNAL = 2; 366 // Deactivation request for all SCO connections (initiated by audio mode change) 367 // waiting for headset service to connect 368 private static final int SCO_STATE_DEACTIVATE_EXT_REQ = 4; 369 370 // Indicates the mode used for SCO audio connection. The mode is virtual call if the request 371 // originated from an app targeting an API version before JB MR2 and raw audio after that. 372 private int mScoAudioMode; 373 // SCO audio mode is virtual voice call (BluetoothHeadset.startScoUsingVirtualVoiceCall()) 374 private static final int SCO_MODE_VIRTUAL_CALL = 0; 375 // SCO audio mode is raw audio (BluetoothHeadset.connectAudio()) 376 private static final int SCO_MODE_RAW = 1; 377 378 // Current connection state indicated by bluetooth headset 379 private int mScoConnectionState; 380 381 // true if boot sequence has been completed 382 private boolean mBootCompleted; 383 // listener for SoundPool sample load completion indication 384 private SoundPoolCallback mSoundPoolCallBack; 385 // thread for SoundPool listener 386 private SoundPoolListenerThread mSoundPoolListenerThread; 387 // message looper for SoundPool listener 388 private Looper mSoundPoolLooper = null; 389 // volume applied to sound played with playSoundEffect() 390 private static int sSoundEffectVolumeDb; 391 // getActiveStreamType() will return: 392 // - STREAM_NOTIFICATION on tablets during this period after a notification stopped 393 // - STREAM_MUSIC on phones during this period after music or talkback/voice search prompt 394 // stopped 395 private static final int DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS = 5000; 396 // previous volume adjustment direction received by checkForRingerModeChange() 397 private int mPrevVolDirection = AudioManager.ADJUST_SAME; 398 // Keyguard manager proxy 399 private KeyguardManager mKeyguardManager; 400 // mVolumeControlStream is set by VolumePanel to temporarily force the stream type which volume 401 // is controlled by Vol keys. 402 private int mVolumeControlStream = -1; 403 private final Object mForceControlStreamLock = new Object(); 404 // VolumePanel is currently the only client of forceVolumeControlStream() and runs in system 405 // server process so in theory it is not necessary to monitor the client death. 406 // However it is good to be ready for future evolutions. 407 private ForceControlStreamClient mForceControlStreamClient = null; 408 // Used to play ringtones outside system_server 409 private volatile IRingtonePlayer mRingtonePlayer; 410 411 private int mDeviceOrientation = Configuration.ORIENTATION_UNDEFINED; 412 private int mDeviceRotation = Surface.ROTATION_0; 413 414 // Request to override default use of A2DP for media. 415 private boolean mBluetoothA2dpEnabled; 416 private final Object mBluetoothA2dpEnabledLock = new Object(); 417 418 // Monitoring of audio routes. Protected by mCurAudioRoutes. 419 final AudioRoutesInfo mCurAudioRoutes = new AudioRoutesInfo(); 420 final RemoteCallbackList<IAudioRoutesObserver> mRoutesObservers 421 = new RemoteCallbackList<IAudioRoutesObserver>(); 422 423 /** 424 * A fake stream type to match the notion of remote media playback 425 */ 426 public final static int STREAM_REMOTE_MUSIC = -200; 427 428 // Devices for which the volume is fixed and VolumePanel slider should be disabled 429 final int mFixedVolumeDevices = AudioSystem.DEVICE_OUT_AUX_DIGITAL | 430 AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET | 431 AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET | 432 AudioSystem.DEVICE_OUT_ALL_USB; 433 434 // TODO merge orientation and rotation 435 private final boolean mMonitorOrientation; 436 private final boolean mMonitorRotation; 437 438 private boolean mDockAudioMediaEnabled = true; 439 440 private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED; 441 442 // Used when safe volume warning message display is requested by setStreamVolume(). In this 443 // case, the new requested volume, stream type and device are stored in mPendingVolumeCommand 444 // and used later when/if disableSafeMediaVolume() is called. 445 private StreamVolumeCommand mPendingVolumeCommand; 446 447 private PowerManager.WakeLock mAudioEventWakeLock; 448 449 private final MediaFocusControl mMediaFocusControl; 450 451 // Reference to BluetoothA2dp to query for AbsoluteVolume. 452 private BluetoothA2dp mA2dp; 453 private final Object mA2dpAvrcpLock = new Object(); 454 // If absolute volume is supported in AVRCP device 455 private boolean mAvrcpAbsVolSupported = false; 456 457 /////////////////////////////////////////////////////////////////////////// 458 // Construction 459 /////////////////////////////////////////////////////////////////////////// 460 461 /** @hide */ 462 public AudioService(Context context) { 463 mContext = context; 464 mContentResolver = context.getContentResolver(); 465 mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE); 466 mVoiceCapable = mContext.getResources().getBoolean( 467 com.android.internal.R.bool.config_voice_capable); 468 469 PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 470 mAudioEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "handleAudioEvent"); 471 472 Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); 473 mHasVibrator = vibrator == null ? false : vibrator.hasVibrator(); 474 475 // Intialized volume 476 MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] = SystemProperties.getInt( 477 "ro.config.vc_call_vol_steps", 478 MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL]); 479 480 sSoundEffectVolumeDb = context.getResources().getInteger( 481 com.android.internal.R.integer.config_soundEffectVolumeDb); 482 483 mVolumePanel = new VolumePanel(context, this); 484 mForcedUseForComm = AudioSystem.FORCE_NONE; 485 486 createAudioSystemThread(); 487 488 mMediaFocusControl = new MediaFocusControl(mAudioHandler.getLooper(), 489 mContext, /*VolumeController*/ mVolumePanel, this); 490 491 AudioSystem.setErrorCallback(mAudioSystemCallback); 492 493 boolean cameraSoundForced = mContext.getResources().getBoolean( 494 com.android.internal.R.bool.config_camera_sound_forced); 495 mCameraSoundForced = new Boolean(cameraSoundForced); 496 sendMsg(mAudioHandler, 497 MSG_SET_FORCE_USE, 498 SENDMSG_QUEUE, 499 AudioSystem.FOR_SYSTEM, 500 cameraSoundForced ? 501 AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE, 502 null, 503 0); 504 505 mSafeMediaVolumeState = new Integer(Settings.Global.getInt(mContentResolver, 506 Settings.Global.AUDIO_SAFE_VOLUME_STATE, 507 SAFE_MEDIA_VOLUME_NOT_CONFIGURED)); 508 // The default safe volume index read here will be replaced by the actual value when 509 // the mcc is read by onConfigureSafeVolume() 510 mSafeMediaVolumeIndex = mContext.getResources().getInteger( 511 com.android.internal.R.integer.config_safe_media_volume_index) * 10; 512 513 mUseFixedVolume = mContext.getResources().getBoolean( 514 com.android.internal.R.bool.config_useFixedVolume); 515 516 // must be called before readPersistedSettings() which needs a valid mStreamVolumeAlias[] 517 // array initialized by updateStreamVolumeAlias() 518 updateStreamVolumeAlias(false /*updateVolumes*/); 519 readPersistedSettings(); 520 mSettingsObserver = new SettingsObserver(); 521 createStreamStates(); 522 523 readAndSetLowRamDevice(); 524 525 // Call setRingerModeInt() to apply correct mute 526 // state on streams affected by ringer mode. 527 mRingerModeMutedStreams = 0; 528 setRingerModeInt(getRingerMode(), false); 529 530 // Register for device connection intent broadcasts. 531 IntentFilter intentFilter = 532 new IntentFilter(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED); 533 intentFilter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); 534 intentFilter.addAction(Intent.ACTION_DOCK_EVENT); 535 intentFilter.addAction(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG); 536 intentFilter.addAction(Intent.ACTION_USB_AUDIO_DEVICE_PLUG); 537 intentFilter.addAction(Intent.ACTION_BOOT_COMPLETED); 538 intentFilter.addAction(Intent.ACTION_SCREEN_ON); 539 intentFilter.addAction(Intent.ACTION_SCREEN_OFF); 540 intentFilter.addAction(Intent.ACTION_USER_SWITCHED); 541 542 intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); 543 // TODO merge orientation and rotation 544 mMonitorOrientation = SystemProperties.getBoolean("ro.audio.monitorOrientation", false); 545 if (mMonitorOrientation) { 546 Log.v(TAG, "monitoring device orientation"); 547 // initialize orientation in AudioSystem 548 setOrientationForAudioSystem(); 549 } 550 mMonitorRotation = SystemProperties.getBoolean("ro.audio.monitorRotation", false); 551 if (mMonitorRotation) { 552 mDeviceRotation = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE)) 553 .getDefaultDisplay().getRotation(); 554 Log.v(TAG, "monitoring device rotation, initial=" + mDeviceRotation); 555 // initialize rotation in AudioSystem 556 setRotationForAudioSystem(); 557 } 558 559 context.registerReceiver(mReceiver, intentFilter); 560 561 mUseMasterVolume = context.getResources().getBoolean( 562 com.android.internal.R.bool.config_useMasterVolume); 563 restoreMasterVolume(); 564 565 mMasterVolumeRamp = context.getResources().getIntArray( 566 com.android.internal.R.array.config_masterVolumeRamp); 567 568 } 569 570 private void createAudioSystemThread() { 571 mAudioSystemThread = new AudioSystemThread(); 572 mAudioSystemThread.start(); 573 waitForAudioHandlerCreation(); 574 } 575 576 /** Waits for the volume handler to be created by the other thread. */ 577 private void waitForAudioHandlerCreation() { 578 synchronized(this) { 579 while (mAudioHandler == null) { 580 try { 581 // Wait for mAudioHandler to be set by the other thread 582 wait(); 583 } catch (InterruptedException e) { 584 Log.e(TAG, "Interrupted while waiting on volume handler."); 585 } 586 } 587 } 588 } 589 590 private void checkAllAliasStreamVolumes() { 591 int numStreamTypes = AudioSystem.getNumStreamTypes(); 592 for (int streamType = 0; streamType < numStreamTypes; streamType++) { 593 if (streamType != mStreamVolumeAlias[streamType]) { 594 mStreamStates[streamType]. 595 setAllIndexes(mStreamStates[mStreamVolumeAlias[streamType]]); 596 } 597 // apply stream volume 598 if (!mStreamStates[streamType].isMuted()) { 599 mStreamStates[streamType].applyAllVolumes(); 600 } 601 } 602 } 603 604 private void createStreamStates() { 605 int numStreamTypes = AudioSystem.getNumStreamTypes(); 606 VolumeStreamState[] streams = mStreamStates = new VolumeStreamState[numStreamTypes]; 607 608 for (int i = 0; i < numStreamTypes; i++) { 609 streams[i] = new VolumeStreamState(System.VOLUME_SETTINGS[mStreamVolumeAlias[i]], i); 610 } 611 612 checkAllAliasStreamVolumes(); 613 } 614 615 private void dumpStreamStates(PrintWriter pw) { 616 pw.println("\nStream volumes (device: index)"); 617 int numStreamTypes = AudioSystem.getNumStreamTypes(); 618 for (int i = 0; i < numStreamTypes; i++) { 619 pw.println("- "+STREAM_NAMES[i]+":"); 620 mStreamStates[i].dump(pw); 621 pw.println(""); 622 } 623 pw.print("\n- mute affected streams = 0x"); 624 pw.println(Integer.toHexString(mMuteAffectedStreams)); 625 } 626 627 628 private void updateStreamVolumeAlias(boolean updateVolumes) { 629 int dtmfStreamAlias; 630 if (mVoiceCapable) { 631 mStreamVolumeAlias = STREAM_VOLUME_ALIAS; 632 dtmfStreamAlias = AudioSystem.STREAM_RING; 633 } else { 634 mStreamVolumeAlias = STREAM_VOLUME_ALIAS_NON_VOICE; 635 dtmfStreamAlias = AudioSystem.STREAM_MUSIC; 636 } 637 if (isInCommunication()) { 638 dtmfStreamAlias = AudioSystem.STREAM_VOICE_CALL; 639 mRingerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_DTMF); 640 } else { 641 mRingerModeAffectedStreams |= (1 << AudioSystem.STREAM_DTMF); 642 } 643 mStreamVolumeAlias[AudioSystem.STREAM_DTMF] = dtmfStreamAlias; 644 if (updateVolumes) { 645 mStreamStates[AudioSystem.STREAM_DTMF].setAllIndexes(mStreamStates[dtmfStreamAlias]); 646 // apply stream mute states according to new value of mRingerModeAffectedStreams 647 setRingerModeInt(getRingerMode(), false); 648 sendMsg(mAudioHandler, 649 MSG_SET_ALL_VOLUMES, 650 SENDMSG_QUEUE, 651 0, 652 0, 653 mStreamStates[AudioSystem.STREAM_DTMF], 0); 654 } 655 } 656 657 private void readDockAudioSettings(ContentResolver cr) 658 { 659 mDockAudioMediaEnabled = Settings.Global.getInt( 660 cr, Settings.Global.DOCK_AUDIO_MEDIA_ENABLED, 0) == 1; 661 662 if (mDockAudioMediaEnabled) { 663 mBecomingNoisyIntentDevices |= AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET; 664 } else { 665 mBecomingNoisyIntentDevices &= ~AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET; 666 } 667 668 sendMsg(mAudioHandler, 669 MSG_SET_FORCE_USE, 670 SENDMSG_QUEUE, 671 AudioSystem.FOR_DOCK, 672 mDockAudioMediaEnabled ? 673 AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE, 674 null, 675 0); 676 } 677 678 private void readPersistedSettings() { 679 final ContentResolver cr = mContentResolver; 680 681 int ringerModeFromSettings = 682 Settings.Global.getInt( 683 cr, Settings.Global.MODE_RINGER, AudioManager.RINGER_MODE_NORMAL); 684 int ringerMode = ringerModeFromSettings; 685 // sanity check in case the settings are restored from a device with incompatible 686 // ringer modes 687 if (!AudioManager.isValidRingerMode(ringerMode)) { 688 ringerMode = AudioManager.RINGER_MODE_NORMAL; 689 } 690 if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) { 691 ringerMode = AudioManager.RINGER_MODE_SILENT; 692 } 693 if (ringerMode != ringerModeFromSettings) { 694 Settings.Global.putInt(cr, Settings.Global.MODE_RINGER, ringerMode); 695 } 696 if (mUseFixedVolume) { 697 ringerMode = AudioManager.RINGER_MODE_NORMAL; 698 } 699 synchronized(mSettingsLock) { 700 mRingerMode = ringerMode; 701 702 // System.VIBRATE_ON is not used any more but defaults for mVibrateSetting 703 // are still needed while setVibrateSetting() and getVibrateSetting() are being 704 // deprecated. 705 mVibrateSetting = getValueForVibrateSetting(0, 706 AudioManager.VIBRATE_TYPE_NOTIFICATION, 707 mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT 708 : AudioManager.VIBRATE_SETTING_OFF); 709 mVibrateSetting = getValueForVibrateSetting(mVibrateSetting, 710 AudioManager.VIBRATE_TYPE_RINGER, 711 mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT 712 : AudioManager.VIBRATE_SETTING_OFF); 713 714 updateRingerModeAffectedStreams(); 715 readDockAudioSettings(cr); 716 } 717 718 mMuteAffectedStreams = System.getIntForUser(cr, 719 System.MUTE_STREAMS_AFFECTED, 720 ((1 << AudioSystem.STREAM_MUSIC)| 721 (1 << AudioSystem.STREAM_RING)| 722 (1 << AudioSystem.STREAM_SYSTEM)), 723 UserHandle.USER_CURRENT); 724 725 boolean masterMute = System.getIntForUser(cr, System.VOLUME_MASTER_MUTE, 726 0, UserHandle.USER_CURRENT) == 1; 727 if (mUseFixedVolume) { 728 masterMute = false; 729 AudioSystem.setMasterVolume(1.0f); 730 } 731 AudioSystem.setMasterMute(masterMute); 732 broadcastMasterMuteStatus(masterMute); 733 734 // Each stream will read its own persisted settings 735 736 // Broadcast the sticky intent 737 broadcastRingerMode(ringerMode); 738 739 // Broadcast vibrate settings 740 broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER); 741 broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION); 742 743 // Restore the default media button receiver from the system settings 744 mMediaFocusControl.restoreMediaButtonReceiver(); 745 } 746 747 private int rescaleIndex(int index, int srcStream, int dstStream) { 748 return (index * mStreamStates[dstStream].getMaxIndex() + mStreamStates[srcStream].getMaxIndex() / 2) / mStreamStates[srcStream].getMaxIndex(); 749 } 750 751 /////////////////////////////////////////////////////////////////////////// 752 // IPC methods 753 /////////////////////////////////////////////////////////////////////////// 754 /** @see AudioManager#isLocalOrRemoteMusicActive() */ 755 public boolean isLocalOrRemoteMusicActive() { 756 if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0)) { 757 // local / wired / BT playback active 758 if (DEBUG_VOL) Log.d(TAG, "isLocalOrRemoteMusicActive(): local"); 759 return true; 760 } 761 if (mMediaFocusControl.checkUpdateRemoteStateIfActive(AudioSystem.STREAM_MUSIC)) { 762 // remote "cast-like" playback active 763 if (DEBUG_VOL) Log.d(TAG, "isLocalOrRemoteMusicActive(): has PLAYBACK_TYPE_REMOTE"); 764 return true; 765 } 766 if (AudioSystem.isStreamActiveRemotely(AudioSystem.STREAM_MUSIC, 0)) { 767 // remote submix playback active 768 if (DEBUG_VOL) Log.d(TAG, "isLocalOrRemoteMusicActive(): remote submix"); 769 return true; 770 } 771 if (DEBUG_VOL) Log.d(TAG, "isLocalOrRemoteMusicActive(): no"); 772 return false; 773 } 774 775 /** @see AudioManager#adjustVolume(int, int) */ 776 public void adjustVolume(int direction, int flags, String callingPackage) { 777 adjustSuggestedStreamVolume(direction, AudioManager.USE_DEFAULT_STREAM_TYPE, flags, 778 callingPackage); 779 } 780 781 /** @see AudioManager#adjustLocalOrRemoteStreamVolume(int, int) with current assumption 782 * on streamType: fixed to STREAM_MUSIC */ 783 public void adjustLocalOrRemoteStreamVolume(int streamType, int direction, 784 String callingPackage) { 785 if (DEBUG_VOL) Log.d(TAG, "adjustLocalOrRemoteStreamVolume(dir="+direction+")"); 786 if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0)) { 787 adjustStreamVolume(AudioSystem.STREAM_MUSIC, direction, 0, callingPackage); 788 } else if (mMediaFocusControl.checkUpdateRemoteStateIfActive(AudioSystem.STREAM_MUSIC)) { 789 mMediaFocusControl.adjustRemoteVolume(AudioSystem.STREAM_MUSIC, direction, 0); 790 } 791 } 792 793 /** @see AudioManager#adjustVolume(int, int) */ 794 public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags, 795 String callingPackage) { 796 if (DEBUG_VOL) Log.d(TAG, "adjustSuggestedStreamVolume() stream="+suggestedStreamType); 797 int streamType; 798 if (mVolumeControlStream != -1) { 799 streamType = mVolumeControlStream; 800 } else { 801 streamType = getActiveStreamType(suggestedStreamType); 802 } 803 804 // Play sounds on STREAM_RING only and if lock screen is not on. 805 if ((streamType != STREAM_REMOTE_MUSIC) && 806 (flags & AudioManager.FLAG_PLAY_SOUND) != 0 && 807 ((mStreamVolumeAlias[streamType] != AudioSystem.STREAM_RING) 808 || (mKeyguardManager != null && mKeyguardManager.isKeyguardLocked()))) { 809 flags &= ~AudioManager.FLAG_PLAY_SOUND; 810 } 811 812 if (streamType == STREAM_REMOTE_MUSIC) { 813 // don't play sounds for remote 814 flags &= ~(AudioManager.FLAG_PLAY_SOUND|AudioManager.FLAG_FIXED_VOLUME); 815 //if (DEBUG_VOL) Log.i(TAG, "Need to adjust remote volume: calling adjustRemoteVolume()"); 816 mMediaFocusControl.adjustRemoteVolume(AudioSystem.STREAM_MUSIC, direction, flags); 817 } else { 818 adjustStreamVolume(streamType, direction, flags, callingPackage); 819 } 820 } 821 822 /** @see AudioManager#adjustStreamVolume(int, int, int) */ 823 public void adjustStreamVolume(int streamType, int direction, int flags, 824 String callingPackage) { 825 if (mUseFixedVolume) { 826 return; 827 } 828 if (DEBUG_VOL) Log.d(TAG, "adjustStreamVolume() stream="+streamType+", dir="+direction); 829 830 ensureValidDirection(direction); 831 ensureValidStreamType(streamType); 832 833 // use stream type alias here so that streams with same alias have the same behavior, 834 // including with regard to silent mode control (e.g the use of STREAM_RING below and in 835 // checkForRingerModeChange() in place of STREAM_RING or STREAM_NOTIFICATION) 836 int streamTypeAlias = mStreamVolumeAlias[streamType]; 837 VolumeStreamState streamState = mStreamStates[streamTypeAlias]; 838 839 final int device = getDeviceForStream(streamTypeAlias); 840 841 int aliasIndex = streamState.getIndex(device); 842 boolean adjustVolume = true; 843 int step; 844 845 // skip a2dp absolute volume control request when the device 846 // is not an a2dp device 847 if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 && 848 (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) { 849 return; 850 } 851 852 if (mAppOps.noteOp(STEAM_VOLUME_OPS[streamTypeAlias], Binder.getCallingUid(), 853 callingPackage) != AppOpsManager.MODE_ALLOWED) { 854 return; 855 } 856 857 // reset any pending volume command 858 synchronized (mSafeMediaVolumeState) { 859 mPendingVolumeCommand = null; 860 } 861 862 flags &= ~AudioManager.FLAG_FIXED_VOLUME; 863 if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) && 864 ((device & mFixedVolumeDevices) != 0)) { 865 flags |= AudioManager.FLAG_FIXED_VOLUME; 866 867 // Always toggle between max safe volume and 0 for fixed volume devices where safe 868 // volume is enforced, and max and 0 for the others. 869 // This is simulated by stepping by the full allowed volume range 870 if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE && 871 (device & mSafeMediaVolumeDevices) != 0) { 872 step = mSafeMediaVolumeIndex; 873 } else { 874 step = streamState.getMaxIndex(); 875 } 876 if (aliasIndex != 0) { 877 aliasIndex = step; 878 } 879 } else { 880 // convert one UI step (+/-1) into a number of internal units on the stream alias 881 step = rescaleIndex(10, streamType, streamTypeAlias); 882 } 883 884 // If either the client forces allowing ringer modes for this adjustment, 885 // or the stream type is one that is affected by ringer modes 886 if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) || 887 (streamTypeAlias == getMasterStreamType())) { 888 int ringerMode = getRingerMode(); 889 // do not vibrate if already in vibrate mode 890 if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) { 891 flags &= ~AudioManager.FLAG_VIBRATE; 892 } 893 // Check if the ringer mode changes with this volume adjustment. If 894 // it does, it will handle adjusting the volume, so we won't below 895 adjustVolume = checkForRingerModeChange(aliasIndex, direction, step); 896 } 897 898 int oldIndex = mStreamStates[streamType].getIndex(device); 899 900 if (adjustVolume && (direction != AudioManager.ADJUST_SAME)) { 901 902 // Check if volume update should be send to AVRCP 903 if (streamTypeAlias == AudioSystem.STREAM_MUSIC && 904 (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && 905 (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) { 906 synchronized (mA2dpAvrcpLock) { 907 if (mA2dp != null && mAvrcpAbsVolSupported) { 908 mA2dp.adjustAvrcpAbsoluteVolume(direction); 909 } 910 } 911 } 912 913 if ((direction == AudioManager.ADJUST_RAISE) && 914 !checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) { 915 Log.e(TAG, "adjustStreamVolume() safe volume index = "+oldIndex); 916 mVolumePanel.postDisplaySafeVolumeWarning(flags); 917 } else if (streamState.adjustIndex(direction * step, device)) { 918 // Post message to set system volume (it in turn will post a message 919 // to persist). Do not change volume if stream is muted. 920 sendMsg(mAudioHandler, 921 MSG_SET_DEVICE_VOLUME, 922 SENDMSG_QUEUE, 923 device, 924 0, 925 streamState, 926 0); 927 } 928 } 929 int index = mStreamStates[streamType].getIndex(device); 930 sendVolumeUpdate(streamType, oldIndex, index, flags); 931 } 932 933 /** @see AudioManager#adjustMasterVolume(int, int) */ 934 public void adjustMasterVolume(int steps, int flags, String callingPackage) { 935 if (mUseFixedVolume) { 936 return; 937 } 938 ensureValidSteps(steps); 939 int volume = Math.round(AudioSystem.getMasterVolume() * MAX_MASTER_VOLUME); 940 int delta = 0; 941 int numSteps = Math.abs(steps); 942 int direction = steps > 0 ? AudioManager.ADJUST_RAISE : AudioManager.ADJUST_LOWER; 943 for (int i = 0; i < numSteps; ++i) { 944 delta = findVolumeDelta(direction, volume); 945 volume += delta; 946 } 947 948 //Log.d(TAG, "adjustMasterVolume volume: " + volume + " steps: " + steps); 949 setMasterVolume(volume, flags, callingPackage); 950 } 951 952 // StreamVolumeCommand contains the information needed to defer the process of 953 // setStreamVolume() in case the user has to acknowledge the safe volume warning message. 954 class StreamVolumeCommand { 955 public final int mStreamType; 956 public final int mIndex; 957 public final int mFlags; 958 public final int mDevice; 959 960 StreamVolumeCommand(int streamType, int index, int flags, int device) { 961 mStreamType = streamType; 962 mIndex = index; 963 mFlags = flags; 964 mDevice = device; 965 } 966 }; 967 968 private void onSetStreamVolume(int streamType, int index, int flags, int device) { 969 setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, false); 970 // setting volume on master stream type also controls silent mode 971 if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) || 972 (mStreamVolumeAlias[streamType] == getMasterStreamType())) { 973 int newRingerMode; 974 if (index == 0) { 975 newRingerMode = mHasVibrator ? AudioManager.RINGER_MODE_VIBRATE 976 : AudioManager.RINGER_MODE_SILENT; 977 } else { 978 newRingerMode = AudioManager.RINGER_MODE_NORMAL; 979 } 980 setRingerMode(newRingerMode); 981 } 982 } 983 984 /** @see AudioManager#setStreamVolume(int, int, int) */ 985 public void setStreamVolume(int streamType, int index, int flags, String callingPackage) { 986 if (mUseFixedVolume) { 987 return; 988 } 989 990 ensureValidStreamType(streamType); 991 int streamTypeAlias = mStreamVolumeAlias[streamType]; 992 VolumeStreamState streamState = mStreamStates[streamTypeAlias]; 993 994 final int device = getDeviceForStream(streamType); 995 int oldIndex; 996 997 // skip a2dp absolute volume control request when the device 998 // is not an a2dp device 999 if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 && 1000 (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) { 1001 return; 1002 } 1003 1004 if (mAppOps.noteOp(STEAM_VOLUME_OPS[streamTypeAlias], Binder.getCallingUid(), 1005 callingPackage) != AppOpsManager.MODE_ALLOWED) { 1006 return; 1007 } 1008 1009 synchronized (mSafeMediaVolumeState) { 1010 // reset any pending volume command 1011 mPendingVolumeCommand = null; 1012 1013 oldIndex = streamState.getIndex(device); 1014 1015 index = rescaleIndex(index * 10, streamType, streamTypeAlias); 1016 1017 if (streamTypeAlias == AudioSystem.STREAM_MUSIC && 1018 (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && 1019 (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) { 1020 synchronized (mA2dpAvrcpLock) { 1021 if (mA2dp != null && mAvrcpAbsVolSupported) { 1022 mA2dp.setAvrcpAbsoluteVolume(index); 1023 } 1024 } 1025 } 1026 1027 flags &= ~AudioManager.FLAG_FIXED_VOLUME; 1028 if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) && 1029 ((device & mFixedVolumeDevices) != 0)) { 1030 flags |= AudioManager.FLAG_FIXED_VOLUME; 1031 1032 // volume is either 0 or max allowed for fixed volume devices 1033 if (index != 0) { 1034 if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE && 1035 (device & mSafeMediaVolumeDevices) != 0) { 1036 index = mSafeMediaVolumeIndex; 1037 } else { 1038 index = streamState.getMaxIndex(); 1039 } 1040 } 1041 } 1042 1043 if (!checkSafeMediaVolume(streamTypeAlias, index, device)) { 1044 mVolumePanel.postDisplaySafeVolumeWarning(flags); 1045 mPendingVolumeCommand = new StreamVolumeCommand( 1046 streamType, index, flags, device); 1047 } else { 1048 onSetStreamVolume(streamType, index, flags, device); 1049 index = mStreamStates[streamType].getIndex(device); 1050 } 1051 } 1052 sendVolumeUpdate(streamType, oldIndex, index, flags); 1053 } 1054 1055 /** @see AudioManager#forceVolumeControlStream(int) */ 1056 public void forceVolumeControlStream(int streamType, IBinder cb) { 1057 synchronized(mForceControlStreamLock) { 1058 mVolumeControlStream = streamType; 1059 if (mVolumeControlStream == -1) { 1060 if (mForceControlStreamClient != null) { 1061 mForceControlStreamClient.release(); 1062 mForceControlStreamClient = null; 1063 } 1064 } else { 1065 mForceControlStreamClient = new ForceControlStreamClient(cb); 1066 } 1067 } 1068 } 1069 1070 private class ForceControlStreamClient implements IBinder.DeathRecipient { 1071 private IBinder mCb; // To be notified of client's death 1072 1073 ForceControlStreamClient(IBinder cb) { 1074 if (cb != null) { 1075 try { 1076 cb.linkToDeath(this, 0); 1077 } catch (RemoteException e) { 1078 // Client has died! 1079 Log.w(TAG, "ForceControlStreamClient() could not link to "+cb+" binder death"); 1080 cb = null; 1081 } 1082 } 1083 mCb = cb; 1084 } 1085 1086 public void binderDied() { 1087 synchronized(mForceControlStreamLock) { 1088 Log.w(TAG, "SCO client died"); 1089 if (mForceControlStreamClient != this) { 1090 Log.w(TAG, "unregistered control stream client died"); 1091 } else { 1092 mForceControlStreamClient = null; 1093 mVolumeControlStream = -1; 1094 } 1095 } 1096 } 1097 1098 public void release() { 1099 if (mCb != null) { 1100 mCb.unlinkToDeath(this, 0); 1101 mCb = null; 1102 } 1103 } 1104 } 1105 1106 private int findVolumeDelta(int direction, int volume) { 1107 int delta = 0; 1108 if (direction == AudioManager.ADJUST_RAISE) { 1109 if (volume == MAX_MASTER_VOLUME) { 1110 return 0; 1111 } 1112 // This is the default value if we make it to the end 1113 delta = mMasterVolumeRamp[1]; 1114 // If we're raising the volume move down the ramp array until we 1115 // find the volume we're above and use that groups delta. 1116 for (int i = mMasterVolumeRamp.length - 1; i > 1; i -= 2) { 1117 if (volume >= mMasterVolumeRamp[i - 1]) { 1118 delta = mMasterVolumeRamp[i]; 1119 break; 1120 } 1121 } 1122 } else if (direction == AudioManager.ADJUST_LOWER){ 1123 if (volume == 0) { 1124 return 0; 1125 } 1126 int length = mMasterVolumeRamp.length; 1127 // This is the default value if we make it to the end 1128 delta = -mMasterVolumeRamp[length - 1]; 1129 // If we're lowering the volume move up the ramp array until we 1130 // find the volume we're below and use the group below it's delta 1131 for (int i = 2; i < length; i += 2) { 1132 if (volume <= mMasterVolumeRamp[i]) { 1133 delta = -mMasterVolumeRamp[i - 1]; 1134 break; 1135 } 1136 } 1137 } 1138 return delta; 1139 } 1140 1141 private void sendBroadcastToAll(Intent intent) { 1142 final long ident = Binder.clearCallingIdentity(); 1143 try { 1144 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 1145 } finally { 1146 Binder.restoreCallingIdentity(ident); 1147 } 1148 } 1149 1150 private void sendStickyBroadcastToAll(Intent intent) { 1151 final long ident = Binder.clearCallingIdentity(); 1152 try { 1153 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 1154 } finally { 1155 Binder.restoreCallingIdentity(ident); 1156 } 1157 } 1158 1159 // UI update and Broadcast Intent 1160 private void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags) { 1161 if (!mVoiceCapable && (streamType == AudioSystem.STREAM_RING)) { 1162 streamType = AudioSystem.STREAM_NOTIFICATION; 1163 } 1164 1165 mVolumePanel.postVolumeChanged(streamType, flags); 1166 1167 if ((flags & AudioManager.FLAG_FIXED_VOLUME) == 0) { 1168 oldIndex = (oldIndex + 5) / 10; 1169 index = (index + 5) / 10; 1170 Intent intent = new Intent(AudioManager.VOLUME_CHANGED_ACTION); 1171 intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, streamType); 1172 intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, index); 1173 intent.putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, oldIndex); 1174 sendBroadcastToAll(intent); 1175 } 1176 } 1177 1178 // UI update and Broadcast Intent 1179 private void sendMasterVolumeUpdate(int flags, int oldVolume, int newVolume) { 1180 mVolumePanel.postMasterVolumeChanged(flags); 1181 1182 Intent intent = new Intent(AudioManager.MASTER_VOLUME_CHANGED_ACTION); 1183 intent.putExtra(AudioManager.EXTRA_PREV_MASTER_VOLUME_VALUE, oldVolume); 1184 intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_VALUE, newVolume); 1185 sendBroadcastToAll(intent); 1186 } 1187 1188 // UI update and Broadcast Intent 1189 private void sendMasterMuteUpdate(boolean muted, int flags) { 1190 mVolumePanel.postMasterMuteChanged(flags); 1191 broadcastMasterMuteStatus(muted); 1192 } 1193 1194 private void broadcastMasterMuteStatus(boolean muted) { 1195 Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION); 1196 intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, muted); 1197 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT 1198 | Intent.FLAG_RECEIVER_REPLACE_PENDING); 1199 sendStickyBroadcastToAll(intent); 1200 } 1201 1202 /** 1203 * Sets the stream state's index, and posts a message to set system volume. 1204 * This will not call out to the UI. Assumes a valid stream type. 1205 * 1206 * @param streamType Type of the stream 1207 * @param index Desired volume index of the stream 1208 * @param device the device whose volume must be changed 1209 * @param force If true, set the volume even if the desired volume is same 1210 * as the current volume. 1211 */ 1212 private void setStreamVolumeInt(int streamType, 1213 int index, 1214 int device, 1215 boolean force) { 1216 VolumeStreamState streamState = mStreamStates[streamType]; 1217 1218 if (streamState.setIndex(index, device) || force) { 1219 // Post message to set system volume (it in turn will post a message 1220 // to persist). 1221 sendMsg(mAudioHandler, 1222 MSG_SET_DEVICE_VOLUME, 1223 SENDMSG_QUEUE, 1224 device, 1225 0, 1226 streamState, 1227 0); 1228 } 1229 } 1230 1231 /** @see AudioManager#setStreamSolo(int, boolean) */ 1232 public void setStreamSolo(int streamType, boolean state, IBinder cb) { 1233 if (mUseFixedVolume) { 1234 return; 1235 } 1236 1237 for (int stream = 0; stream < mStreamStates.length; stream++) { 1238 if (!isStreamAffectedByMute(stream) || stream == streamType) continue; 1239 mStreamStates[stream].mute(cb, state); 1240 } 1241 } 1242 1243 /** @see AudioManager#setStreamMute(int, boolean) */ 1244 public void setStreamMute(int streamType, boolean state, IBinder cb) { 1245 if (mUseFixedVolume) { 1246 return; 1247 } 1248 1249 if (isStreamAffectedByMute(streamType)) { 1250 mStreamStates[streamType].mute(cb, state); 1251 } 1252 } 1253 1254 /** get stream mute state. */ 1255 public boolean isStreamMute(int streamType) { 1256 return mStreamStates[streamType].isMuted(); 1257 } 1258 1259 /** @see AudioManager#setMasterMute(boolean, int) */ 1260 public void setMasterMute(boolean state, int flags, IBinder cb) { 1261 if (mUseFixedVolume) { 1262 return; 1263 } 1264 1265 if (state != AudioSystem.getMasterMute()) { 1266 AudioSystem.setMasterMute(state); 1267 // Post a persist master volume msg 1268 sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME_MUTE, SENDMSG_REPLACE, state ? 1 1269 : 0, 0, null, PERSIST_DELAY); 1270 sendMasterMuteUpdate(state, flags); 1271 } 1272 } 1273 1274 /** get master mute state. */ 1275 public boolean isMasterMute() { 1276 return AudioSystem.getMasterMute(); 1277 } 1278 1279 protected static int getMaxStreamVolume(int streamType) { 1280 return MAX_STREAM_VOLUME[streamType]; 1281 } 1282 1283 /** @see AudioManager#getStreamVolume(int) */ 1284 public int getStreamVolume(int streamType) { 1285 ensureValidStreamType(streamType); 1286 int device = getDeviceForStream(streamType); 1287 int index = mStreamStates[streamType].getIndex(device); 1288 1289 // by convention getStreamVolume() returns 0 when a stream is muted. 1290 if (mStreamStates[streamType].isMuted()) { 1291 index = 0; 1292 } 1293 if (index != 0 && (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) && 1294 (device & mFixedVolumeDevices) != 0) { 1295 index = mStreamStates[streamType].getMaxIndex(); 1296 } 1297 return (index + 5) / 10; 1298 } 1299 1300 public int getMasterVolume() { 1301 if (isMasterMute()) return 0; 1302 return getLastAudibleMasterVolume(); 1303 } 1304 1305 public void setMasterVolume(int volume, int flags, String callingPackage) { 1306 if (mUseFixedVolume) { 1307 return; 1308 } 1309 1310 if (mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, Binder.getCallingUid(), 1311 callingPackage) != AppOpsManager.MODE_ALLOWED) { 1312 return; 1313 } 1314 1315 if (volume < 0) { 1316 volume = 0; 1317 } else if (volume > MAX_MASTER_VOLUME) { 1318 volume = MAX_MASTER_VOLUME; 1319 } 1320 doSetMasterVolume((float)volume / MAX_MASTER_VOLUME, flags); 1321 } 1322 1323 private void doSetMasterVolume(float volume, int flags) { 1324 // don't allow changing master volume when muted 1325 if (!AudioSystem.getMasterMute()) { 1326 int oldVolume = getMasterVolume(); 1327 AudioSystem.setMasterVolume(volume); 1328 1329 int newVolume = getMasterVolume(); 1330 if (newVolume != oldVolume) { 1331 // Post a persist master volume msg 1332 sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME, SENDMSG_REPLACE, 1333 Math.round(volume * (float)1000.0), 0, null, PERSIST_DELAY); 1334 } 1335 // Send the volume update regardless whether there was a change. 1336 sendMasterVolumeUpdate(flags, oldVolume, newVolume); 1337 } 1338 } 1339 1340 /** @see AudioManager#getStreamMaxVolume(int) */ 1341 public int getStreamMaxVolume(int streamType) { 1342 ensureValidStreamType(streamType); 1343 return (mStreamStates[streamType].getMaxIndex() + 5) / 10; 1344 } 1345 1346 public int getMasterMaxVolume() { 1347 return MAX_MASTER_VOLUME; 1348 } 1349 1350 /** Get last audible volume before stream was muted. */ 1351 public int getLastAudibleStreamVolume(int streamType) { 1352 ensureValidStreamType(streamType); 1353 int device = getDeviceForStream(streamType); 1354 return (mStreamStates[streamType].getIndex(device) + 5) / 10; 1355 } 1356 1357 /** Get last audible master volume before it was muted. */ 1358 public int getLastAudibleMasterVolume() { 1359 return Math.round(AudioSystem.getMasterVolume() * MAX_MASTER_VOLUME); 1360 } 1361 1362 /** @see AudioManager#getMasterStreamType() */ 1363 public int getMasterStreamType() { 1364 if (mVoiceCapable) { 1365 return AudioSystem.STREAM_RING; 1366 } else { 1367 return AudioSystem.STREAM_MUSIC; 1368 } 1369 } 1370 1371 /** @see AudioManager#getRingerMode() */ 1372 public int getRingerMode() { 1373 synchronized(mSettingsLock) { 1374 return mRingerMode; 1375 } 1376 } 1377 1378 private void ensureValidRingerMode(int ringerMode) { 1379 if (!AudioManager.isValidRingerMode(ringerMode)) { 1380 throw new IllegalArgumentException("Bad ringer mode " + ringerMode); 1381 } 1382 } 1383 1384 /** @see AudioManager#setRingerMode(int) */ 1385 public void setRingerMode(int ringerMode) { 1386 if (mUseFixedVolume) { 1387 return; 1388 } 1389 1390 if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) { 1391 ringerMode = AudioManager.RINGER_MODE_SILENT; 1392 } 1393 if (ringerMode != getRingerMode()) { 1394 setRingerModeInt(ringerMode, true); 1395 // Send sticky broadcast 1396 broadcastRingerMode(ringerMode); 1397 } 1398 } 1399 1400 private void setRingerModeInt(int ringerMode, boolean persist) { 1401 synchronized(mSettingsLock) { 1402 mRingerMode = ringerMode; 1403 } 1404 1405 // Mute stream if not previously muted by ringer mode and ringer mode 1406 // is not RINGER_MODE_NORMAL and stream is affected by ringer mode. 1407 // Unmute stream if previously muted by ringer mode and ringer mode 1408 // is RINGER_MODE_NORMAL or stream is not affected by ringer mode. 1409 int numStreamTypes = AudioSystem.getNumStreamTypes(); 1410 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { 1411 if (isStreamMutedByRingerMode(streamType)) { 1412 if (!isStreamAffectedByRingerMode(streamType) || 1413 ringerMode == AudioManager.RINGER_MODE_NORMAL) { 1414 // ring and notifications volume should never be 0 when not silenced 1415 // on voice capable devices 1416 if (mVoiceCapable && 1417 mStreamVolumeAlias[streamType] == AudioSystem.STREAM_RING) { 1418 synchronized (mStreamStates[streamType]) { 1419 Set set = mStreamStates[streamType].mIndex.entrySet(); 1420 Iterator i = set.iterator(); 1421 while (i.hasNext()) { 1422 Map.Entry entry = (Map.Entry)i.next(); 1423 if ((Integer)entry.getValue() == 0) { 1424 entry.setValue(10); 1425 } 1426 } 1427 } 1428 } 1429 mStreamStates[streamType].mute(null, false); 1430 mRingerModeMutedStreams &= ~(1 << streamType); 1431 } 1432 } else { 1433 if (isStreamAffectedByRingerMode(streamType) && 1434 ringerMode != AudioManager.RINGER_MODE_NORMAL) { 1435 mStreamStates[streamType].mute(null, true); 1436 mRingerModeMutedStreams |= (1 << streamType); 1437 } 1438 } 1439 } 1440 1441 // Post a persist ringer mode msg 1442 if (persist) { 1443 sendMsg(mAudioHandler, MSG_PERSIST_RINGER_MODE, 1444 SENDMSG_REPLACE, 0, 0, null, PERSIST_DELAY); 1445 } 1446 } 1447 1448 private void restoreMasterVolume() { 1449 if (mUseFixedVolume) { 1450 AudioSystem.setMasterVolume(1.0f); 1451 return; 1452 } 1453 if (mUseMasterVolume) { 1454 float volume = Settings.System.getFloatForUser(mContentResolver, 1455 Settings.System.VOLUME_MASTER, -1.0f, UserHandle.USER_CURRENT); 1456 if (volume >= 0.0f) { 1457 AudioSystem.setMasterVolume(volume); 1458 } 1459 } 1460 } 1461 1462 /** @see AudioManager#shouldVibrate(int) */ 1463 public boolean shouldVibrate(int vibrateType) { 1464 if (!mHasVibrator) return false; 1465 1466 switch (getVibrateSetting(vibrateType)) { 1467 1468 case AudioManager.VIBRATE_SETTING_ON: 1469 return getRingerMode() != AudioManager.RINGER_MODE_SILENT; 1470 1471 case AudioManager.VIBRATE_SETTING_ONLY_SILENT: 1472 return getRingerMode() == AudioManager.RINGER_MODE_VIBRATE; 1473 1474 case AudioManager.VIBRATE_SETTING_OFF: 1475 // return false, even for incoming calls 1476 return false; 1477 1478 default: 1479 return false; 1480 } 1481 } 1482 1483 /** @see AudioManager#getVibrateSetting(int) */ 1484 public int getVibrateSetting(int vibrateType) { 1485 if (!mHasVibrator) return AudioManager.VIBRATE_SETTING_OFF; 1486 return (mVibrateSetting >> (vibrateType * 2)) & 3; 1487 } 1488 1489 /** @see AudioManager#setVibrateSetting(int, int) */ 1490 public void setVibrateSetting(int vibrateType, int vibrateSetting) { 1491 1492 if (!mHasVibrator) return; 1493 1494 mVibrateSetting = getValueForVibrateSetting(mVibrateSetting, vibrateType, vibrateSetting); 1495 1496 // Broadcast change 1497 broadcastVibrateSetting(vibrateType); 1498 1499 } 1500 1501 /** 1502 * @see #setVibrateSetting(int, int) 1503 */ 1504 public static int getValueForVibrateSetting(int existingValue, int vibrateType, 1505 int vibrateSetting) { 1506 1507 // First clear the existing setting. Each vibrate type has two bits in 1508 // the value. Note '3' is '11' in binary. 1509 existingValue &= ~(3 << (vibrateType * 2)); 1510 1511 // Set into the old value 1512 existingValue |= (vibrateSetting & 3) << (vibrateType * 2); 1513 1514 return existingValue; 1515 } 1516 1517 private class SetModeDeathHandler implements IBinder.DeathRecipient { 1518 private IBinder mCb; // To be notified of client's death 1519 private int mPid; 1520 private int mMode = AudioSystem.MODE_NORMAL; // Current mode set by this client 1521 1522 SetModeDeathHandler(IBinder cb, int pid) { 1523 mCb = cb; 1524 mPid = pid; 1525 } 1526 1527 public void binderDied() { 1528 int newModeOwnerPid = 0; 1529 synchronized(mSetModeDeathHandlers) { 1530 Log.w(TAG, "setMode() client died"); 1531 int index = mSetModeDeathHandlers.indexOf(this); 1532 if (index < 0) { 1533 Log.w(TAG, "unregistered setMode() client died"); 1534 } else { 1535 newModeOwnerPid = setModeInt(AudioSystem.MODE_NORMAL, mCb, mPid); 1536 } 1537 } 1538 // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all 1539 // SCO connections not started by the application changing the mode 1540 if (newModeOwnerPid != 0) { 1541 final long ident = Binder.clearCallingIdentity(); 1542 disconnectBluetoothSco(newModeOwnerPid); 1543 Binder.restoreCallingIdentity(ident); 1544 } 1545 } 1546 1547 public int getPid() { 1548 return mPid; 1549 } 1550 1551 public void setMode(int mode) { 1552 mMode = mode; 1553 } 1554 1555 public int getMode() { 1556 return mMode; 1557 } 1558 1559 public IBinder getBinder() { 1560 return mCb; 1561 } 1562 } 1563 1564 /** @see AudioManager#setMode(int) */ 1565 public void setMode(int mode, IBinder cb) { 1566 if (!checkAudioSettingsPermission("setMode()")) { 1567 return; 1568 } 1569 1570 if (mode < AudioSystem.MODE_CURRENT || mode >= AudioSystem.NUM_MODES) { 1571 return; 1572 } 1573 1574 int newModeOwnerPid = 0; 1575 synchronized(mSetModeDeathHandlers) { 1576 if (mode == AudioSystem.MODE_CURRENT) { 1577 mode = mMode; 1578 } 1579 newModeOwnerPid = setModeInt(mode, cb, Binder.getCallingPid()); 1580 } 1581 // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all 1582 // SCO connections not started by the application changing the mode 1583 if (newModeOwnerPid != 0) { 1584 disconnectBluetoothSco(newModeOwnerPid); 1585 } 1586 } 1587 1588 // must be called synchronized on mSetModeDeathHandlers 1589 // setModeInt() returns a valid PID if the audio mode was successfully set to 1590 // any mode other than NORMAL. 1591 int setModeInt(int mode, IBinder cb, int pid) { 1592 int newModeOwnerPid = 0; 1593 if (cb == null) { 1594 Log.e(TAG, "setModeInt() called with null binder"); 1595 return newModeOwnerPid; 1596 } 1597 1598 SetModeDeathHandler hdlr = null; 1599 Iterator iter = mSetModeDeathHandlers.iterator(); 1600 while (iter.hasNext()) { 1601 SetModeDeathHandler h = (SetModeDeathHandler)iter.next(); 1602 if (h.getPid() == pid) { 1603 hdlr = h; 1604 // Remove from client list so that it is re-inserted at top of list 1605 iter.remove(); 1606 hdlr.getBinder().unlinkToDeath(hdlr, 0); 1607 break; 1608 } 1609 } 1610 int status = AudioSystem.AUDIO_STATUS_OK; 1611 do { 1612 if (mode == AudioSystem.MODE_NORMAL) { 1613 // get new mode from client at top the list if any 1614 if (!mSetModeDeathHandlers.isEmpty()) { 1615 hdlr = mSetModeDeathHandlers.get(0); 1616 cb = hdlr.getBinder(); 1617 mode = hdlr.getMode(); 1618 } 1619 } else { 1620 if (hdlr == null) { 1621 hdlr = new SetModeDeathHandler(cb, pid); 1622 } 1623 // Register for client death notification 1624 try { 1625 cb.linkToDeath(hdlr, 0); 1626 } catch (RemoteException e) { 1627 // Client has died! 1628 Log.w(TAG, "setMode() could not link to "+cb+" binder death"); 1629 } 1630 1631 // Last client to call setMode() is always at top of client list 1632 // as required by SetModeDeathHandler.binderDied() 1633 mSetModeDeathHandlers.add(0, hdlr); 1634 hdlr.setMode(mode); 1635 } 1636 1637 if (mode != mMode) { 1638 status = AudioSystem.setPhoneState(mode); 1639 if (status == AudioSystem.AUDIO_STATUS_OK) { 1640 mMode = mode; 1641 } else { 1642 if (hdlr != null) { 1643 mSetModeDeathHandlers.remove(hdlr); 1644 cb.unlinkToDeath(hdlr, 0); 1645 } 1646 // force reading new top of mSetModeDeathHandlers stack 1647 mode = AudioSystem.MODE_NORMAL; 1648 } 1649 } else { 1650 status = AudioSystem.AUDIO_STATUS_OK; 1651 } 1652 } while (status != AudioSystem.AUDIO_STATUS_OK && !mSetModeDeathHandlers.isEmpty()); 1653 1654 if (status == AudioSystem.AUDIO_STATUS_OK) { 1655 if (mode != AudioSystem.MODE_NORMAL) { 1656 if (mSetModeDeathHandlers.isEmpty()) { 1657 Log.e(TAG, "setMode() different from MODE_NORMAL with empty mode client stack"); 1658 } else { 1659 newModeOwnerPid = mSetModeDeathHandlers.get(0).getPid(); 1660 } 1661 } 1662 int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE); 1663 if (streamType == STREAM_REMOTE_MUSIC) { 1664 // here handle remote media playback the same way as local playback 1665 streamType = AudioManager.STREAM_MUSIC; 1666 } 1667 int device = getDeviceForStream(streamType); 1668 int index = mStreamStates[mStreamVolumeAlias[streamType]].getIndex(device); 1669 setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, true); 1670 1671 updateStreamVolumeAlias(true /*updateVolumes*/); 1672 } 1673 return newModeOwnerPid; 1674 } 1675 1676 /** @see AudioManager#getMode() */ 1677 public int getMode() { 1678 return mMode; 1679 } 1680 1681 //========================================================================================== 1682 // Sound Effects 1683 //========================================================================================== 1684 1685 private static final String TAG_AUDIO_ASSETS = "audio_assets"; 1686 private static final String ATTR_VERSION = "version"; 1687 private static final String TAG_GROUP = "group"; 1688 private static final String ATTR_GROUP_NAME = "name"; 1689 private static final String TAG_ASSET = "asset"; 1690 private static final String ATTR_ASSET_ID = "id"; 1691 private static final String ATTR_ASSET_FILE = "file"; 1692 1693 private static final String ASSET_FILE_VERSION = "1.0"; 1694 private static final String GROUP_TOUCH_SOUNDS = "touch_sounds"; 1695 1696 private static final int SOUND_EFECTS_LOAD_TIMEOUT_MS = 5000; 1697 1698 class LoadSoundEffectReply { 1699 public int mStatus = 1; 1700 }; 1701 1702 private void loadTouchSoundAssetDefaults() { 1703 SOUND_EFFECT_FILES.add("Effect_Tick.ogg"); 1704 for (int i = 0; i < AudioManager.NUM_SOUND_EFFECTS; i++) { 1705 SOUND_EFFECT_FILES_MAP[i][0] = 0; 1706 SOUND_EFFECT_FILES_MAP[i][1] = -1; 1707 } 1708 } 1709 1710 private void loadTouchSoundAssets() { 1711 XmlResourceParser parser = null; 1712 1713 // only load assets once. 1714 if (!SOUND_EFFECT_FILES.isEmpty()) { 1715 return; 1716 } 1717 1718 loadTouchSoundAssetDefaults(); 1719 1720 try { 1721 parser = mContext.getResources().getXml(com.android.internal.R.xml.audio_assets); 1722 1723 XmlUtils.beginDocument(parser, TAG_AUDIO_ASSETS); 1724 String version = parser.getAttributeValue(null, ATTR_VERSION); 1725 boolean inTouchSoundsGroup = false; 1726 1727 if (ASSET_FILE_VERSION.equals(version)) { 1728 while (true) { 1729 XmlUtils.nextElement(parser); 1730 String element = parser.getName(); 1731 if (element == null) { 1732 break; 1733 } 1734 if (element.equals(TAG_GROUP)) { 1735 String name = parser.getAttributeValue(null, ATTR_GROUP_NAME); 1736 if (GROUP_TOUCH_SOUNDS.equals(name)) { 1737 inTouchSoundsGroup = true; 1738 break; 1739 } 1740 } 1741 } 1742 while (inTouchSoundsGroup) { 1743 XmlUtils.nextElement(parser); 1744 String element = parser.getName(); 1745 if (element == null) { 1746 break; 1747 } 1748 if (element.equals(TAG_ASSET)) { 1749 String id = parser.getAttributeValue(null, ATTR_ASSET_ID); 1750 String file = parser.getAttributeValue(null, ATTR_ASSET_FILE); 1751 int fx; 1752 1753 try { 1754 Field field = AudioManager.class.getField(id); 1755 fx = field.getInt(null); 1756 } catch (Exception e) { 1757 Log.w(TAG, "Invalid touch sound ID: "+id); 1758 continue; 1759 } 1760 1761 int i = SOUND_EFFECT_FILES.indexOf(file); 1762 if (i == -1) { 1763 i = SOUND_EFFECT_FILES.size(); 1764 SOUND_EFFECT_FILES.add(file); 1765 } 1766 SOUND_EFFECT_FILES_MAP[fx][0] = i; 1767 } else { 1768 break; 1769 } 1770 } 1771 } 1772 } catch (Resources.NotFoundException e) { 1773 Log.w(TAG, "audio assets file not found", e); 1774 } catch (XmlPullParserException e) { 1775 Log.w(TAG, "XML parser exception reading touch sound assets", e); 1776 } catch (IOException e) { 1777 Log.w(TAG, "I/O exception reading touch sound assets", e); 1778 } finally { 1779 if (parser != null) { 1780 parser.close(); 1781 } 1782 } 1783 } 1784 1785 /** @see AudioManager#playSoundEffect(int) */ 1786 public void playSoundEffect(int effectType) { 1787 playSoundEffectVolume(effectType, -1.0f); 1788 } 1789 1790 /** @see AudioManager#playSoundEffect(int, float) */ 1791 public void playSoundEffectVolume(int effectType, float volume) { 1792 sendMsg(mAudioHandler, MSG_PLAY_SOUND_EFFECT, SENDMSG_QUEUE, 1793 effectType, (int) (volume * 1000), null, 0); 1794 } 1795 1796 /** 1797 * Loads samples into the soundpool. 1798 * This method must be called at first when sound effects are enabled 1799 */ 1800 public boolean loadSoundEffects() { 1801 int attempts = 3; 1802 LoadSoundEffectReply reply = new LoadSoundEffectReply(); 1803 1804 synchronized (reply) { 1805 sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, reply, 0); 1806 while ((reply.mStatus == 1) && (attempts-- > 0)) { 1807 try { 1808 reply.wait(SOUND_EFECTS_LOAD_TIMEOUT_MS); 1809 } catch (InterruptedException e) { 1810 Log.w(TAG, "loadSoundEffects Interrupted while waiting sound pool loaded."); 1811 } 1812 } 1813 } 1814 return (reply.mStatus == 0); 1815 } 1816 1817 /** 1818 * Unloads samples from the sound pool. 1819 * This method can be called to free some memory when 1820 * sound effects are disabled. 1821 */ 1822 public void unloadSoundEffects() { 1823 sendMsg(mAudioHandler, MSG_UNLOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, null, 0); 1824 } 1825 1826 class SoundPoolListenerThread extends Thread { 1827 public SoundPoolListenerThread() { 1828 super("SoundPoolListenerThread"); 1829 } 1830 1831 @Override 1832 public void run() { 1833 1834 Looper.prepare(); 1835 mSoundPoolLooper = Looper.myLooper(); 1836 1837 synchronized (mSoundEffectsLock) { 1838 if (mSoundPool != null) { 1839 mSoundPoolCallBack = new SoundPoolCallback(); 1840 mSoundPool.setOnLoadCompleteListener(mSoundPoolCallBack); 1841 } 1842 mSoundEffectsLock.notify(); 1843 } 1844 Looper.loop(); 1845 } 1846 } 1847 1848 private final class SoundPoolCallback implements 1849 android.media.SoundPool.OnLoadCompleteListener { 1850 1851 int mStatus = 1; // 1 means neither error nor last sample loaded yet 1852 List<Integer> mSamples = new ArrayList<Integer>(); 1853 1854 public int status() { 1855 return mStatus; 1856 } 1857 1858 public void setSamples(int[] samples) { 1859 for (int i = 0; i < samples.length; i++) { 1860 // do not wait ack for samples rejected upfront by SoundPool 1861 if (samples[i] > 0) { 1862 mSamples.add(samples[i]); 1863 } 1864 } 1865 } 1866 1867 public void onLoadComplete(SoundPool soundPool, int sampleId, int status) { 1868 synchronized (mSoundEffectsLock) { 1869 int i = mSamples.indexOf(sampleId); 1870 if (i >= 0) { 1871 mSamples.remove(i); 1872 } 1873 if ((status != 0) || mSamples. isEmpty()) { 1874 mStatus = status; 1875 mSoundEffectsLock.notify(); 1876 } 1877 } 1878 } 1879 } 1880 1881 /** @see AudioManager#reloadAudioSettings() */ 1882 public void reloadAudioSettings() { 1883 readAudioSettings(false /*userSwitch*/); 1884 } 1885 1886 private void readAudioSettings(boolean userSwitch) { 1887 // restore ringer mode, ringer mode affected streams, mute affected streams and vibrate settings 1888 readPersistedSettings(); 1889 1890 // restore volume settings 1891 int numStreamTypes = AudioSystem.getNumStreamTypes(); 1892 for (int streamType = 0; streamType < numStreamTypes; streamType++) { 1893 VolumeStreamState streamState = mStreamStates[streamType]; 1894 1895 if (userSwitch && mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) { 1896 continue; 1897 } 1898 1899 synchronized (streamState) { 1900 streamState.readSettings(); 1901 1902 // unmute stream that was muted but is not affect by mute anymore 1903 if (streamState.isMuted() && ((!isStreamAffectedByMute(streamType) && 1904 !isStreamMutedByRingerMode(streamType)) || mUseFixedVolume)) { 1905 int size = streamState.mDeathHandlers.size(); 1906 for (int i = 0; i < size; i++) { 1907 streamState.mDeathHandlers.get(i).mMuteCount = 1; 1908 streamState.mDeathHandlers.get(i).mute(false); 1909 } 1910 } 1911 } 1912 } 1913 1914 // apply new ringer mode before checking volume for alias streams so that streams 1915 // muted by ringer mode have the correct volume 1916 setRingerModeInt(getRingerMode(), false); 1917 1918 checkAllAliasStreamVolumes(); 1919 1920 synchronized (mSafeMediaVolumeState) { 1921 if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) { 1922 enforceSafeMediaVolume(); 1923 } 1924 } 1925 } 1926 1927 /** @see AudioManager#setSpeakerphoneOn(boolean) */ 1928 public void setSpeakerphoneOn(boolean on){ 1929 if (!checkAudioSettingsPermission("setSpeakerphoneOn()")) { 1930 return; 1931 } 1932 1933 if (on) { 1934 if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) { 1935 sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, 1936 AudioSystem.FOR_RECORD, AudioSystem.FORCE_NONE, null, 0); 1937 } 1938 mForcedUseForComm = AudioSystem.FORCE_SPEAKER; 1939 } else if (mForcedUseForComm == AudioSystem.FORCE_SPEAKER){ 1940 mForcedUseForComm = AudioSystem.FORCE_NONE; 1941 } 1942 1943 sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, 1944 AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, null, 0); 1945 } 1946 1947 /** @see AudioManager#isSpeakerphoneOn() */ 1948 public boolean isSpeakerphoneOn() { 1949 return (mForcedUseForComm == AudioSystem.FORCE_SPEAKER); 1950 } 1951 1952 /** @see AudioManager#setBluetoothScoOn(boolean) */ 1953 public void setBluetoothScoOn(boolean on){ 1954 if (!checkAudioSettingsPermission("setBluetoothScoOn()")) { 1955 return; 1956 } 1957 1958 if (on) { 1959 mForcedUseForComm = AudioSystem.FORCE_BT_SCO; 1960 } else if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) { 1961 mForcedUseForComm = AudioSystem.FORCE_NONE; 1962 } 1963 1964 sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, 1965 AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, null, 0); 1966 sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, 1967 AudioSystem.FOR_RECORD, mForcedUseForComm, null, 0); 1968 } 1969 1970 /** @see AudioManager#isBluetoothScoOn() */ 1971 public boolean isBluetoothScoOn() { 1972 return (mForcedUseForComm == AudioSystem.FORCE_BT_SCO); 1973 } 1974 1975 /** @see AudioManager#setBluetoothA2dpOn(boolean) */ 1976 public void setBluetoothA2dpOn(boolean on) { 1977 synchronized (mBluetoothA2dpEnabledLock) { 1978 mBluetoothA2dpEnabled = on; 1979 sendMsg(mAudioHandler, MSG_SET_FORCE_BT_A2DP_USE, SENDMSG_QUEUE, 1980 AudioSystem.FOR_MEDIA, 1981 mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP, 1982 null, 0); 1983 } 1984 } 1985 1986 /** @see AudioManager#isBluetoothA2dpOn() */ 1987 public boolean isBluetoothA2dpOn() { 1988 synchronized (mBluetoothA2dpEnabledLock) { 1989 return mBluetoothA2dpEnabled; 1990 } 1991 } 1992 1993 /** @see AudioManager#startBluetoothSco() */ 1994 public void startBluetoothSco(IBinder cb, int targetSdkVersion){ 1995 if (!checkAudioSettingsPermission("startBluetoothSco()") || 1996 !mBootCompleted) { 1997 return; 1998 } 1999 ScoClient client = getScoClient(cb, true); 2000 // The calling identity must be cleared before calling ScoClient.incCount(). 2001 // inCount() calls requestScoState() which in turn can call BluetoothHeadset APIs 2002 // and this must be done on behalf of system server to make sure permissions are granted. 2003 // The caller identity must be cleared after getScoClient() because it is needed if a new 2004 // client is created. 2005 final long ident = Binder.clearCallingIdentity(); 2006 client.incCount(targetSdkVersion); 2007 Binder.restoreCallingIdentity(ident); 2008 } 2009 2010 /** @see AudioManager#stopBluetoothSco() */ 2011 public void stopBluetoothSco(IBinder cb){ 2012 if (!checkAudioSettingsPermission("stopBluetoothSco()") || 2013 !mBootCompleted) { 2014 return; 2015 } 2016 ScoClient client = getScoClient(cb, false); 2017 // The calling identity must be cleared before calling ScoClient.decCount(). 2018 // decCount() calls requestScoState() which in turn can call BluetoothHeadset APIs 2019 // and this must be done on behalf of system server to make sure permissions are granted. 2020 final long ident = Binder.clearCallingIdentity(); 2021 if (client != null) { 2022 client.decCount(); 2023 } 2024 Binder.restoreCallingIdentity(ident); 2025 } 2026 2027 2028 private class ScoClient implements IBinder.DeathRecipient { 2029 private IBinder mCb; // To be notified of client's death 2030 private int mCreatorPid; 2031 private int mStartcount; // number of SCO connections started by this client 2032 2033 ScoClient(IBinder cb) { 2034 mCb = cb; 2035 mCreatorPid = Binder.getCallingPid(); 2036 mStartcount = 0; 2037 } 2038 2039 public void binderDied() { 2040 synchronized(mScoClients) { 2041 Log.w(TAG, "SCO client died"); 2042 int index = mScoClients.indexOf(this); 2043 if (index < 0) { 2044 Log.w(TAG, "unregistered SCO client died"); 2045 } else { 2046 clearCount(true); 2047 mScoClients.remove(this); 2048 } 2049 } 2050 } 2051 2052 public void incCount(int targetSdkVersion) { 2053 synchronized(mScoClients) { 2054 requestScoState(BluetoothHeadset.STATE_AUDIO_CONNECTED, targetSdkVersion); 2055 if (mStartcount == 0) { 2056 try { 2057 mCb.linkToDeath(this, 0); 2058 } catch (RemoteException e) { 2059 // client has already died! 2060 Log.w(TAG, "ScoClient incCount() could not link to "+mCb+" binder death"); 2061 } 2062 } 2063 mStartcount++; 2064 } 2065 } 2066 2067 public void decCount() { 2068 synchronized(mScoClients) { 2069 if (mStartcount == 0) { 2070 Log.w(TAG, "ScoClient.decCount() already 0"); 2071 } else { 2072 mStartcount--; 2073 if (mStartcount == 0) { 2074 try { 2075 mCb.unlinkToDeath(this, 0); 2076 } catch (NoSuchElementException e) { 2077 Log.w(TAG, "decCount() going to 0 but not registered to binder"); 2078 } 2079 } 2080 requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, 0); 2081 } 2082 } 2083 } 2084 2085 public void clearCount(boolean stopSco) { 2086 synchronized(mScoClients) { 2087 if (mStartcount != 0) { 2088 try { 2089 mCb.unlinkToDeath(this, 0); 2090 } catch (NoSuchElementException e) { 2091 Log.w(TAG, "clearCount() mStartcount: "+mStartcount+" != 0 but not registered to binder"); 2092 } 2093 } 2094 mStartcount = 0; 2095 if (stopSco) { 2096 requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, 0); 2097 } 2098 } 2099 } 2100 2101 public int getCount() { 2102 return mStartcount; 2103 } 2104 2105 public IBinder getBinder() { 2106 return mCb; 2107 } 2108 2109 public int getPid() { 2110 return mCreatorPid; 2111 } 2112 2113 public int totalCount() { 2114 synchronized(mScoClients) { 2115 int count = 0; 2116 int size = mScoClients.size(); 2117 for (int i = 0; i < size; i++) { 2118 count += mScoClients.get(i).getCount(); 2119 } 2120 return count; 2121 } 2122 } 2123 2124 private void requestScoState(int state, int targetSdkVersion) { 2125 checkScoAudioState(); 2126 if (totalCount() == 0) { 2127 if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) { 2128 // Make sure that the state transitions to CONNECTING even if we cannot initiate 2129 // the connection. 2130 broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTING); 2131 // Accept SCO audio activation only in NORMAL audio mode or if the mode is 2132 // currently controlled by the same client process. 2133 synchronized(mSetModeDeathHandlers) { 2134 if ((mSetModeDeathHandlers.isEmpty() || 2135 mSetModeDeathHandlers.get(0).getPid() == mCreatorPid) && 2136 (mScoAudioState == SCO_STATE_INACTIVE || 2137 mScoAudioState == SCO_STATE_DEACTIVATE_REQ)) { 2138 if (mScoAudioState == SCO_STATE_INACTIVE) { 2139 mScoAudioMode = 2140 (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR2) ? 2141 SCO_MODE_VIRTUAL_CALL : SCO_MODE_RAW; 2142 if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) { 2143 boolean status; 2144 if (mScoAudioMode == SCO_MODE_RAW) { 2145 status = mBluetoothHeadset.connectAudio(); 2146 } else { 2147 status = mBluetoothHeadset.startScoUsingVirtualVoiceCall( 2148 mBluetoothHeadsetDevice); 2149 } 2150 if (status) { 2151 mScoAudioState = SCO_STATE_ACTIVE_INTERNAL; 2152 } else { 2153 broadcastScoConnectionState( 2154 AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 2155 } 2156 } else if (getBluetoothHeadset()) { 2157 mScoAudioState = SCO_STATE_ACTIVATE_REQ; 2158 } 2159 } else { 2160 mScoAudioState = SCO_STATE_ACTIVE_INTERNAL; 2161 broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTED); 2162 } 2163 } else { 2164 broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 2165 } 2166 } 2167 } else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED && 2168 (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL || 2169 mScoAudioState == SCO_STATE_ACTIVATE_REQ)) { 2170 if (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL) { 2171 if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) { 2172 boolean status; 2173 if (mScoAudioMode == SCO_MODE_RAW) { 2174 status = mBluetoothHeadset.disconnectAudio(); 2175 } else { 2176 status = mBluetoothHeadset.stopScoUsingVirtualVoiceCall( 2177 mBluetoothHeadsetDevice); 2178 } 2179 if (!status) { 2180 mScoAudioState = SCO_STATE_INACTIVE; 2181 broadcastScoConnectionState( 2182 AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 2183 } 2184 } else if (getBluetoothHeadset()) { 2185 mScoAudioState = SCO_STATE_DEACTIVATE_REQ; 2186 } 2187 } else { 2188 mScoAudioState = SCO_STATE_INACTIVE; 2189 broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 2190 } 2191 } 2192 } 2193 } 2194 } 2195 2196 private void checkScoAudioState() { 2197 if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null && 2198 mScoAudioState == SCO_STATE_INACTIVE && 2199 mBluetoothHeadset.getAudioState(mBluetoothHeadsetDevice) 2200 != BluetoothHeadset.STATE_AUDIO_DISCONNECTED) { 2201 mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL; 2202 } 2203 } 2204 2205 private ScoClient getScoClient(IBinder cb, boolean create) { 2206 synchronized(mScoClients) { 2207 ScoClient client = null; 2208 int size = mScoClients.size(); 2209 for (int i = 0; i < size; i++) { 2210 client = mScoClients.get(i); 2211 if (client.getBinder() == cb) 2212 return client; 2213 } 2214 if (create) { 2215 client = new ScoClient(cb); 2216 mScoClients.add(client); 2217 } 2218 return client; 2219 } 2220 } 2221 2222 public void clearAllScoClients(int exceptPid, boolean stopSco) { 2223 synchronized(mScoClients) { 2224 ScoClient savedClient = null; 2225 int size = mScoClients.size(); 2226 for (int i = 0; i < size; i++) { 2227 ScoClient cl = mScoClients.get(i); 2228 if (cl.getPid() != exceptPid) { 2229 cl.clearCount(stopSco); 2230 } else { 2231 savedClient = cl; 2232 } 2233 } 2234 mScoClients.clear(); 2235 if (savedClient != null) { 2236 mScoClients.add(savedClient); 2237 } 2238 } 2239 } 2240 2241 private boolean getBluetoothHeadset() { 2242 boolean result = false; 2243 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 2244 if (adapter != null) { 2245 result = adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener, 2246 BluetoothProfile.HEADSET); 2247 } 2248 // If we could not get a bluetooth headset proxy, send a failure message 2249 // without delay to reset the SCO audio state and clear SCO clients. 2250 // If we could get a proxy, send a delayed failure message that will reset our state 2251 // in case we don't receive onServiceConnected(). 2252 sendMsg(mAudioHandler, MSG_BT_HEADSET_CNCT_FAILED, 2253 SENDMSG_REPLACE, 0, 0, null, result ? BT_HEADSET_CNCT_TIMEOUT_MS : 0); 2254 return result; 2255 } 2256 2257 private void disconnectBluetoothSco(int exceptPid) { 2258 synchronized(mScoClients) { 2259 checkScoAudioState(); 2260 if (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL || 2261 mScoAudioState == SCO_STATE_DEACTIVATE_EXT_REQ) { 2262 if (mBluetoothHeadsetDevice != null) { 2263 if (mBluetoothHeadset != null) { 2264 if (!mBluetoothHeadset.stopVoiceRecognition( 2265 mBluetoothHeadsetDevice)) { 2266 sendMsg(mAudioHandler, MSG_BT_HEADSET_CNCT_FAILED, 2267 SENDMSG_REPLACE, 0, 0, null, 0); 2268 } 2269 } else if (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL && 2270 getBluetoothHeadset()) { 2271 mScoAudioState = SCO_STATE_DEACTIVATE_EXT_REQ; 2272 } 2273 } 2274 } else { 2275 clearAllScoClients(exceptPid, true); 2276 } 2277 } 2278 } 2279 2280 private void resetBluetoothSco() { 2281 synchronized(mScoClients) { 2282 clearAllScoClients(0, false); 2283 mScoAudioState = SCO_STATE_INACTIVE; 2284 broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 2285 } 2286 } 2287 2288 private void broadcastScoConnectionState(int state) { 2289 sendMsg(mAudioHandler, MSG_BROADCAST_BT_CONNECTION_STATE, 2290 SENDMSG_QUEUE, state, 0, null, 0); 2291 } 2292 2293 private void onBroadcastScoConnectionState(int state) { 2294 if (state != mScoConnectionState) { 2295 Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED); 2296 newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, state); 2297 newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_PREVIOUS_STATE, 2298 mScoConnectionState); 2299 sendStickyBroadcastToAll(newIntent); 2300 mScoConnectionState = state; 2301 } 2302 } 2303 2304 private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener = 2305 new BluetoothProfile.ServiceListener() { 2306 public void onServiceConnected(int profile, BluetoothProfile proxy) { 2307 BluetoothDevice btDevice; 2308 List<BluetoothDevice> deviceList; 2309 switch(profile) { 2310 case BluetoothProfile.A2DP: 2311 synchronized (mA2dpAvrcpLock) { 2312 mA2dp = (BluetoothA2dp) proxy; 2313 deviceList = mA2dp.getConnectedDevices(); 2314 if (deviceList.size() > 0) { 2315 btDevice = deviceList.get(0); 2316 synchronized (mConnectedDevices) { 2317 int state = mA2dp.getConnectionState(btDevice); 2318 int delay = checkSendBecomingNoisyIntent( 2319 AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 2320 (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0); 2321 queueMsgUnderWakeLock(mAudioHandler, 2322 MSG_SET_A2DP_CONNECTION_STATE, 2323 state, 2324 0, 2325 btDevice, 2326 delay); 2327 } 2328 } 2329 } 2330 break; 2331 2332 case BluetoothProfile.HEADSET: 2333 synchronized (mScoClients) { 2334 // Discard timeout message 2335 mAudioHandler.removeMessages(MSG_BT_HEADSET_CNCT_FAILED); 2336 mBluetoothHeadset = (BluetoothHeadset) proxy; 2337 deviceList = mBluetoothHeadset.getConnectedDevices(); 2338 if (deviceList.size() > 0) { 2339 mBluetoothHeadsetDevice = deviceList.get(0); 2340 } else { 2341 mBluetoothHeadsetDevice = null; 2342 } 2343 // Refresh SCO audio state 2344 checkScoAudioState(); 2345 // Continue pending action if any 2346 if (mScoAudioState == SCO_STATE_ACTIVATE_REQ || 2347 mScoAudioState == SCO_STATE_DEACTIVATE_REQ || 2348 mScoAudioState == SCO_STATE_DEACTIVATE_EXT_REQ) { 2349 boolean status = false; 2350 if (mBluetoothHeadsetDevice != null) { 2351 switch (mScoAudioState) { 2352 case SCO_STATE_ACTIVATE_REQ: 2353 mScoAudioState = SCO_STATE_ACTIVE_INTERNAL; 2354 if (mScoAudioMode == SCO_MODE_RAW) { 2355 status = mBluetoothHeadset.connectAudio(); 2356 } else { 2357 status = mBluetoothHeadset.startScoUsingVirtualVoiceCall( 2358 mBluetoothHeadsetDevice); 2359 } 2360 break; 2361 case SCO_STATE_DEACTIVATE_REQ: 2362 if (mScoAudioMode == SCO_MODE_RAW) { 2363 status = mBluetoothHeadset.disconnectAudio(); 2364 } else { 2365 status = mBluetoothHeadset.stopScoUsingVirtualVoiceCall( 2366 mBluetoothHeadsetDevice); 2367 } 2368 break; 2369 case SCO_STATE_DEACTIVATE_EXT_REQ: 2370 status = mBluetoothHeadset.stopVoiceRecognition( 2371 mBluetoothHeadsetDevice); 2372 } 2373 } 2374 if (!status) { 2375 sendMsg(mAudioHandler, MSG_BT_HEADSET_CNCT_FAILED, 2376 SENDMSG_REPLACE, 0, 0, null, 0); 2377 } 2378 } 2379 } 2380 break; 2381 2382 default: 2383 break; 2384 } 2385 } 2386 public void onServiceDisconnected(int profile) { 2387 switch(profile) { 2388 case BluetoothProfile.A2DP: 2389 synchronized (mA2dpAvrcpLock) { 2390 mA2dp = null; 2391 synchronized (mConnectedDevices) { 2392 if (mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP)) { 2393 makeA2dpDeviceUnavailableNow( 2394 mConnectedDevices.get(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP)); 2395 } 2396 } 2397 } 2398 break; 2399 2400 case BluetoothProfile.HEADSET: 2401 synchronized (mScoClients) { 2402 mBluetoothHeadset = null; 2403 } 2404 break; 2405 2406 default: 2407 break; 2408 } 2409 } 2410 }; 2411 2412 private void onCheckMusicActive() { 2413 synchronized (mSafeMediaVolumeState) { 2414 if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE) { 2415 int device = getDeviceForStream(AudioSystem.STREAM_MUSIC); 2416 2417 if ((device & mSafeMediaVolumeDevices) != 0) { 2418 sendMsg(mAudioHandler, 2419 MSG_CHECK_MUSIC_ACTIVE, 2420 SENDMSG_REPLACE, 2421 0, 2422 0, 2423 null, 2424 MUSIC_ACTIVE_POLL_PERIOD_MS); 2425 int index = mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(device); 2426 if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0) && 2427 (index > mSafeMediaVolumeIndex)) { 2428 // Approximate cumulative active music time 2429 mMusicActiveMs += MUSIC_ACTIVE_POLL_PERIOD_MS; 2430 if (mMusicActiveMs > UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX) { 2431 setSafeMediaVolumeEnabled(true); 2432 mMusicActiveMs = 0; 2433 } 2434 } 2435 } 2436 } 2437 } 2438 } 2439 2440 private void onConfigureSafeVolume(boolean force) { 2441 synchronized (mSafeMediaVolumeState) { 2442 int mcc = mContext.getResources().getConfiguration().mcc; 2443 if ((mMcc != mcc) || ((mMcc == 0) && force)) { 2444 mSafeMediaVolumeIndex = mContext.getResources().getInteger( 2445 com.android.internal.R.integer.config_safe_media_volume_index) * 10; 2446 boolean safeMediaVolumeEnabled = mContext.getResources().getBoolean( 2447 com.android.internal.R.bool.config_safe_media_volume_enabled); 2448 2449 // The persisted state is either "disabled" or "active": this is the state applied 2450 // next time we boot and cannot be "inactive" 2451 int persistedState; 2452 if (safeMediaVolumeEnabled) { 2453 persistedState = SAFE_MEDIA_VOLUME_ACTIVE; 2454 // The state can already be "inactive" here if the user has forced it before 2455 // the 30 seconds timeout for forced configuration. In this case we don't reset 2456 // it to "active". 2457 if (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_INACTIVE) { 2458 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE; 2459 enforceSafeMediaVolume(); 2460 } 2461 } else { 2462 persistedState = SAFE_MEDIA_VOLUME_DISABLED; 2463 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_DISABLED; 2464 } 2465 mMcc = mcc; 2466 sendMsg(mAudioHandler, 2467 MSG_PERSIST_SAFE_VOLUME_STATE, 2468 SENDMSG_QUEUE, 2469 persistedState, 2470 0, 2471 null, 2472 0); 2473 } 2474 } 2475 } 2476 2477 /////////////////////////////////////////////////////////////////////////// 2478 // Internal methods 2479 /////////////////////////////////////////////////////////////////////////// 2480 2481 /** 2482 * Checks if the adjustment should change ringer mode instead of just 2483 * adjusting volume. If so, this will set the proper ringer mode and volume 2484 * indices on the stream states. 2485 */ 2486 private boolean checkForRingerModeChange(int oldIndex, int direction, int step) { 2487 boolean adjustVolumeIndex = true; 2488 int ringerMode = getRingerMode(); 2489 2490 switch (ringerMode) { 2491 case RINGER_MODE_NORMAL: 2492 if (direction == AudioManager.ADJUST_LOWER) { 2493 if (mHasVibrator) { 2494 // "step" is the delta in internal index units corresponding to a 2495 // change of 1 in UI index units. 2496 // Because of rounding when rescaling from one stream index range to its alias 2497 // index range, we cannot simply test oldIndex == step: 2498 // (step <= oldIndex < 2 * step) is equivalent to: (old UI index == 1) 2499 if (step <= oldIndex && oldIndex < 2 * step) { 2500 ringerMode = RINGER_MODE_VIBRATE; 2501 } 2502 } else { 2503 // (oldIndex < step) is equivalent to (old UI index == 0) 2504 if ((oldIndex < step) && mPrevVolDirection != AudioManager.ADJUST_LOWER) { 2505 ringerMode = RINGER_MODE_SILENT; 2506 } 2507 } 2508 } 2509 break; 2510 case RINGER_MODE_VIBRATE: 2511 if (!mHasVibrator) { 2512 Log.e(TAG, "checkForRingerModeChange() current ringer mode is vibrate" + 2513 "but no vibrator is present"); 2514 break; 2515 } 2516 if ((direction == AudioManager.ADJUST_LOWER)) { 2517 if (mPrevVolDirection != AudioManager.ADJUST_LOWER) { 2518 ringerMode = RINGER_MODE_SILENT; 2519 } 2520 } else if (direction == AudioManager.ADJUST_RAISE) { 2521 ringerMode = RINGER_MODE_NORMAL; 2522 } 2523 adjustVolumeIndex = false; 2524 break; 2525 case RINGER_MODE_SILENT: 2526 if (direction == AudioManager.ADJUST_RAISE) { 2527 if (mHasVibrator) { 2528 ringerMode = RINGER_MODE_VIBRATE; 2529 } else { 2530 ringerMode = RINGER_MODE_NORMAL; 2531 } 2532 } 2533 adjustVolumeIndex = false; 2534 break; 2535 default: 2536 Log.e(TAG, "checkForRingerModeChange() wrong ringer mode: "+ringerMode); 2537 break; 2538 } 2539 2540 setRingerMode(ringerMode); 2541 2542 mPrevVolDirection = direction; 2543 2544 return adjustVolumeIndex; 2545 } 2546 2547 public boolean isStreamAffectedByRingerMode(int streamType) { 2548 return (mRingerModeAffectedStreams & (1 << streamType)) != 0; 2549 } 2550 2551 private boolean isStreamMutedByRingerMode(int streamType) { 2552 return (mRingerModeMutedStreams & (1 << streamType)) != 0; 2553 } 2554 2555 boolean updateRingerModeAffectedStreams() { 2556 int ringerModeAffectedStreams; 2557 // make sure settings for ringer mode are consistent with device type: non voice capable 2558 // devices (tablets) include media stream in silent mode whereas phones don't. 2559 ringerModeAffectedStreams = Settings.System.getIntForUser(mContentResolver, 2560 Settings.System.MODE_RINGER_STREAMS_AFFECTED, 2561 ((1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_NOTIFICATION)| 2562 (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)), 2563 UserHandle.USER_CURRENT); 2564 2565 // ringtone, notification and system streams are always affected by ringer mode 2566 ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_RING)| 2567 (1 << AudioSystem.STREAM_NOTIFICATION)| 2568 (1 << AudioSystem.STREAM_SYSTEM); 2569 2570 if (mVoiceCapable) { 2571 ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_MUSIC); 2572 } else { 2573 ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_MUSIC); 2574 } 2575 synchronized (mCameraSoundForced) { 2576 if (mCameraSoundForced) { 2577 ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED); 2578 } else { 2579 ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_SYSTEM_ENFORCED); 2580 } 2581 } 2582 if (mStreamVolumeAlias[AudioSystem.STREAM_DTMF] == AudioSystem.STREAM_RING) { 2583 ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_DTMF); 2584 } else { 2585 ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_DTMF); 2586 } 2587 2588 if (ringerModeAffectedStreams != mRingerModeAffectedStreams) { 2589 Settings.System.putIntForUser(mContentResolver, 2590 Settings.System.MODE_RINGER_STREAMS_AFFECTED, 2591 ringerModeAffectedStreams, 2592 UserHandle.USER_CURRENT); 2593 mRingerModeAffectedStreams = ringerModeAffectedStreams; 2594 return true; 2595 } 2596 return false; 2597 } 2598 2599 public boolean isStreamAffectedByMute(int streamType) { 2600 return (mMuteAffectedStreams & (1 << streamType)) != 0; 2601 } 2602 2603 private void ensureValidDirection(int direction) { 2604 if (direction < AudioManager.ADJUST_LOWER || direction > AudioManager.ADJUST_RAISE) { 2605 throw new IllegalArgumentException("Bad direction " + direction); 2606 } 2607 } 2608 2609 private void ensureValidSteps(int steps) { 2610 if (Math.abs(steps) > MAX_BATCH_VOLUME_ADJUST_STEPS) { 2611 throw new IllegalArgumentException("Bad volume adjust steps " + steps); 2612 } 2613 } 2614 2615 private void ensureValidStreamType(int streamType) { 2616 if (streamType < 0 || streamType >= mStreamStates.length) { 2617 throw new IllegalArgumentException("Bad stream type " + streamType); 2618 } 2619 } 2620 2621 private boolean isInCommunication() { 2622 boolean isOffhook = false; 2623 2624 if (mVoiceCapable) { 2625 try { 2626 ITelephony phone = ITelephony.Stub.asInterface(ServiceManager.checkService("phone")); 2627 if (phone != null) isOffhook = phone.isOffhook(); 2628 } catch (RemoteException e) { 2629 Log.w(TAG, "Couldn't connect to phone service", e); 2630 } 2631 } 2632 return (isOffhook || getMode() == AudioManager.MODE_IN_COMMUNICATION); 2633 } 2634 2635 /** 2636 * For code clarity for getActiveStreamType(int) 2637 * @param delay_ms max time since last STREAM_MUSIC activity to consider 2638 * @return true if STREAM_MUSIC is active in streams handled by AudioFlinger now or 2639 * in the last "delay_ms" ms. 2640 */ 2641 private boolean isAfMusicActiveRecently(int delay_ms) { 2642 return AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, delay_ms) 2643 || AudioSystem.isStreamActiveRemotely(AudioSystem.STREAM_MUSIC, delay_ms); 2644 } 2645 2646 private int getActiveStreamType(int suggestedStreamType) { 2647 if (mVoiceCapable) { 2648 if (isInCommunication()) { 2649 if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION) 2650 == AudioSystem.FORCE_BT_SCO) { 2651 // Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO..."); 2652 return AudioSystem.STREAM_BLUETOOTH_SCO; 2653 } else { 2654 // Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL..."); 2655 return AudioSystem.STREAM_VOICE_CALL; 2656 } 2657 } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) { 2658 if (isAfMusicActiveRecently(DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS)) { 2659 if (DEBUG_VOL) 2660 Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC stream active"); 2661 return AudioSystem.STREAM_MUSIC; 2662 } else 2663 if (mMediaFocusControl.checkUpdateRemoteStateIfActive(AudioSystem.STREAM_MUSIC)) 2664 { 2665 if (DEBUG_VOL) 2666 Log.v(TAG, "getActiveStreamType: Forcing STREAM_REMOTE_MUSIC"); 2667 return STREAM_REMOTE_MUSIC; 2668 } else { 2669 if (DEBUG_VOL) 2670 Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING b/c default"); 2671 return AudioSystem.STREAM_RING; 2672 } 2673 } else if (isAfMusicActiveRecently(0)) { 2674 if (DEBUG_VOL) 2675 Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC stream active"); 2676 return AudioSystem.STREAM_MUSIC; 2677 } else { 2678 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Returning suggested type " 2679 + suggestedStreamType); 2680 return suggestedStreamType; 2681 } 2682 } else { 2683 if (isInCommunication()) { 2684 if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION) 2685 == AudioSystem.FORCE_BT_SCO) { 2686 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO"); 2687 return AudioSystem.STREAM_BLUETOOTH_SCO; 2688 } else { 2689 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL"); 2690 return AudioSystem.STREAM_VOICE_CALL; 2691 } 2692 } else if (AudioSystem.isStreamActive(AudioSystem.STREAM_NOTIFICATION, 2693 DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS) || 2694 AudioSystem.isStreamActive(AudioSystem.STREAM_RING, 2695 DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS)) { 2696 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION"); 2697 return AudioSystem.STREAM_NOTIFICATION; 2698 } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) { 2699 if (isAfMusicActiveRecently(DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS)) { 2700 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: forcing STREAM_MUSIC"); 2701 return AudioSystem.STREAM_MUSIC; 2702 } else 2703 if (mMediaFocusControl.checkUpdateRemoteStateIfActive(AudioSystem.STREAM_MUSIC)) 2704 { 2705 if (DEBUG_VOL) 2706 Log.v(TAG, "getActiveStreamType: Forcing STREAM_REMOTE_MUSIC"); 2707 return STREAM_REMOTE_MUSIC; 2708 } else { 2709 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: using STREAM_MUSIC as default"); 2710 return AudioSystem.STREAM_MUSIC; 2711 } 2712 } else { 2713 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Returning suggested type " 2714 + suggestedStreamType); 2715 return suggestedStreamType; 2716 } 2717 } 2718 } 2719 2720 private void broadcastRingerMode(int ringerMode) { 2721 // Send sticky broadcast 2722 Intent broadcast = new Intent(AudioManager.RINGER_MODE_CHANGED_ACTION); 2723 broadcast.putExtra(AudioManager.EXTRA_RINGER_MODE, ringerMode); 2724 broadcast.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT 2725 | Intent.FLAG_RECEIVER_REPLACE_PENDING); 2726 sendStickyBroadcastToAll(broadcast); 2727 } 2728 2729 private void broadcastVibrateSetting(int vibrateType) { 2730 // Send broadcast 2731 if (ActivityManagerNative.isSystemReady()) { 2732 Intent broadcast = new Intent(AudioManager.VIBRATE_SETTING_CHANGED_ACTION); 2733 broadcast.putExtra(AudioManager.EXTRA_VIBRATE_TYPE, vibrateType); 2734 broadcast.putExtra(AudioManager.EXTRA_VIBRATE_SETTING, getVibrateSetting(vibrateType)); 2735 sendBroadcastToAll(broadcast); 2736 } 2737 } 2738 2739 // Message helper methods 2740 /** 2741 * Queue a message on the given handler's message queue, after acquiring the service wake lock. 2742 * Note that the wake lock needs to be released after the message has been handled. 2743 */ 2744 private void queueMsgUnderWakeLock(Handler handler, int msg, 2745 int arg1, int arg2, Object obj, int delay) { 2746 final long ident = Binder.clearCallingIdentity(); 2747 // Always acquire the wake lock as AudioService because it is released by the 2748 // message handler. 2749 mAudioEventWakeLock.acquire(); 2750 Binder.restoreCallingIdentity(ident); 2751 sendMsg(handler, msg, SENDMSG_QUEUE, arg1, arg2, obj, delay); 2752 } 2753 2754 private static void sendMsg(Handler handler, int msg, 2755 int existingMsgPolicy, int arg1, int arg2, Object obj, int delay) { 2756 2757 if (existingMsgPolicy == SENDMSG_REPLACE) { 2758 handler.removeMessages(msg); 2759 } else if (existingMsgPolicy == SENDMSG_NOOP && handler.hasMessages(msg)) { 2760 return; 2761 } 2762 2763 handler.sendMessageDelayed(handler.obtainMessage(msg, arg1, arg2, obj), delay); 2764 } 2765 2766 boolean checkAudioSettingsPermission(String method) { 2767 if (mContext.checkCallingOrSelfPermission("android.permission.MODIFY_AUDIO_SETTINGS") 2768 == PackageManager.PERMISSION_GRANTED) { 2769 return true; 2770 } 2771 String msg = "Audio Settings Permission Denial: " + method + " from pid=" 2772 + Binder.getCallingPid() 2773 + ", uid=" + Binder.getCallingUid(); 2774 Log.w(TAG, msg); 2775 return false; 2776 } 2777 2778 private int getDeviceForStream(int stream) { 2779 int device = AudioSystem.getDevicesForStream(stream); 2780 if ((device & (device - 1)) != 0) { 2781 // Multiple device selection is either: 2782 // - speaker + one other device: give priority to speaker in this case. 2783 // - one A2DP device + another device: happens with duplicated output. In this case 2784 // retain the device on the A2DP output as the other must not correspond to an active 2785 // selection if not the speaker. 2786 if ((device & AudioSystem.DEVICE_OUT_SPEAKER) != 0) { 2787 device = AudioSystem.DEVICE_OUT_SPEAKER; 2788 } else { 2789 device &= AudioSystem.DEVICE_OUT_ALL_A2DP; 2790 } 2791 } 2792 return device; 2793 } 2794 2795 public void setWiredDeviceConnectionState(int device, int state, String name) { 2796 synchronized (mConnectedDevices) { 2797 int delay = checkSendBecomingNoisyIntent(device, state); 2798 queueMsgUnderWakeLock(mAudioHandler, 2799 MSG_SET_WIRED_DEVICE_CONNECTION_STATE, 2800 device, 2801 state, 2802 name, 2803 delay); 2804 } 2805 } 2806 2807 public int setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state) 2808 { 2809 int delay; 2810 synchronized (mConnectedDevices) { 2811 delay = checkSendBecomingNoisyIntent(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 2812 (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0); 2813 queueMsgUnderWakeLock(mAudioHandler, 2814 MSG_SET_A2DP_CONNECTION_STATE, 2815 state, 2816 0, 2817 device, 2818 delay); 2819 } 2820 return delay; 2821 } 2822 2823 /////////////////////////////////////////////////////////////////////////// 2824 // Inner classes 2825 /////////////////////////////////////////////////////////////////////////// 2826 2827 public class VolumeStreamState { 2828 private final int mStreamType; 2829 2830 private String mVolumeIndexSettingName; 2831 private int mIndexMax; 2832 private final ConcurrentHashMap<Integer, Integer> mIndex = 2833 new ConcurrentHashMap<Integer, Integer>(8, 0.75f, 4); 2834 private ArrayList<VolumeDeathHandler> mDeathHandlers; //handles mute/solo clients death 2835 2836 private VolumeStreamState(String settingName, int streamType) { 2837 2838 mVolumeIndexSettingName = settingName; 2839 2840 mStreamType = streamType; 2841 mIndexMax = MAX_STREAM_VOLUME[streamType]; 2842 AudioSystem.initStreamVolume(streamType, 0, mIndexMax); 2843 mIndexMax *= 10; 2844 2845 // mDeathHandlers must be created before calling readSettings() 2846 mDeathHandlers = new ArrayList<VolumeDeathHandler>(); 2847 2848 readSettings(); 2849 } 2850 2851 public String getSettingNameForDevice(int device) { 2852 String name = mVolumeIndexSettingName; 2853 String suffix = AudioSystem.getDeviceName(device); 2854 if (suffix.isEmpty()) { 2855 return name; 2856 } 2857 return name + "_" + suffix; 2858 } 2859 2860 public synchronized void readSettings() { 2861 // force maximum volume on all streams if fixed volume property is set 2862 if (mUseFixedVolume) { 2863 mIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, mIndexMax); 2864 return; 2865 } 2866 // do not read system stream volume from settings: this stream is always aliased 2867 // to another stream type and its volume is never persisted. Values in settings can 2868 // only be stale values 2869 if ((mStreamType == AudioSystem.STREAM_SYSTEM) || 2870 (mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED)) { 2871 int index = 10 * AudioManager.DEFAULT_STREAM_VOLUME[mStreamType]; 2872 synchronized (mCameraSoundForced) { 2873 if (mCameraSoundForced) { 2874 index = mIndexMax; 2875 } 2876 } 2877 mIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, index); 2878 return; 2879 } 2880 2881 int remainingDevices = AudioSystem.DEVICE_OUT_ALL; 2882 2883 for (int i = 0; remainingDevices != 0; i++) { 2884 int device = (1 << i); 2885 if ((device & remainingDevices) == 0) { 2886 continue; 2887 } 2888 remainingDevices &= ~device; 2889 2890 // retrieve current volume for device 2891 String name = getSettingNameForDevice(device); 2892 // if no volume stored for current stream and device, use default volume if default 2893 // device, continue otherwise 2894 int defaultIndex = (device == AudioSystem.DEVICE_OUT_DEFAULT) ? 2895 AudioManager.DEFAULT_STREAM_VOLUME[mStreamType] : -1; 2896 int index = Settings.System.getIntForUser( 2897 mContentResolver, name, defaultIndex, UserHandle.USER_CURRENT); 2898 if (index == -1) { 2899 continue; 2900 } 2901 2902 // ignore settings for fixed volume devices: volume should always be at max or 0 2903 if ((mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_MUSIC) && 2904 ((device & mFixedVolumeDevices) != 0)) { 2905 mIndex.put(device, (index != 0) ? mIndexMax : 0); 2906 } else { 2907 mIndex.put(device, getValidIndex(10 * index)); 2908 } 2909 } 2910 } 2911 2912 public void applyDeviceVolume(int device) { 2913 int index; 2914 if (isMuted()) { 2915 index = 0; 2916 } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && 2917 mAvrcpAbsVolSupported) { 2918 index = (mIndexMax + 5)/10; 2919 } else { 2920 index = (getIndex(device) + 5)/10; 2921 } 2922 AudioSystem.setStreamVolumeIndex(mStreamType, index, device); 2923 } 2924 2925 public synchronized void applyAllVolumes() { 2926 // apply default volume first: by convention this will reset all 2927 // devices volumes in audio policy manager to the supplied value 2928 int index; 2929 if (isMuted()) { 2930 index = 0; 2931 } else { 2932 index = (getIndex(AudioSystem.DEVICE_OUT_DEFAULT) + 5)/10; 2933 } 2934 AudioSystem.setStreamVolumeIndex(mStreamType, index, AudioSystem.DEVICE_OUT_DEFAULT); 2935 // then apply device specific volumes 2936 Set set = mIndex.entrySet(); 2937 Iterator i = set.iterator(); 2938 while (i.hasNext()) { 2939 Map.Entry entry = (Map.Entry)i.next(); 2940 int device = ((Integer)entry.getKey()).intValue(); 2941 if (device != AudioSystem.DEVICE_OUT_DEFAULT) { 2942 if (isMuted()) { 2943 index = 0; 2944 } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && 2945 mAvrcpAbsVolSupported) { 2946 index = (mIndexMax + 5)/10; 2947 } else { 2948 index = ((Integer)entry.getValue() + 5)/10; 2949 } 2950 AudioSystem.setStreamVolumeIndex(mStreamType, index, device); 2951 } 2952 } 2953 } 2954 2955 public boolean adjustIndex(int deltaIndex, int device) { 2956 return setIndex(getIndex(device) + deltaIndex, 2957 device); 2958 } 2959 2960 public synchronized boolean setIndex(int index, int device) { 2961 int oldIndex = getIndex(device); 2962 index = getValidIndex(index); 2963 synchronized (mCameraSoundForced) { 2964 if ((mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED) && mCameraSoundForced) { 2965 index = mIndexMax; 2966 } 2967 } 2968 mIndex.put(device, index); 2969 2970 if (oldIndex != index) { 2971 // Apply change to all streams using this one as alias 2972 // if changing volume of current device, also change volume of current 2973 // device on aliased stream 2974 boolean currentDevice = (device == getDeviceForStream(mStreamType)); 2975 int numStreamTypes = AudioSystem.getNumStreamTypes(); 2976 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { 2977 if (streamType != mStreamType && 2978 mStreamVolumeAlias[streamType] == mStreamType) { 2979 int scaledIndex = rescaleIndex(index, mStreamType, streamType); 2980 mStreamStates[streamType].setIndex(scaledIndex, 2981 device); 2982 if (currentDevice) { 2983 mStreamStates[streamType].setIndex(scaledIndex, 2984 getDeviceForStream(streamType)); 2985 } 2986 } 2987 } 2988 return true; 2989 } else { 2990 return false; 2991 } 2992 } 2993 2994 public synchronized int getIndex(int device) { 2995 Integer index = mIndex.get(device); 2996 if (index == null) { 2997 // there is always an entry for AudioSystem.DEVICE_OUT_DEFAULT 2998 index = mIndex.get(AudioSystem.DEVICE_OUT_DEFAULT); 2999 } 3000 return index.intValue(); 3001 } 3002 3003 public int getMaxIndex() { 3004 return mIndexMax; 3005 } 3006 3007 public synchronized void setAllIndexes(VolumeStreamState srcStream) { 3008 int srcStreamType = srcStream.getStreamType(); 3009 // apply default device volume from source stream to all devices first in case 3010 // some devices are present in this stream state but not in source stream state 3011 int index = srcStream.getIndex(AudioSystem.DEVICE_OUT_DEFAULT); 3012 index = rescaleIndex(index, srcStreamType, mStreamType); 3013 Set set = mIndex.entrySet(); 3014 Iterator i = set.iterator(); 3015 while (i.hasNext()) { 3016 Map.Entry entry = (Map.Entry)i.next(); 3017 entry.setValue(index); 3018 } 3019 // Now apply actual volume for devices in source stream state 3020 set = srcStream.mIndex.entrySet(); 3021 i = set.iterator(); 3022 while (i.hasNext()) { 3023 Map.Entry entry = (Map.Entry)i.next(); 3024 int device = ((Integer)entry.getKey()).intValue(); 3025 index = ((Integer)entry.getValue()).intValue(); 3026 index = rescaleIndex(index, srcStreamType, mStreamType); 3027 3028 setIndex(index, device); 3029 } 3030 } 3031 3032 public synchronized void setAllIndexesToMax() { 3033 Set set = mIndex.entrySet(); 3034 Iterator i = set.iterator(); 3035 while (i.hasNext()) { 3036 Map.Entry entry = (Map.Entry)i.next(); 3037 entry.setValue(mIndexMax); 3038 } 3039 } 3040 3041 public synchronized void mute(IBinder cb, boolean state) { 3042 VolumeDeathHandler handler = getDeathHandler(cb, state); 3043 if (handler == null) { 3044 Log.e(TAG, "Could not get client death handler for stream: "+mStreamType); 3045 return; 3046 } 3047 handler.mute(state); 3048 } 3049 3050 public int getStreamType() { 3051 return mStreamType; 3052 } 3053 3054 private int getValidIndex(int index) { 3055 if (index < 0) { 3056 return 0; 3057 } else if (mUseFixedVolume || index > mIndexMax) { 3058 return mIndexMax; 3059 } 3060 3061 return index; 3062 } 3063 3064 private class VolumeDeathHandler implements IBinder.DeathRecipient { 3065 private IBinder mICallback; // To be notified of client's death 3066 private int mMuteCount; // Number of active mutes for this client 3067 3068 VolumeDeathHandler(IBinder cb) { 3069 mICallback = cb; 3070 } 3071 3072 // must be called while synchronized on parent VolumeStreamState 3073 public void mute(boolean state) { 3074 boolean updateVolume = false; 3075 if (state) { 3076 if (mMuteCount == 0) { 3077 // Register for client death notification 3078 try { 3079 // mICallback can be 0 if muted by AudioService 3080 if (mICallback != null) { 3081 mICallback.linkToDeath(this, 0); 3082 } 3083 VolumeStreamState.this.mDeathHandlers.add(this); 3084 // If the stream is not yet muted by any client, set level to 0 3085 if (!VolumeStreamState.this.isMuted()) { 3086 updateVolume = true; 3087 } 3088 } catch (RemoteException e) { 3089 // Client has died! 3090 binderDied(); 3091 return; 3092 } 3093 } else { 3094 Log.w(TAG, "stream: "+mStreamType+" was already muted by this client"); 3095 } 3096 mMuteCount++; 3097 } else { 3098 if (mMuteCount == 0) { 3099 Log.e(TAG, "unexpected unmute for stream: "+mStreamType); 3100 } else { 3101 mMuteCount--; 3102 if (mMuteCount == 0) { 3103 // Unregister from client death notification 3104 VolumeStreamState.this.mDeathHandlers.remove(this); 3105 // mICallback can be 0 if muted by AudioService 3106 if (mICallback != null) { 3107 mICallback.unlinkToDeath(this, 0); 3108 } 3109 if (!VolumeStreamState.this.isMuted()) { 3110 updateVolume = true; 3111 } 3112 } 3113 } 3114 } 3115 if (updateVolume) { 3116 sendMsg(mAudioHandler, 3117 MSG_SET_ALL_VOLUMES, 3118 SENDMSG_QUEUE, 3119 0, 3120 0, 3121 VolumeStreamState.this, 0); 3122 } 3123 } 3124 3125 public void binderDied() { 3126 Log.w(TAG, "Volume service client died for stream: "+mStreamType); 3127 if (mMuteCount != 0) { 3128 // Reset all active mute requests from this client. 3129 mMuteCount = 1; 3130 mute(false); 3131 } 3132 } 3133 } 3134 3135 private synchronized int muteCount() { 3136 int count = 0; 3137 int size = mDeathHandlers.size(); 3138 for (int i = 0; i < size; i++) { 3139 count += mDeathHandlers.get(i).mMuteCount; 3140 } 3141 return count; 3142 } 3143 3144 private synchronized boolean isMuted() { 3145 return muteCount() != 0; 3146 } 3147 3148 // only called by mute() which is already synchronized 3149 private VolumeDeathHandler getDeathHandler(IBinder cb, boolean state) { 3150 VolumeDeathHandler handler; 3151 int size = mDeathHandlers.size(); 3152 for (int i = 0; i < size; i++) { 3153 handler = mDeathHandlers.get(i); 3154 if (cb == handler.mICallback) { 3155 return handler; 3156 } 3157 } 3158 // If this is the first mute request for this client, create a new 3159 // client death handler. Otherwise, it is an out of sequence unmute request. 3160 if (state) { 3161 handler = new VolumeDeathHandler(cb); 3162 } else { 3163 Log.w(TAG, "stream was not muted by this client"); 3164 handler = null; 3165 } 3166 return handler; 3167 } 3168 3169 private void dump(PrintWriter pw) { 3170 pw.print(" Mute count: "); 3171 pw.println(muteCount()); 3172 pw.print(" Current: "); 3173 Set set = mIndex.entrySet(); 3174 Iterator i = set.iterator(); 3175 while (i.hasNext()) { 3176 Map.Entry entry = (Map.Entry)i.next(); 3177 pw.print(Integer.toHexString(((Integer)entry.getKey()).intValue()) 3178 + ": " + ((((Integer)entry.getValue()).intValue() + 5) / 10)+", "); 3179 } 3180 } 3181 } 3182 3183 /** Thread that handles native AudioSystem control. */ 3184 private class AudioSystemThread extends Thread { 3185 AudioSystemThread() { 3186 super("AudioService"); 3187 } 3188 3189 @Override 3190 public void run() { 3191 // Set this thread up so the handler will work on it 3192 Looper.prepare(); 3193 3194 synchronized(AudioService.this) { 3195 mAudioHandler = new AudioHandler(); 3196 3197 // Notify that the handler has been created 3198 AudioService.this.notify(); 3199 } 3200 3201 // Listen for volume change requests that are set by VolumePanel 3202 Looper.loop(); 3203 } 3204 } 3205 3206 /** Handles internal volume messages in separate volume thread. */ 3207 private class AudioHandler extends Handler { 3208 3209 private void setDeviceVolume(VolumeStreamState streamState, int device) { 3210 3211 // Apply volume 3212 streamState.applyDeviceVolume(device); 3213 3214 // Apply change to all streams using this one as alias 3215 int numStreamTypes = AudioSystem.getNumStreamTypes(); 3216 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { 3217 if (streamType != streamState.mStreamType && 3218 mStreamVolumeAlias[streamType] == streamState.mStreamType) { 3219 // Make sure volume is also maxed out on A2DP device for aliased stream 3220 // that may have a different device selected 3221 int streamDevice = getDeviceForStream(streamType); 3222 if ((device != streamDevice) && mAvrcpAbsVolSupported && 3223 ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0)) { 3224 mStreamStates[streamType].applyDeviceVolume(device); 3225 } 3226 mStreamStates[streamType].applyDeviceVolume(streamDevice); 3227 } 3228 } 3229 3230 // Post a persist volume msg 3231 sendMsg(mAudioHandler, 3232 MSG_PERSIST_VOLUME, 3233 SENDMSG_QUEUE, 3234 device, 3235 0, 3236 streamState, 3237 PERSIST_DELAY); 3238 3239 } 3240 3241 private void setAllVolumes(VolumeStreamState streamState) { 3242 3243 // Apply volume 3244 streamState.applyAllVolumes(); 3245 3246 // Apply change to all streams using this one as alias 3247 int numStreamTypes = AudioSystem.getNumStreamTypes(); 3248 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { 3249 if (streamType != streamState.mStreamType && 3250 mStreamVolumeAlias[streamType] == streamState.mStreamType) { 3251 mStreamStates[streamType].applyAllVolumes(); 3252 } 3253 } 3254 } 3255 3256 private void persistVolume(VolumeStreamState streamState, int device) { 3257 if (mUseFixedVolume) { 3258 return; 3259 } 3260 System.putIntForUser(mContentResolver, 3261 streamState.getSettingNameForDevice(device), 3262 (streamState.getIndex(device) + 5)/ 10, 3263 UserHandle.USER_CURRENT); 3264 } 3265 3266 private void persistRingerMode(int ringerMode) { 3267 if (mUseFixedVolume) { 3268 return; 3269 } 3270 Settings.Global.putInt(mContentResolver, Settings.Global.MODE_RINGER, ringerMode); 3271 } 3272 3273 private boolean onLoadSoundEffects() { 3274 int status; 3275 3276 synchronized (mSoundEffectsLock) { 3277 if (!mBootCompleted) { 3278 Log.w(TAG, "onLoadSoundEffects() called before boot complete"); 3279 return false; 3280 } 3281 3282 if (mSoundPool != null) { 3283 return true; 3284 } 3285 3286 loadTouchSoundAssets(); 3287 3288 mSoundPool = new SoundPool(NUM_SOUNDPOOL_CHANNELS, AudioSystem.STREAM_SYSTEM, 0); 3289 mSoundPoolCallBack = null; 3290 mSoundPoolListenerThread = new SoundPoolListenerThread(); 3291 mSoundPoolListenerThread.start(); 3292 int attempts = 3; 3293 while ((mSoundPoolCallBack == null) && (attempts-- > 0)) { 3294 try { 3295 // Wait for mSoundPoolCallBack to be set by the other thread 3296 mSoundEffectsLock.wait(SOUND_EFECTS_LOAD_TIMEOUT_MS); 3297 } catch (InterruptedException e) { 3298 Log.w(TAG, "Interrupted while waiting sound pool listener thread."); 3299 } 3300 } 3301 3302 if (mSoundPoolCallBack == null) { 3303 Log.w(TAG, "onLoadSoundEffects() SoundPool listener or thread creation error"); 3304 if (mSoundPoolLooper != null) { 3305 mSoundPoolLooper.quit(); 3306 mSoundPoolLooper = null; 3307 } 3308 mSoundPoolListenerThread = null; 3309 mSoundPool.release(); 3310 mSoundPool = null; 3311 return false; 3312 } 3313 /* 3314 * poolId table: The value -1 in this table indicates that corresponding 3315 * file (same index in SOUND_EFFECT_FILES[] has not been loaded. 3316 * Once loaded, the value in poolId is the sample ID and the same 3317 * sample can be reused for another effect using the same file. 3318 */ 3319 int[] poolId = new int[SOUND_EFFECT_FILES.size()]; 3320 for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) { 3321 poolId[fileIdx] = -1; 3322 } 3323 /* 3324 * Effects whose value in SOUND_EFFECT_FILES_MAP[effect][1] is -1 must be loaded. 3325 * If load succeeds, value in SOUND_EFFECT_FILES_MAP[effect][1] is > 0: 3326 * this indicates we have a valid sample loaded for this effect. 3327 */ 3328 3329 int numSamples = 0; 3330 for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) { 3331 // Do not load sample if this effect uses the MediaPlayer 3332 if (SOUND_EFFECT_FILES_MAP[effect][1] == 0) { 3333 continue; 3334 } 3335 if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == -1) { 3336 String filePath = Environment.getRootDirectory() 3337 + SOUND_EFFECTS_PATH 3338 + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effect][0]); 3339 int sampleId = mSoundPool.load(filePath, 0); 3340 if (sampleId <= 0) { 3341 Log.w(TAG, "Soundpool could not load file: "+filePath); 3342 } else { 3343 SOUND_EFFECT_FILES_MAP[effect][1] = sampleId; 3344 poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = sampleId; 3345 numSamples++; 3346 } 3347 } else { 3348 SOUND_EFFECT_FILES_MAP[effect][1] = 3349 poolId[SOUND_EFFECT_FILES_MAP[effect][0]]; 3350 } 3351 } 3352 // wait for all samples to be loaded 3353 if (numSamples > 0) { 3354 mSoundPoolCallBack.setSamples(poolId); 3355 3356 attempts = 3; 3357 status = 1; 3358 while ((status == 1) && (attempts-- > 0)) { 3359 try { 3360 mSoundEffectsLock.wait(SOUND_EFECTS_LOAD_TIMEOUT_MS); 3361 status = mSoundPoolCallBack.status(); 3362 } catch (InterruptedException e) { 3363 Log.w(TAG, "Interrupted while waiting sound pool callback."); 3364 } 3365 } 3366 } else { 3367 status = -1; 3368 } 3369 3370 if (mSoundPoolLooper != null) { 3371 mSoundPoolLooper.quit(); 3372 mSoundPoolLooper = null; 3373 } 3374 mSoundPoolListenerThread = null; 3375 if (status != 0) { 3376 Log.w(TAG, 3377 "onLoadSoundEffects(), Error "+status+ " while loading samples"); 3378 for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) { 3379 if (SOUND_EFFECT_FILES_MAP[effect][1] > 0) { 3380 SOUND_EFFECT_FILES_MAP[effect][1] = -1; 3381 } 3382 } 3383 3384 mSoundPool.release(); 3385 mSoundPool = null; 3386 } 3387 } 3388 return (status == 0); 3389 } 3390 3391 /** 3392 * Unloads samples from the sound pool. 3393 * This method can be called to free some memory when 3394 * sound effects are disabled. 3395 */ 3396 private void onUnloadSoundEffects() { 3397 synchronized (mSoundEffectsLock) { 3398 if (mSoundPool == null) { 3399 return; 3400 } 3401 3402 int[] poolId = new int[SOUND_EFFECT_FILES.size()]; 3403 for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) { 3404 poolId[fileIdx] = 0; 3405 } 3406 3407 for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) { 3408 if (SOUND_EFFECT_FILES_MAP[effect][1] <= 0) { 3409 continue; 3410 } 3411 if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == 0) { 3412 mSoundPool.unload(SOUND_EFFECT_FILES_MAP[effect][1]); 3413 SOUND_EFFECT_FILES_MAP[effect][1] = -1; 3414 poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = -1; 3415 } 3416 } 3417 mSoundPool.release(); 3418 mSoundPool = null; 3419 } 3420 } 3421 3422 private void onPlaySoundEffect(int effectType, int volume) { 3423 synchronized (mSoundEffectsLock) { 3424 3425 onLoadSoundEffects(); 3426 3427 if (mSoundPool == null) { 3428 return; 3429 } 3430 float volFloat; 3431 // use default if volume is not specified by caller 3432 if (volume < 0) { 3433 volFloat = (float)Math.pow(10, (float)sSoundEffectVolumeDb/20); 3434 } else { 3435 volFloat = (float) volume / 1000.0f; 3436 } 3437 3438 if (SOUND_EFFECT_FILES_MAP[effectType][1] > 0) { 3439 mSoundPool.play(SOUND_EFFECT_FILES_MAP[effectType][1], 3440 volFloat, volFloat, 0, 0, 1.0f); 3441 } else { 3442 MediaPlayer mediaPlayer = new MediaPlayer(); 3443 try { 3444 String filePath = Environment.getRootDirectory() + SOUND_EFFECTS_PATH + 3445 SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]); 3446 mediaPlayer.setDataSource(filePath); 3447 mediaPlayer.setAudioStreamType(AudioSystem.STREAM_SYSTEM); 3448 mediaPlayer.prepare(); 3449 mediaPlayer.setVolume(volFloat); 3450 mediaPlayer.setOnCompletionListener(new OnCompletionListener() { 3451 public void onCompletion(MediaPlayer mp) { 3452 cleanupPlayer(mp); 3453 } 3454 }); 3455 mediaPlayer.setOnErrorListener(new OnErrorListener() { 3456 public boolean onError(MediaPlayer mp, int what, int extra) { 3457 cleanupPlayer(mp); 3458 return true; 3459 } 3460 }); 3461 mediaPlayer.start(); 3462 } catch (IOException ex) { 3463 Log.w(TAG, "MediaPlayer IOException: "+ex); 3464 } catch (IllegalArgumentException ex) { 3465 Log.w(TAG, "MediaPlayer IllegalArgumentException: "+ex); 3466 } catch (IllegalStateException ex) { 3467 Log.w(TAG, "MediaPlayer IllegalStateException: "+ex); 3468 } 3469 } 3470 } 3471 } 3472 3473 private void cleanupPlayer(MediaPlayer mp) { 3474 if (mp != null) { 3475 try { 3476 mp.stop(); 3477 mp.release(); 3478 } catch (IllegalStateException ex) { 3479 Log.w(TAG, "MediaPlayer IllegalStateException: "+ex); 3480 } 3481 } 3482 } 3483 3484 private void setForceUse(int usage, int config) { 3485 AudioSystem.setForceUse(usage, config); 3486 } 3487 3488 private void onPersistSafeVolumeState(int state) { 3489 Settings.Global.putInt(mContentResolver, 3490 Settings.Global.AUDIO_SAFE_VOLUME_STATE, 3491 state); 3492 } 3493 3494 @Override 3495 public void handleMessage(Message msg) { 3496 3497 switch (msg.what) { 3498 3499 case MSG_SET_DEVICE_VOLUME: 3500 setDeviceVolume((VolumeStreamState) msg.obj, msg.arg1); 3501 break; 3502 3503 case MSG_SET_ALL_VOLUMES: 3504 setAllVolumes((VolumeStreamState) msg.obj); 3505 break; 3506 3507 case MSG_PERSIST_VOLUME: 3508 persistVolume((VolumeStreamState) msg.obj, msg.arg1); 3509 break; 3510 3511 case MSG_PERSIST_MASTER_VOLUME: 3512 if (mUseFixedVolume) { 3513 return; 3514 } 3515 Settings.System.putFloatForUser(mContentResolver, 3516 Settings.System.VOLUME_MASTER, 3517 (float)msg.arg1 / (float)1000.0, 3518 UserHandle.USER_CURRENT); 3519 break; 3520 3521 case MSG_PERSIST_MASTER_VOLUME_MUTE: 3522 if (mUseFixedVolume) { 3523 return; 3524 } 3525 Settings.System.putIntForUser(mContentResolver, 3526 Settings.System.VOLUME_MASTER_MUTE, 3527 msg.arg1, 3528 UserHandle.USER_CURRENT); 3529 break; 3530 3531 case MSG_PERSIST_RINGER_MODE: 3532 // note that the value persisted is the current ringer mode, not the 3533 // value of ringer mode as of the time the request was made to persist 3534 persistRingerMode(getRingerMode()); 3535 break; 3536 3537 case MSG_MEDIA_SERVER_DIED: 3538 if (AudioSystem.checkAudioFlinger() != AudioSystem.AUDIO_STATUS_OK) { 3539 Log.e(TAG, "Media server died."); 3540 sendMsg(mAudioHandler, MSG_MEDIA_SERVER_DIED, SENDMSG_NOOP, 0, 0, 3541 null, 500); 3542 break; 3543 } 3544 Log.e(TAG, "Media server started."); 3545 3546 // indicate to audio HAL that we start the reconfiguration phase after a media 3547 // server crash 3548 // Note that we only execute this when the media server 3549 // process restarts after a crash, not the first time it is started. 3550 AudioSystem.setParameters("restarting=true"); 3551 3552 readAndSetLowRamDevice(); 3553 3554 // Restore device connection states 3555 synchronized (mConnectedDevices) { 3556 Set set = mConnectedDevices.entrySet(); 3557 Iterator i = set.iterator(); 3558 while (i.hasNext()) { 3559 Map.Entry device = (Map.Entry)i.next(); 3560 AudioSystem.setDeviceConnectionState( 3561 ((Integer)device.getKey()).intValue(), 3562 AudioSystem.DEVICE_STATE_AVAILABLE, 3563 (String)device.getValue()); 3564 } 3565 } 3566 // Restore call state 3567 AudioSystem.setPhoneState(mMode); 3568 3569 // Restore forced usage for communcations and record 3570 AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm); 3571 AudioSystem.setForceUse(AudioSystem.FOR_RECORD, mForcedUseForComm); 3572 AudioSystem.setForceUse(AudioSystem.FOR_SYSTEM, mCameraSoundForced ? 3573 AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE); 3574 3575 // Restore stream volumes 3576 int numStreamTypes = AudioSystem.getNumStreamTypes(); 3577 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { 3578 VolumeStreamState streamState = mStreamStates[streamType]; 3579 AudioSystem.initStreamVolume(streamType, 0, (streamState.mIndexMax + 5) / 10); 3580 3581 streamState.applyAllVolumes(); 3582 } 3583 3584 // Restore ringer mode 3585 setRingerModeInt(getRingerMode(), false); 3586 3587 // Restore master volume 3588 restoreMasterVolume(); 3589 3590 // Reset device orientation (if monitored for this device) 3591 if (mMonitorOrientation) { 3592 setOrientationForAudioSystem(); 3593 } 3594 if (mMonitorRotation) { 3595 setRotationForAudioSystem(); 3596 } 3597 3598 synchronized (mBluetoothA2dpEnabledLock) { 3599 AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, 3600 mBluetoothA2dpEnabled ? 3601 AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP); 3602 } 3603 3604 synchronized (mSettingsLock) { 3605 AudioSystem.setForceUse(AudioSystem.FOR_DOCK, 3606 mDockAudioMediaEnabled ? 3607 AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE); 3608 } 3609 3610 // indicate the end of reconfiguration phase to audio HAL 3611 AudioSystem.setParameters("restarting=false"); 3612 break; 3613 3614 case MSG_UNLOAD_SOUND_EFFECTS: 3615 onUnloadSoundEffects(); 3616 break; 3617 3618 case MSG_LOAD_SOUND_EFFECTS: 3619 //FIXME: onLoadSoundEffects() should be executed in a separate thread as it 3620 // can take several dozens of milliseconds to complete 3621 boolean loaded = onLoadSoundEffects(); 3622 if (msg.obj != null) { 3623 LoadSoundEffectReply reply = (LoadSoundEffectReply)msg.obj; 3624 synchronized (reply) { 3625 reply.mStatus = loaded ? 0 : -1; 3626 reply.notify(); 3627 } 3628 } 3629 break; 3630 3631 case MSG_PLAY_SOUND_EFFECT: 3632 onPlaySoundEffect(msg.arg1, msg.arg2); 3633 break; 3634 3635 case MSG_BTA2DP_DOCK_TIMEOUT: 3636 // msg.obj == address of BTA2DP device 3637 synchronized (mConnectedDevices) { 3638 makeA2dpDeviceUnavailableNow( (String) msg.obj ); 3639 } 3640 break; 3641 3642 case MSG_SET_FORCE_USE: 3643 case MSG_SET_FORCE_BT_A2DP_USE: 3644 setForceUse(msg.arg1, msg.arg2); 3645 break; 3646 3647 case MSG_BT_HEADSET_CNCT_FAILED: 3648 resetBluetoothSco(); 3649 break; 3650 3651 case MSG_SET_WIRED_DEVICE_CONNECTION_STATE: 3652 onSetWiredDeviceConnectionState(msg.arg1, msg.arg2, (String)msg.obj); 3653 mAudioEventWakeLock.release(); 3654 break; 3655 3656 case MSG_SET_A2DP_CONNECTION_STATE: 3657 onSetA2dpConnectionState((BluetoothDevice)msg.obj, msg.arg1); 3658 mAudioEventWakeLock.release(); 3659 break; 3660 3661 case MSG_REPORT_NEW_ROUTES: { 3662 int N = mRoutesObservers.beginBroadcast(); 3663 if (N > 0) { 3664 AudioRoutesInfo routes; 3665 synchronized (mCurAudioRoutes) { 3666 routes = new AudioRoutesInfo(mCurAudioRoutes); 3667 } 3668 while (N > 0) { 3669 N--; 3670 IAudioRoutesObserver obs = mRoutesObservers.getBroadcastItem(N); 3671 try { 3672 obs.dispatchAudioRoutesChanged(routes); 3673 } catch (RemoteException e) { 3674 } 3675 } 3676 } 3677 mRoutesObservers.finishBroadcast(); 3678 break; 3679 } 3680 3681 case MSG_CHECK_MUSIC_ACTIVE: 3682 onCheckMusicActive(); 3683 break; 3684 3685 case MSG_BROADCAST_AUDIO_BECOMING_NOISY: 3686 onSendBecomingNoisyIntent(); 3687 break; 3688 3689 case MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED: 3690 case MSG_CONFIGURE_SAFE_MEDIA_VOLUME: 3691 onConfigureSafeVolume((msg.what == MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED)); 3692 break; 3693 case MSG_PERSIST_SAFE_VOLUME_STATE: 3694 onPersistSafeVolumeState(msg.arg1); 3695 break; 3696 3697 case MSG_BROADCAST_BT_CONNECTION_STATE: 3698 onBroadcastScoConnectionState(msg.arg1); 3699 break; 3700 } 3701 } 3702 } 3703 3704 private class SettingsObserver extends ContentObserver { 3705 3706 SettingsObserver() { 3707 super(new Handler()); 3708 mContentResolver.registerContentObserver(Settings.System.getUriFor( 3709 Settings.System.MODE_RINGER_STREAMS_AFFECTED), false, this); 3710 mContentResolver.registerContentObserver(Settings.Global.getUriFor( 3711 Settings.Global.DOCK_AUDIO_MEDIA_ENABLED), false, this); 3712 } 3713 3714 @Override 3715 public void onChange(boolean selfChange) { 3716 super.onChange(selfChange); 3717 // FIXME This synchronized is not necessary if mSettingsLock only protects mRingerMode. 3718 // However there appear to be some missing locks around mRingerModeMutedStreams 3719 // and mRingerModeAffectedStreams, so will leave this synchronized for now. 3720 // mRingerModeMutedStreams and mMuteAffectedStreams are safe (only accessed once). 3721 synchronized (mSettingsLock) { 3722 if (updateRingerModeAffectedStreams()) { 3723 /* 3724 * Ensure all stream types that should be affected by ringer mode 3725 * are in the proper state. 3726 */ 3727 setRingerModeInt(getRingerMode(), false); 3728 } 3729 readDockAudioSettings(mContentResolver); 3730 } 3731 } 3732 } 3733 3734 // must be called synchronized on mConnectedDevices 3735 private void makeA2dpDeviceAvailable(String address) { 3736 // enable A2DP before notifying A2DP connection to avoid unecessary processing in 3737 // audio policy manager 3738 VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC]; 3739 sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE, 3740 AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0, streamState, 0); 3741 setBluetoothA2dpOnInt(true); 3742 AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 3743 AudioSystem.DEVICE_STATE_AVAILABLE, 3744 address); 3745 // Reset A2DP suspend state each time a new sink is connected 3746 AudioSystem.setParameters("A2dpSuspended=false"); 3747 mConnectedDevices.put( new Integer(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP), 3748 address); 3749 } 3750 3751 private void onSendBecomingNoisyIntent() { 3752 sendBroadcastToAll(new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY)); 3753 } 3754 3755 // must be called synchronized on mConnectedDevices 3756 private void makeA2dpDeviceUnavailableNow(String address) { 3757 synchronized (mA2dpAvrcpLock) { 3758 mAvrcpAbsVolSupported = false; 3759 } 3760 AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 3761 AudioSystem.DEVICE_STATE_UNAVAILABLE, 3762 address); 3763 mConnectedDevices.remove(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP); 3764 } 3765 3766 // must be called synchronized on mConnectedDevices 3767 private void makeA2dpDeviceUnavailableLater(String address) { 3768 // prevent any activity on the A2DP audio output to avoid unwanted 3769 // reconnection of the sink. 3770 AudioSystem.setParameters("A2dpSuspended=true"); 3771 // the device will be made unavailable later, so consider it disconnected right away 3772 mConnectedDevices.remove(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP); 3773 // send the delayed message to make the device unavailable later 3774 Message msg = mAudioHandler.obtainMessage(MSG_BTA2DP_DOCK_TIMEOUT, address); 3775 mAudioHandler.sendMessageDelayed(msg, BTA2DP_DOCK_TIMEOUT_MILLIS); 3776 3777 } 3778 3779 // must be called synchronized on mConnectedDevices 3780 private void cancelA2dpDeviceTimeout() { 3781 mAudioHandler.removeMessages(MSG_BTA2DP_DOCK_TIMEOUT); 3782 } 3783 3784 // must be called synchronized on mConnectedDevices 3785 private boolean hasScheduledA2dpDockTimeout() { 3786 return mAudioHandler.hasMessages(MSG_BTA2DP_DOCK_TIMEOUT); 3787 } 3788 3789 private void onSetA2dpConnectionState(BluetoothDevice btDevice, int state) 3790 { 3791 if (DEBUG_VOL) Log.d(TAG, "onSetA2dpConnectionState btDevice="+btDevice+" state="+state); 3792 if (btDevice == null) { 3793 return; 3794 } 3795 String address = btDevice.getAddress(); 3796 if (!BluetoothAdapter.checkBluetoothAddress(address)) { 3797 address = ""; 3798 } 3799 3800 synchronized (mConnectedDevices) { 3801 boolean isConnected = 3802 (mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) && 3803 mConnectedDevices.get(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP).equals(address)); 3804 3805 if (isConnected && state != BluetoothProfile.STATE_CONNECTED) { 3806 if (btDevice.isBluetoothDock()) { 3807 if (state == BluetoothProfile.STATE_DISCONNECTED) { 3808 // introduction of a delay for transient disconnections of docks when 3809 // power is rapidly turned off/on, this message will be canceled if 3810 // we reconnect the dock under a preset delay 3811 makeA2dpDeviceUnavailableLater(address); 3812 // the next time isConnected is evaluated, it will be false for the dock 3813 } 3814 } else { 3815 makeA2dpDeviceUnavailableNow(address); 3816 } 3817 synchronized (mCurAudioRoutes) { 3818 if (mCurAudioRoutes.mBluetoothName != null) { 3819 mCurAudioRoutes.mBluetoothName = null; 3820 sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES, 3821 SENDMSG_NOOP, 0, 0, null, 0); 3822 } 3823 } 3824 } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) { 3825 if (btDevice.isBluetoothDock()) { 3826 // this could be a reconnection after a transient disconnection 3827 cancelA2dpDeviceTimeout(); 3828 mDockAddress = address; 3829 } else { 3830 // this could be a connection of another A2DP device before the timeout of 3831 // a dock: cancel the dock timeout, and make the dock unavailable now 3832 if(hasScheduledA2dpDockTimeout()) { 3833 cancelA2dpDeviceTimeout(); 3834 makeA2dpDeviceUnavailableNow(mDockAddress); 3835 } 3836 } 3837 makeA2dpDeviceAvailable(address); 3838 synchronized (mCurAudioRoutes) { 3839 String name = btDevice.getAliasName(); 3840 if (!TextUtils.equals(mCurAudioRoutes.mBluetoothName, name)) { 3841 mCurAudioRoutes.mBluetoothName = name; 3842 sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES, 3843 SENDMSG_NOOP, 0, 0, null, 0); 3844 } 3845 } 3846 } 3847 } 3848 } 3849 3850 public void avrcpSupportsAbsoluteVolume(String address, boolean support) { 3851 // address is not used for now, but may be used when multiple a2dp devices are supported 3852 synchronized (mA2dpAvrcpLock) { 3853 mAvrcpAbsVolSupported = support; 3854 sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE, 3855 AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0, 3856 mStreamStates[AudioSystem.STREAM_MUSIC], 0); 3857 sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE, 3858 AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0, 3859 mStreamStates[AudioSystem.STREAM_RING], 0); 3860 } 3861 } 3862 3863 private boolean handleDeviceConnection(boolean connected, int device, String params) { 3864 synchronized (mConnectedDevices) { 3865 boolean isConnected = (mConnectedDevices.containsKey(device) && 3866 (params.isEmpty() || mConnectedDevices.get(device).equals(params))); 3867 3868 if (isConnected && !connected) { 3869 AudioSystem.setDeviceConnectionState(device, 3870 AudioSystem.DEVICE_STATE_UNAVAILABLE, 3871 mConnectedDevices.get(device)); 3872 mConnectedDevices.remove(device); 3873 return true; 3874 } else if (!isConnected && connected) { 3875 AudioSystem.setDeviceConnectionState(device, 3876 AudioSystem.DEVICE_STATE_AVAILABLE, 3877 params); 3878 mConnectedDevices.put(new Integer(device), params); 3879 return true; 3880 } 3881 } 3882 return false; 3883 } 3884 3885 // Devices which removal triggers intent ACTION_AUDIO_BECOMING_NOISY. The intent is only 3886 // sent if none of these devices is connected. 3887 int mBecomingNoisyIntentDevices = 3888 AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE | 3889 AudioSystem.DEVICE_OUT_ALL_A2DP | AudioSystem.DEVICE_OUT_AUX_DIGITAL | 3890 AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET | AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET | 3891 AudioSystem.DEVICE_OUT_ALL_USB; 3892 3893 // must be called before removing the device from mConnectedDevices 3894 private int checkSendBecomingNoisyIntent(int device, int state) { 3895 int delay = 0; 3896 if ((state == 0) && ((device & mBecomingNoisyIntentDevices) != 0)) { 3897 int devices = 0; 3898 for (int dev : mConnectedDevices.keySet()) { 3899 if ((dev & mBecomingNoisyIntentDevices) != 0) { 3900 devices |= dev; 3901 } 3902 } 3903 if (devices == device) { 3904 sendMsg(mAudioHandler, 3905 MSG_BROADCAST_AUDIO_BECOMING_NOISY, 3906 SENDMSG_REPLACE, 3907 0, 3908 0, 3909 null, 3910 0); 3911 delay = 1000; 3912 } 3913 } 3914 3915 if (mAudioHandler.hasMessages(MSG_SET_A2DP_CONNECTION_STATE) || 3916 mAudioHandler.hasMessages(MSG_SET_WIRED_DEVICE_CONNECTION_STATE)) { 3917 delay = 1000; 3918 } 3919 return delay; 3920 } 3921 3922 private void sendDeviceConnectionIntent(int device, int state, String name) 3923 { 3924 Intent intent = new Intent(); 3925 3926 intent.putExtra("state", state); 3927 intent.putExtra("name", name); 3928 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 3929 3930 int connType = 0; 3931 3932 if (device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) { 3933 connType = AudioRoutesInfo.MAIN_HEADSET; 3934 intent.setAction(Intent.ACTION_HEADSET_PLUG); 3935 intent.putExtra("microphone", 1); 3936 } else if (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE) { 3937 connType = AudioRoutesInfo.MAIN_HEADPHONES; 3938 intent.setAction(Intent.ACTION_HEADSET_PLUG); 3939 intent.putExtra("microphone", 0); 3940 } else if (device == AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET) { 3941 connType = AudioRoutesInfo.MAIN_DOCK_SPEAKERS; 3942 intent.setAction(Intent.ACTION_ANALOG_AUDIO_DOCK_PLUG); 3943 } else if (device == AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET) { 3944 connType = AudioRoutesInfo.MAIN_DOCK_SPEAKERS; 3945 intent.setAction(Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG); 3946 } else if (device == AudioSystem.DEVICE_OUT_AUX_DIGITAL) { 3947 connType = AudioRoutesInfo.MAIN_HDMI; 3948 intent.setAction(Intent.ACTION_HDMI_AUDIO_PLUG); 3949 } 3950 3951 synchronized (mCurAudioRoutes) { 3952 if (connType != 0) { 3953 int newConn = mCurAudioRoutes.mMainType; 3954 if (state != 0) { 3955 newConn |= connType; 3956 } else { 3957 newConn &= ~connType; 3958 } 3959 if (newConn != mCurAudioRoutes.mMainType) { 3960 mCurAudioRoutes.mMainType = newConn; 3961 sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES, 3962 SENDMSG_NOOP, 0, 0, null, 0); 3963 } 3964 } 3965 } 3966 3967 final long ident = Binder.clearCallingIdentity(); 3968 try { 3969 ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.USER_ALL); 3970 } finally { 3971 Binder.restoreCallingIdentity(ident); 3972 } 3973 } 3974 3975 private void onSetWiredDeviceConnectionState(int device, int state, String name) 3976 { 3977 synchronized (mConnectedDevices) { 3978 if ((state == 0) && ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) || 3979 (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE))) { 3980 setBluetoothA2dpOnInt(true); 3981 } 3982 boolean isUsb = ((device & AudioSystem.DEVICE_OUT_ALL_USB) != 0); 3983 handleDeviceConnection((state == 1), device, (isUsb ? name : "")); 3984 if (state != 0) { 3985 if ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) || 3986 (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE)) { 3987 setBluetoothA2dpOnInt(false); 3988 } 3989 if ((device & mSafeMediaVolumeDevices) != 0) { 3990 sendMsg(mAudioHandler, 3991 MSG_CHECK_MUSIC_ACTIVE, 3992 SENDMSG_REPLACE, 3993 0, 3994 0, 3995 null, 3996 MUSIC_ACTIVE_POLL_PERIOD_MS); 3997 } 3998 } 3999 if (!isUsb) { 4000 sendDeviceConnectionIntent(device, state, name); 4001 } 4002 } 4003 } 4004 4005 /* cache of the address of the last dock the device was connected to */ 4006 private String mDockAddress; 4007 4008 /** 4009 * Receiver for misc intent broadcasts the Phone app cares about. 4010 */ 4011 private class AudioServiceBroadcastReceiver extends BroadcastReceiver { 4012 @Override 4013 public void onReceive(Context context, Intent intent) { 4014 String action = intent.getAction(); 4015 int device; 4016 int state; 4017 4018 if (action.equals(Intent.ACTION_DOCK_EVENT)) { 4019 int dockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, 4020 Intent.EXTRA_DOCK_STATE_UNDOCKED); 4021 int config; 4022 switch (dockState) { 4023 case Intent.EXTRA_DOCK_STATE_DESK: 4024 config = AudioSystem.FORCE_BT_DESK_DOCK; 4025 break; 4026 case Intent.EXTRA_DOCK_STATE_CAR: 4027 config = AudioSystem.FORCE_BT_CAR_DOCK; 4028 break; 4029 case Intent.EXTRA_DOCK_STATE_LE_DESK: 4030 config = AudioSystem.FORCE_ANALOG_DOCK; 4031 break; 4032 case Intent.EXTRA_DOCK_STATE_HE_DESK: 4033 config = AudioSystem.FORCE_DIGITAL_DOCK; 4034 break; 4035 case Intent.EXTRA_DOCK_STATE_UNDOCKED: 4036 default: 4037 config = AudioSystem.FORCE_NONE; 4038 } 4039 // Low end docks have a menu to enable or disable audio 4040 // (see mDockAudioMediaEnabled) 4041 if (!((dockState == Intent.EXTRA_DOCK_STATE_LE_DESK) || 4042 ((dockState == Intent.EXTRA_DOCK_STATE_UNDOCKED) && 4043 (mDockState == Intent.EXTRA_DOCK_STATE_LE_DESK)))) { 4044 AudioSystem.setForceUse(AudioSystem.FOR_DOCK, config); 4045 } 4046 mDockState = dockState; 4047 } else if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) { 4048 state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 4049 BluetoothProfile.STATE_DISCONNECTED); 4050 device = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO; 4051 String address = null; 4052 4053 BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 4054 if (btDevice == null) { 4055 return; 4056 } 4057 4058 address = btDevice.getAddress(); 4059 BluetoothClass btClass = btDevice.getBluetoothClass(); 4060 if (btClass != null) { 4061 switch (btClass.getDeviceClass()) { 4062 case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET: 4063 case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE: 4064 device = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET; 4065 break; 4066 case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO: 4067 device = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT; 4068 break; 4069 } 4070 } 4071 4072 if (!BluetoothAdapter.checkBluetoothAddress(address)) { 4073 address = ""; 4074 } 4075 4076 boolean connected = (state == BluetoothProfile.STATE_CONNECTED); 4077 if (handleDeviceConnection(connected, device, address)) { 4078 synchronized (mScoClients) { 4079 if (connected) { 4080 mBluetoothHeadsetDevice = btDevice; 4081 } else { 4082 mBluetoothHeadsetDevice = null; 4083 resetBluetoothSco(); 4084 } 4085 } 4086 } 4087 } else if (action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) || 4088 action.equals(Intent.ACTION_USB_AUDIO_DEVICE_PLUG)) { 4089 state = intent.getIntExtra("state", 0); 4090 int alsaCard = intent.getIntExtra("card", -1); 4091 int alsaDevice = intent.getIntExtra("device", -1); 4092 String params = (alsaCard == -1 && alsaDevice == -1 ? "" 4093 : "card=" + alsaCard + ";device=" + alsaDevice); 4094 device = action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) ? 4095 AudioSystem.DEVICE_OUT_USB_ACCESSORY : AudioSystem.DEVICE_OUT_USB_DEVICE; 4096 Log.v(TAG, "Broadcast Receiver: Got " 4097 + (action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) ? 4098 "ACTION_USB_AUDIO_ACCESSORY_PLUG" : "ACTION_USB_AUDIO_DEVICE_PLUG") 4099 + ", state = " + state + ", card: " + alsaCard + ", device: " + alsaDevice); 4100 setWiredDeviceConnectionState(device, state, params); 4101 } else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) { 4102 boolean broadcast = false; 4103 int scoAudioState = AudioManager.SCO_AUDIO_STATE_ERROR; 4104 synchronized (mScoClients) { 4105 int btState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1); 4106 // broadcast intent if the connection was initated by AudioService 4107 if (!mScoClients.isEmpty() && 4108 (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL || 4109 mScoAudioState == SCO_STATE_ACTIVATE_REQ || 4110 mScoAudioState == SCO_STATE_DEACTIVATE_REQ)) { 4111 broadcast = true; 4112 } 4113 switch (btState) { 4114 case BluetoothHeadset.STATE_AUDIO_CONNECTED: 4115 scoAudioState = AudioManager.SCO_AUDIO_STATE_CONNECTED; 4116 if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL && 4117 mScoAudioState != SCO_STATE_DEACTIVATE_REQ && 4118 mScoAudioState != SCO_STATE_DEACTIVATE_EXT_REQ) { 4119 mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL; 4120 } 4121 break; 4122 case BluetoothHeadset.STATE_AUDIO_DISCONNECTED: 4123 scoAudioState = AudioManager.SCO_AUDIO_STATE_DISCONNECTED; 4124 mScoAudioState = SCO_STATE_INACTIVE; 4125 clearAllScoClients(0, false); 4126 break; 4127 case BluetoothHeadset.STATE_AUDIO_CONNECTING: 4128 if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL && 4129 mScoAudioState != SCO_STATE_DEACTIVATE_REQ && 4130 mScoAudioState != SCO_STATE_DEACTIVATE_EXT_REQ) { 4131 mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL; 4132 } 4133 default: 4134 // do not broadcast CONNECTING or invalid state 4135 broadcast = false; 4136 break; 4137 } 4138 } 4139 if (broadcast) { 4140 broadcastScoConnectionState(scoAudioState); 4141 //FIXME: this is to maintain compatibility with deprecated intent 4142 // AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. Remove when appropriate. 4143 Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED); 4144 newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, scoAudioState); 4145 sendStickyBroadcastToAll(newIntent); 4146 } 4147 } else if (action.equals(Intent.ACTION_BOOT_COMPLETED)) { 4148 mBootCompleted = true; 4149 sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 4150 0, 0, null, 0); 4151 4152 mKeyguardManager = 4153 (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); 4154 mScoConnectionState = AudioManager.SCO_AUDIO_STATE_ERROR; 4155 resetBluetoothSco(); 4156 getBluetoothHeadset(); 4157 //FIXME: this is to maintain compatibility with deprecated intent 4158 // AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. Remove when appropriate. 4159 Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED); 4160 newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, 4161 AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 4162 sendStickyBroadcastToAll(newIntent); 4163 4164 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 4165 if (adapter != null) { 4166 adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener, 4167 BluetoothProfile.A2DP); 4168 } 4169 4170 sendMsg(mAudioHandler, 4171 MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED, 4172 SENDMSG_REPLACE, 4173 0, 4174 0, 4175 null, 4176 SAFE_VOLUME_CONFIGURE_TIMEOUT_MS); 4177 } else if (action.equals(Intent.ACTION_SCREEN_ON)) { 4178 AudioSystem.setParameters("screen_state=on"); 4179 } else if (action.equals(Intent.ACTION_SCREEN_OFF)) { 4180 AudioSystem.setParameters("screen_state=off"); 4181 } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) { 4182 handleConfigurationChanged(context); 4183 } else if (action.equals(Intent.ACTION_USER_SWITCHED)) { 4184 // attempt to stop music playback for background user 4185 sendMsg(mAudioHandler, 4186 MSG_BROADCAST_AUDIO_BECOMING_NOISY, 4187 SENDMSG_REPLACE, 4188 0, 4189 0, 4190 null, 4191 0); 4192 // the current audio focus owner is no longer valid 4193 mMediaFocusControl.discardAudioFocusOwner(); 4194 4195 // load volume settings for new user 4196 readAudioSettings(true /*userSwitch*/); 4197 // preserve STREAM_MUSIC volume from one user to the next. 4198 sendMsg(mAudioHandler, 4199 MSG_SET_ALL_VOLUMES, 4200 SENDMSG_QUEUE, 4201 0, 4202 0, 4203 mStreamStates[AudioSystem.STREAM_MUSIC], 0); 4204 } 4205 } 4206 } 4207 4208 //========================================================================================== 4209 // RemoteControlDisplay / RemoteControlClient / Remote info 4210 //========================================================================================== 4211 public boolean registerRemoteController(IRemoteControlDisplay rcd, int w, int h, 4212 ComponentName listenerComp) { 4213 return mMediaFocusControl.registerRemoteController(rcd, w, h, listenerComp); 4214 } 4215 4216 public boolean registerRemoteControlDisplay(IRemoteControlDisplay rcd, int w, int h) { 4217 return mMediaFocusControl.registerRemoteControlDisplay(rcd, w, h); 4218 } 4219 4220 public void unregisterRemoteControlDisplay(IRemoteControlDisplay rcd) { 4221 mMediaFocusControl.unregisterRemoteControlDisplay(rcd); 4222 } 4223 4224 public void remoteControlDisplayUsesBitmapSize(IRemoteControlDisplay rcd, int w, int h) { 4225 mMediaFocusControl.remoteControlDisplayUsesBitmapSize(rcd, w, h); 4226 } 4227 4228 public void remoteControlDisplayWantsPlaybackPositionSync(IRemoteControlDisplay rcd, 4229 boolean wantsSync) { 4230 mMediaFocusControl.remoteControlDisplayWantsPlaybackPositionSync(rcd, wantsSync); 4231 } 4232 4233 public void registerMediaButtonEventReceiverForCalls(ComponentName c) { 4234 mMediaFocusControl.registerMediaButtonEventReceiverForCalls(c); 4235 } 4236 4237 public void unregisterMediaButtonEventReceiverForCalls() { 4238 mMediaFocusControl.unregisterMediaButtonEventReceiverForCalls(); 4239 } 4240 4241 public void registerMediaButtonIntent(PendingIntent pi, ComponentName c, IBinder token) { 4242 mMediaFocusControl.registerMediaButtonIntent(pi, c, token); 4243 } 4244 4245 public void unregisterMediaButtonIntent(PendingIntent pi) { 4246 mMediaFocusControl.unregisterMediaButtonIntent(pi); 4247 } 4248 4249 public int registerRemoteControlClient(PendingIntent mediaIntent, 4250 IRemoteControlClient rcClient, String callingPckg) { 4251 return mMediaFocusControl.registerRemoteControlClient(mediaIntent, rcClient, callingPckg); 4252 } 4253 4254 public void unregisterRemoteControlClient(PendingIntent mediaIntent, 4255 IRemoteControlClient rcClient) { 4256 mMediaFocusControl.unregisterRemoteControlClient(mediaIntent, rcClient); 4257 } 4258 4259 public void setRemoteControlClientPlaybackPosition(int generationId, long timeMs) { 4260 mMediaFocusControl.setRemoteControlClientPlaybackPosition(generationId, timeMs); 4261 } 4262 4263 public void updateRemoteControlClientMetadata(int generationId, int key, Rating value) { 4264 mMediaFocusControl.updateRemoteControlClientMetadata(generationId, key, value); 4265 } 4266 4267 public void registerRemoteVolumeObserverForRcc(int rccId, IRemoteVolumeObserver rvo) { 4268 mMediaFocusControl.registerRemoteVolumeObserverForRcc(rccId, rvo); 4269 } 4270 4271 public int getRemoteStreamVolume() { 4272 return mMediaFocusControl.getRemoteStreamVolume(); 4273 } 4274 4275 public int getRemoteStreamMaxVolume() { 4276 return mMediaFocusControl.getRemoteStreamMaxVolume(); 4277 } 4278 4279 public void setRemoteStreamVolume(int index) { 4280 mMediaFocusControl.setRemoteStreamVolume(index); 4281 } 4282 4283 public void setPlaybackStateForRcc(int rccId, int state, long timeMs, float speed) { 4284 mMediaFocusControl.setPlaybackStateForRcc(rccId, state, timeMs, speed); 4285 } 4286 4287 public void setPlaybackInfoForRcc(int rccId, int what, int value) { 4288 mMediaFocusControl.setPlaybackInfoForRcc(rccId, what, value); 4289 } 4290 4291 public void dispatchMediaKeyEvent(KeyEvent keyEvent) { 4292 mMediaFocusControl.dispatchMediaKeyEvent(keyEvent); 4293 } 4294 4295 public void dispatchMediaKeyEventUnderWakelock(KeyEvent keyEvent) { 4296 mMediaFocusControl.dispatchMediaKeyEventUnderWakelock(keyEvent); 4297 } 4298 4299 //========================================================================================== 4300 // Audio Focus 4301 //========================================================================================== 4302 public int requestAudioFocus(int mainStreamType, int durationHint, IBinder cb, 4303 IAudioFocusDispatcher fd, String clientId, String callingPackageName) { 4304 return mMediaFocusControl.requestAudioFocus(mainStreamType, durationHint, cb, fd, 4305 clientId, callingPackageName); 4306 } 4307 4308 public int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId) { 4309 return mMediaFocusControl.abandonAudioFocus(fd, clientId); 4310 } 4311 4312 public void unregisterAudioFocusClient(String clientId) { 4313 mMediaFocusControl.unregisterAudioFocusClient(clientId); 4314 } 4315 4316 public int getCurrentAudioFocus() { 4317 return mMediaFocusControl.getCurrentAudioFocus(); 4318 } 4319 4320 //========================================================================================== 4321 // Device orientation 4322 //========================================================================================== 4323 /** 4324 * Handles device configuration changes that may map to a change in the orientation 4325 * or orientation. 4326 * Monitoring orientation and rotation is optional, and is defined by the definition and value 4327 * of the "ro.audio.monitorOrientation" and "ro.audio.monitorRotation" system properties. 4328 */ 4329 private void handleConfigurationChanged(Context context) { 4330 try { 4331 // reading new orientation "safely" (i.e. under try catch) in case anything 4332 // goes wrong when obtaining resources and configuration 4333 Configuration config = context.getResources().getConfiguration(); 4334 // TODO merge rotation and orientation 4335 if (mMonitorOrientation) { 4336 int newOrientation = config.orientation; 4337 if (newOrientation != mDeviceOrientation) { 4338 mDeviceOrientation = newOrientation; 4339 setOrientationForAudioSystem(); 4340 } 4341 } 4342 if (mMonitorRotation) { 4343 int newRotation = ((WindowManager) context.getSystemService( 4344 Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation(); 4345 if (newRotation != mDeviceRotation) { 4346 mDeviceRotation = newRotation; 4347 setRotationForAudioSystem(); 4348 } 4349 } 4350 sendMsg(mAudioHandler, 4351 MSG_CONFIGURE_SAFE_MEDIA_VOLUME, 4352 SENDMSG_REPLACE, 4353 0, 4354 0, 4355 null, 4356 0); 4357 4358 boolean cameraSoundForced = mContext.getResources().getBoolean( 4359 com.android.internal.R.bool.config_camera_sound_forced); 4360 synchronized (mSettingsLock) { 4361 synchronized (mCameraSoundForced) { 4362 if (cameraSoundForced != mCameraSoundForced) { 4363 mCameraSoundForced = cameraSoundForced; 4364 4365 VolumeStreamState s = mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED]; 4366 if (cameraSoundForced) { 4367 s.setAllIndexesToMax(); 4368 mRingerModeAffectedStreams &= 4369 ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED); 4370 } else { 4371 s.setAllIndexes(mStreamStates[AudioSystem.STREAM_SYSTEM]); 4372 mRingerModeAffectedStreams |= 4373 (1 << AudioSystem.STREAM_SYSTEM_ENFORCED); 4374 } 4375 // take new state into account for streams muted by ringer mode 4376 setRingerModeInt(getRingerMode(), false); 4377 4378 sendMsg(mAudioHandler, 4379 MSG_SET_FORCE_USE, 4380 SENDMSG_QUEUE, 4381 AudioSystem.FOR_SYSTEM, 4382 cameraSoundForced ? 4383 AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE, 4384 null, 4385 0); 4386 4387 sendMsg(mAudioHandler, 4388 MSG_SET_ALL_VOLUMES, 4389 SENDMSG_QUEUE, 4390 0, 4391 0, 4392 mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED], 0); 4393 } 4394 } 4395 } 4396 mVolumePanel.setLayoutDirection(config.getLayoutDirection()); 4397 } catch (Exception e) { 4398 Log.e(TAG, "Error handling configuration change: ", e); 4399 } 4400 } 4401 4402 private void setOrientationForAudioSystem() { 4403 switch (mDeviceOrientation) { 4404 case Configuration.ORIENTATION_LANDSCAPE: 4405 //Log.i(TAG, "orientation is landscape"); 4406 AudioSystem.setParameters("orientation=landscape"); 4407 break; 4408 case Configuration.ORIENTATION_PORTRAIT: 4409 //Log.i(TAG, "orientation is portrait"); 4410 AudioSystem.setParameters("orientation=portrait"); 4411 break; 4412 case Configuration.ORIENTATION_SQUARE: 4413 //Log.i(TAG, "orientation is square"); 4414 AudioSystem.setParameters("orientation=square"); 4415 break; 4416 case Configuration.ORIENTATION_UNDEFINED: 4417 //Log.i(TAG, "orientation is undefined"); 4418 AudioSystem.setParameters("orientation=undefined"); 4419 break; 4420 default: 4421 Log.e(TAG, "Unknown orientation"); 4422 } 4423 } 4424 4425 private void setRotationForAudioSystem() { 4426 switch (mDeviceRotation) { 4427 case Surface.ROTATION_0: 4428 AudioSystem.setParameters("rotation=0"); 4429 break; 4430 case Surface.ROTATION_90: 4431 AudioSystem.setParameters("rotation=90"); 4432 break; 4433 case Surface.ROTATION_180: 4434 AudioSystem.setParameters("rotation=180"); 4435 break; 4436 case Surface.ROTATION_270: 4437 AudioSystem.setParameters("rotation=270"); 4438 break; 4439 default: 4440 Log.e(TAG, "Unknown device rotation"); 4441 } 4442 } 4443 4444 4445 // Handles request to override default use of A2DP for media. 4446 public void setBluetoothA2dpOnInt(boolean on) { 4447 synchronized (mBluetoothA2dpEnabledLock) { 4448 mBluetoothA2dpEnabled = on; 4449 mAudioHandler.removeMessages(MSG_SET_FORCE_BT_A2DP_USE); 4450 AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, 4451 mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP); 4452 } 4453 } 4454 4455 @Override 4456 public void setRingtonePlayer(IRingtonePlayer player) { 4457 mContext.enforceCallingOrSelfPermission(REMOTE_AUDIO_PLAYBACK, null); 4458 mRingtonePlayer = player; 4459 } 4460 4461 @Override 4462 public IRingtonePlayer getRingtonePlayer() { 4463 return mRingtonePlayer; 4464 } 4465 4466 @Override 4467 public AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) { 4468 synchronized (mCurAudioRoutes) { 4469 AudioRoutesInfo routes = new AudioRoutesInfo(mCurAudioRoutes); 4470 mRoutesObservers.register(observer); 4471 return routes; 4472 } 4473 } 4474 4475 4476 //========================================================================================== 4477 // Safe media volume management. 4478 // MUSIC stream volume level is limited when headphones are connected according to safety 4479 // regulation. When the user attempts to raise the volume above the limit, a warning is 4480 // displayed and the user has to acknowlegde before the volume is actually changed. 4481 // The volume index corresponding to the limit is stored in config_safe_media_volume_index 4482 // property. Platforms with a different limit must set this property accordingly in their 4483 // overlay. 4484 //========================================================================================== 4485 4486 // mSafeMediaVolumeState indicates whether the media volume is limited over headphones. 4487 // It is SAFE_MEDIA_VOLUME_NOT_CONFIGURED at boot time until a network service is connected 4488 // or the configure time is elapsed. It is then set to SAFE_MEDIA_VOLUME_ACTIVE or 4489 // SAFE_MEDIA_VOLUME_DISABLED according to country option. If not SAFE_MEDIA_VOLUME_DISABLED, it 4490 // can be set to SAFE_MEDIA_VOLUME_INACTIVE by calling AudioService.disableSafeMediaVolume() 4491 // (when user opts out). 4492 private final int SAFE_MEDIA_VOLUME_NOT_CONFIGURED = 0; 4493 private final int SAFE_MEDIA_VOLUME_DISABLED = 1; 4494 private final int SAFE_MEDIA_VOLUME_INACTIVE = 2; 4495 private final int SAFE_MEDIA_VOLUME_ACTIVE = 3; 4496 private Integer mSafeMediaVolumeState; 4497 4498 private int mMcc = 0; 4499 // mSafeMediaVolumeIndex is the cached value of config_safe_media_volume_index property 4500 private int mSafeMediaVolumeIndex; 4501 // mSafeMediaVolumeDevices lists the devices for which safe media volume is enforced, 4502 private final int mSafeMediaVolumeDevices = AudioSystem.DEVICE_OUT_WIRED_HEADSET | 4503 AudioSystem.DEVICE_OUT_WIRED_HEADPHONE; 4504 // mMusicActiveMs is the cumulative time of music activity since safe volume was disabled. 4505 // When this time reaches UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX, the safe media volume is re-enabled 4506 // automatically. mMusicActiveMs is rounded to a multiple of MUSIC_ACTIVE_POLL_PERIOD_MS. 4507 private int mMusicActiveMs; 4508 private static final int UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX = (20 * 3600 * 1000); // 20 hours 4509 private static final int MUSIC_ACTIVE_POLL_PERIOD_MS = 60000; // 1 minute polling interval 4510 private static final int SAFE_VOLUME_CONFIGURE_TIMEOUT_MS = 30000; // 30s after boot completed 4511 4512 private void setSafeMediaVolumeEnabled(boolean on) { 4513 synchronized (mSafeMediaVolumeState) { 4514 if ((mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_NOT_CONFIGURED) && 4515 (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_DISABLED)) { 4516 if (on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE)) { 4517 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE; 4518 enforceSafeMediaVolume(); 4519 } else if (!on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE)) { 4520 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE; 4521 mMusicActiveMs = 0; 4522 sendMsg(mAudioHandler, 4523 MSG_CHECK_MUSIC_ACTIVE, 4524 SENDMSG_REPLACE, 4525 0, 4526 0, 4527 null, 4528 MUSIC_ACTIVE_POLL_PERIOD_MS); 4529 } 4530 } 4531 } 4532 } 4533 4534 private void enforceSafeMediaVolume() { 4535 VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC]; 4536 int devices = mSafeMediaVolumeDevices; 4537 int i = 0; 4538 4539 while (devices != 0) { 4540 int device = 1 << i++; 4541 if ((device & devices) == 0) { 4542 continue; 4543 } 4544 int index = streamState.getIndex(device); 4545 if (index > mSafeMediaVolumeIndex) { 4546 streamState.setIndex(mSafeMediaVolumeIndex, device); 4547 sendMsg(mAudioHandler, 4548 MSG_SET_DEVICE_VOLUME, 4549 SENDMSG_QUEUE, 4550 device, 4551 0, 4552 streamState, 4553 0); 4554 } 4555 devices &= ~device; 4556 } 4557 } 4558 4559 private boolean checkSafeMediaVolume(int streamType, int index, int device) { 4560 synchronized (mSafeMediaVolumeState) { 4561 if ((mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) && 4562 (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) && 4563 ((device & mSafeMediaVolumeDevices) != 0) && 4564 (index > mSafeMediaVolumeIndex)) { 4565 return false; 4566 } 4567 return true; 4568 } 4569 } 4570 4571 public void disableSafeMediaVolume() { 4572 synchronized (mSafeMediaVolumeState) { 4573 setSafeMediaVolumeEnabled(false); 4574 if (mPendingVolumeCommand != null) { 4575 onSetStreamVolume(mPendingVolumeCommand.mStreamType, 4576 mPendingVolumeCommand.mIndex, 4577 mPendingVolumeCommand.mFlags, 4578 mPendingVolumeCommand.mDevice); 4579 mPendingVolumeCommand = null; 4580 } 4581 } 4582 } 4583 4584 4585 //========================================================================================== 4586 // Camera shutter sound policy. 4587 // config_camera_sound_forced configuration option in config.xml defines if the camera shutter 4588 // sound is forced (sound even if the device is in silent mode) or not. This option is false by 4589 // default and can be overridden by country specific overlay in values-mccXXX/config.xml. 4590 //========================================================================================== 4591 4592 // cached value of com.android.internal.R.bool.config_camera_sound_forced 4593 private Boolean mCameraSoundForced; 4594 4595 // called by android.hardware.Camera to populate CameraInfo.canDisableShutterSound 4596 public boolean isCameraSoundForced() { 4597 synchronized (mCameraSoundForced) { 4598 return mCameraSoundForced; 4599 } 4600 } 4601 4602 private static final String[] RINGER_MODE_NAMES = new String[] { 4603 "SILENT", 4604 "VIBRATE", 4605 "NORMAL" 4606 }; 4607 4608 private void dumpRingerMode(PrintWriter pw) { 4609 pw.println("\nRinger mode: "); 4610 pw.println("- mode: "+RINGER_MODE_NAMES[mRingerMode]); 4611 pw.print("- ringer mode affected streams = 0x"); 4612 pw.println(Integer.toHexString(mRingerModeAffectedStreams)); 4613 pw.print("- ringer mode muted streams = 0x"); 4614 pw.println(Integer.toHexString(mRingerModeMutedStreams)); 4615 } 4616 4617 @Override 4618 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 4619 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); 4620 4621 mMediaFocusControl.dump(pw); 4622 dumpStreamStates(pw); 4623 dumpRingerMode(pw); 4624 pw.println("\nAudio routes:"); 4625 pw.print(" mMainType=0x"); pw.println(Integer.toHexString(mCurAudioRoutes.mMainType)); 4626 pw.print(" mBluetoothName="); pw.println(mCurAudioRoutes.mBluetoothName); 4627 } 4628 4629 // Inform AudioFlinger of our device's low RAM attribute 4630 private static void readAndSetLowRamDevice() 4631 { 4632 int status = AudioSystem.setLowRamDevice(ActivityManager.isLowRamDeviceStatic()); 4633 if (status != 0) { 4634 Log.w(TAG, "AudioFlinger informed of device's low RAM attribute; status " + status); 4635 } 4636 } 4637} 4638