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