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