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