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