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