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