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