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