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