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