1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.media; 18 19 import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT; 20 import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_AUDIO; 21 import static android.content.Context.DEVICE_ID_DEFAULT; 22 23 import android.Manifest; 24 import android.annotation.CallbackExecutor; 25 import android.annotation.IntDef; 26 import android.annotation.IntRange; 27 import android.annotation.NonNull; 28 import android.annotation.Nullable; 29 import android.annotation.RequiresPermission; 30 import android.annotation.SdkConstant; 31 import android.annotation.SdkConstant.SdkConstantType; 32 import android.annotation.SuppressLint; 33 import android.annotation.SystemApi; 34 import android.annotation.SystemService; 35 import android.annotation.TestApi; 36 import android.app.NotificationManager; 37 import android.app.PendingIntent; 38 import android.app.compat.CompatChanges; 39 import android.bluetooth.BluetoothCodecConfig; 40 import android.bluetooth.BluetoothDevice; 41 import android.bluetooth.BluetoothLeAudioCodecConfig; 42 import android.companion.virtual.VirtualDeviceManager; 43 import android.compat.annotation.ChangeId; 44 import android.compat.annotation.EnabledSince; 45 import android.compat.annotation.Overridable; 46 import android.compat.annotation.UnsupportedAppUsage; 47 import android.content.ComponentName; 48 import android.content.Context; 49 import android.content.Intent; 50 import android.media.AudioAttributes.AttributeSystemUsage; 51 import android.media.CallbackUtil.ListenerInfo; 52 import android.media.audiopolicy.AudioPolicy; 53 import android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener; 54 import android.media.audiopolicy.AudioProductStrategy; 55 import android.media.audiopolicy.AudioVolumeGroup; 56 import android.media.audiopolicy.AudioVolumeGroupChangeHandler; 57 import android.media.projection.MediaProjection; 58 import android.media.session.MediaController; 59 import android.media.session.MediaSession; 60 import android.media.session.MediaSessionLegacyHelper; 61 import android.media.session.MediaSessionManager; 62 import android.net.Uri; 63 import android.os.Binder; 64 import android.os.Build; 65 import android.os.Handler; 66 import android.os.IBinder; 67 import android.os.Looper; 68 import android.os.Message; 69 import android.os.RemoteException; 70 import android.os.ServiceManager; 71 import android.os.SystemClock; 72 import android.os.UserHandle; 73 import android.provider.Settings; 74 import android.text.TextUtils; 75 import android.util.ArrayMap; 76 import android.util.Log; 77 import android.util.Pair; 78 import android.view.KeyEvent; 79 80 import com.android.internal.annotations.GuardedBy; 81 import com.android.internal.util.Preconditions; 82 83 import java.io.IOException; 84 import java.lang.annotation.Retention; 85 import java.lang.annotation.RetentionPolicy; 86 import java.lang.ref.WeakReference; 87 import java.util.ArrayList; 88 import java.util.Arrays; 89 import java.util.Collections; 90 import java.util.HashMap; 91 import java.util.HashSet; 92 import java.util.Iterator; 93 import java.util.List; 94 import java.util.Map; 95 import java.util.Objects; 96 import java.util.TreeMap; 97 import java.util.concurrent.ConcurrentHashMap; 98 import java.util.concurrent.Executor; 99 import java.util.concurrent.Executors; 100 import java.util.concurrent.TimeUnit; 101 102 /** 103 * AudioManager provides access to volume and ringer mode control. 104 */ 105 @SystemService(Context.AUDIO_SERVICE) 106 public class AudioManager { 107 108 private Context mOriginalContext; 109 private Context mApplicationContext; 110 private int mOriginalContextDeviceId = DEVICE_ID_DEFAULT; 111 private @Nullable VirtualDeviceManager mVirtualDeviceManager; // Lazy initialized. 112 private static final String TAG = "AudioManager"; 113 private static final boolean DEBUG = false; 114 private static final AudioPortEventHandler sAudioPortEventHandler = new AudioPortEventHandler(); 115 private static final AudioVolumeGroupChangeHandler sAudioAudioVolumeGroupChangedHandler = 116 new AudioVolumeGroupChangeHandler(); 117 118 private static WeakReference<Context> sContext; 119 120 /** 121 * Broadcast intent, a hint for applications that audio is about to become 122 * 'noisy' due to a change in audio outputs. For example, this intent may 123 * be sent when a wired headset is unplugged, or when an A2DP audio 124 * sink is disconnected, and the audio system is about to automatically 125 * switch audio route to the speaker. Applications that are controlling 126 * audio streams may consider pausing, reducing volume or some other action 127 * on receipt of this intent so as not to surprise the user with audio 128 * from the speaker. 129 */ 130 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 131 public static final String ACTION_AUDIO_BECOMING_NOISY = "android.media.AUDIO_BECOMING_NOISY"; 132 133 /** 134 * Sticky broadcast intent action indicating that the ringer mode has 135 * changed. Includes the new ringer mode. 136 * 137 * @see #EXTRA_RINGER_MODE 138 */ 139 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 140 public static final String RINGER_MODE_CHANGED_ACTION = "android.media.RINGER_MODE_CHANGED"; 141 142 /** 143 * @hide 144 * Sticky broadcast intent action indicating that the internal ringer mode has 145 * changed. Includes the new ringer mode. 146 * 147 * @see #EXTRA_RINGER_MODE 148 */ 149 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 150 public static final String INTERNAL_RINGER_MODE_CHANGED_ACTION = 151 "android.media.INTERNAL_RINGER_MODE_CHANGED_ACTION"; 152 153 /** 154 * The new ringer mode. 155 * 156 * @see #RINGER_MODE_CHANGED_ACTION 157 * @see #RINGER_MODE_NORMAL 158 * @see #RINGER_MODE_SILENT 159 * @see #RINGER_MODE_VIBRATE 160 */ 161 public static final String EXTRA_RINGER_MODE = "android.media.EXTRA_RINGER_MODE"; 162 163 /** 164 * Broadcast intent action indicating that the vibrate setting has 165 * changed. Includes the vibrate type and its new setting. 166 * 167 * @see #EXTRA_VIBRATE_TYPE 168 * @see #EXTRA_VIBRATE_SETTING 169 * @deprecated Applications should maintain their own vibrate policy based on 170 * current ringer mode and listen to {@link #RINGER_MODE_CHANGED_ACTION} instead. 171 */ 172 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 173 public static final String VIBRATE_SETTING_CHANGED_ACTION = 174 "android.media.VIBRATE_SETTING_CHANGED"; 175 176 /** 177 * @hide Broadcast intent when the volume for a particular stream type changes. 178 * Includes the stream, the new volume and previous volumes. 179 * Notes: 180 * - for internal platform use only, do not make public, 181 * - never used for "remote" volume changes 182 * 183 * @see #EXTRA_VOLUME_STREAM_TYPE 184 * @see #EXTRA_VOLUME_STREAM_VALUE 185 * @see #EXTRA_PREV_VOLUME_STREAM_VALUE 186 */ 187 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 188 @UnsupportedAppUsage 189 public static final String VOLUME_CHANGED_ACTION = "android.media.VOLUME_CHANGED_ACTION"; 190 191 /** 192 * @hide Broadcast intent when the volume for a particular stream type changes. 193 * Includes the stream, the new volume and previous volumes. 194 * Notes: 195 * - for internal platform use only, do not make public, 196 * - never used for "remote" volume changes 197 * 198 * @see #EXTRA_VOLUME_STREAM_TYPE 199 * @see #EXTRA_VOLUME_STREAM_VALUE 200 * @see #EXTRA_PREV_VOLUME_STREAM_VALUE 201 */ 202 @SystemApi 203 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 204 @SuppressLint("ActionValue") 205 public static final String ACTION_VOLUME_CHANGED = "android.media.VOLUME_CHANGED_ACTION"; 206 207 /** 208 * @hide Broadcast intent when the devices for a particular stream type changes. 209 * Includes the stream, the new devices and previous devices. 210 * Notes: 211 * - for internal platform use only, do not make public, 212 * - never used for "remote" volume changes 213 * 214 * @see #EXTRA_VOLUME_STREAM_TYPE 215 * @see #EXTRA_VOLUME_STREAM_DEVICES 216 * @see #EXTRA_PREV_VOLUME_STREAM_DEVICES 217 * @see #getDevicesForStream 218 */ 219 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 220 public static final String STREAM_DEVICES_CHANGED_ACTION = 221 "android.media.STREAM_DEVICES_CHANGED_ACTION"; 222 223 /** 224 * @hide Broadcast intent when a stream mute state changes. 225 * Includes the stream that changed and the new mute state 226 * 227 * @see #EXTRA_VOLUME_STREAM_TYPE 228 * @see #EXTRA_STREAM_VOLUME_MUTED 229 */ 230 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 231 public static final String STREAM_MUTE_CHANGED_ACTION = 232 "android.media.STREAM_MUTE_CHANGED_ACTION"; 233 234 /** 235 * @hide Broadcast intent when the master mute state changes. 236 * Includes the the new volume 237 * 238 * @see #EXTRA_MASTER_VOLUME_MUTED 239 */ 240 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 241 public static final String MASTER_MUTE_CHANGED_ACTION = 242 "android.media.MASTER_MUTE_CHANGED_ACTION"; 243 244 /** 245 * The new vibrate setting for a particular type. 246 * 247 * @see #VIBRATE_SETTING_CHANGED_ACTION 248 * @see #EXTRA_VIBRATE_TYPE 249 * @see #VIBRATE_SETTING_ON 250 * @see #VIBRATE_SETTING_OFF 251 * @see #VIBRATE_SETTING_ONLY_SILENT 252 * @deprecated Applications should maintain their own vibrate policy based on 253 * current ringer mode and listen to {@link #RINGER_MODE_CHANGED_ACTION} instead. 254 */ 255 public static final String EXTRA_VIBRATE_SETTING = "android.media.EXTRA_VIBRATE_SETTING"; 256 257 /** 258 * The vibrate type whose setting has changed. 259 * 260 * @see #VIBRATE_SETTING_CHANGED_ACTION 261 * @see #VIBRATE_TYPE_NOTIFICATION 262 * @see #VIBRATE_TYPE_RINGER 263 * @deprecated Applications should maintain their own vibrate policy based on 264 * current ringer mode and listen to {@link #RINGER_MODE_CHANGED_ACTION} instead. 265 */ 266 public static final String EXTRA_VIBRATE_TYPE = "android.media.EXTRA_VIBRATE_TYPE"; 267 268 /** 269 * @hide The stream type for the volume changed intent. 270 */ 271 @SystemApi 272 @SuppressLint("ActionValue") 273 public static final String EXTRA_VOLUME_STREAM_TYPE = "android.media.EXTRA_VOLUME_STREAM_TYPE"; 274 275 /** 276 * @hide 277 * The stream type alias for the volume changed intent. 278 * For instance the intent may indicate a change of the {@link #STREAM_NOTIFICATION} stream 279 * type (as indicated by the {@link #EXTRA_VOLUME_STREAM_TYPE} extra), but this is also 280 * reflected by a change of the volume of its alias, {@link #STREAM_RING} on some devices, 281 * {@link #STREAM_MUSIC} on others (e.g. a television). 282 */ 283 public static final String EXTRA_VOLUME_STREAM_TYPE_ALIAS = 284 "android.media.EXTRA_VOLUME_STREAM_TYPE_ALIAS"; 285 286 /** 287 * @hide The volume associated with the stream for the volume changed intent. 288 */ 289 @SystemApi 290 @SuppressLint("ActionValue") 291 public static final String EXTRA_VOLUME_STREAM_VALUE = 292 "android.media.EXTRA_VOLUME_STREAM_VALUE"; 293 294 /** 295 * @hide The previous volume associated with the stream for the volume changed intent. 296 */ 297 public static final String EXTRA_PREV_VOLUME_STREAM_VALUE = 298 "android.media.EXTRA_PREV_VOLUME_STREAM_VALUE"; 299 300 /** 301 * @hide The devices associated with the stream for the stream devices changed intent. 302 */ 303 public static final String EXTRA_VOLUME_STREAM_DEVICES = 304 "android.media.EXTRA_VOLUME_STREAM_DEVICES"; 305 306 /** 307 * @hide The previous devices associated with the stream for the stream devices changed intent. 308 */ 309 public static final String EXTRA_PREV_VOLUME_STREAM_DEVICES = 310 "android.media.EXTRA_PREV_VOLUME_STREAM_DEVICES"; 311 312 /** 313 * @hide The new master volume mute state for the master mute changed intent. 314 * Value is boolean 315 */ 316 public static final String EXTRA_MASTER_VOLUME_MUTED = 317 "android.media.EXTRA_MASTER_VOLUME_MUTED"; 318 319 /** 320 * @hide The new stream volume mute state for the stream mute changed intent. 321 * Value is boolean 322 */ 323 public static final String EXTRA_STREAM_VOLUME_MUTED = 324 "android.media.EXTRA_STREAM_VOLUME_MUTED"; 325 326 /** 327 * Broadcast Action: Wired Headset plugged in or unplugged. 328 * 329 * You <em>cannot</em> receive this through components declared 330 * in manifests, only by explicitly registering for it with 331 * {@link Context#registerReceiver(BroadcastReceiver, IntentFilter) 332 * Context.registerReceiver()}. 333 * 334 * <p>The intent will have the following extra values: 335 * <ul> 336 * <li><em>state</em> - 0 for unplugged, 1 for plugged. </li> 337 * <li><em>name</em> - Headset type, human readable string </li> 338 * <li><em>microphone</em> - 1 if headset has a microphone, 0 otherwise </li> 339 * </ul> 340 * </ul> 341 */ 342 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 343 public static final String ACTION_HEADSET_PLUG = 344 "android.intent.action.HEADSET_PLUG"; 345 346 /** 347 * Broadcast Action: A sticky broadcast indicating an HDMI cable was plugged or unplugged. 348 * 349 * The intent will have the following extra values: {@link #EXTRA_AUDIO_PLUG_STATE}, 350 * {@link #EXTRA_MAX_CHANNEL_COUNT}, {@link #EXTRA_ENCODINGS}. 351 * <p>It can only be received by explicitly registering for it with 352 * {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)}. 353 */ 354 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 355 public static final String ACTION_HDMI_AUDIO_PLUG = 356 "android.media.action.HDMI_AUDIO_PLUG"; 357 358 /** 359 * Extra used in {@link #ACTION_HDMI_AUDIO_PLUG} to communicate whether HDMI is plugged in 360 * or unplugged. 361 * An integer value of 1 indicates a plugged-in state, 0 is unplugged. 362 */ 363 public static final String EXTRA_AUDIO_PLUG_STATE = "android.media.extra.AUDIO_PLUG_STATE"; 364 365 /** 366 * Extra used in {@link #ACTION_HDMI_AUDIO_PLUG} to define the maximum number of channels 367 * supported by the HDMI device. 368 * The corresponding integer value is only available when the device is plugged in (as expressed 369 * by {@link #EXTRA_AUDIO_PLUG_STATE}). 370 */ 371 public static final String EXTRA_MAX_CHANNEL_COUNT = "android.media.extra.MAX_CHANNEL_COUNT"; 372 373 /** 374 * Extra used in {@link #ACTION_HDMI_AUDIO_PLUG} to define the audio encodings supported by 375 * the connected HDMI device. 376 * The corresponding array of encoding values is only available when the device is plugged in 377 * (as expressed by {@link #EXTRA_AUDIO_PLUG_STATE}). Encoding values are defined in 378 * {@link AudioFormat} (for instance see {@link AudioFormat#ENCODING_PCM_16BIT}). Use 379 * {@link android.content.Intent#getIntArrayExtra(String)} to retrieve the encoding values. 380 */ 381 public static final String EXTRA_ENCODINGS = "android.media.extra.ENCODINGS"; 382 383 /** Used to identify the volume of audio streams for phone calls */ 384 public static final int STREAM_VOICE_CALL = AudioSystem.STREAM_VOICE_CALL; 385 /** Used to identify the volume of audio streams for system sounds */ 386 public static final int STREAM_SYSTEM = AudioSystem.STREAM_SYSTEM; 387 /** Used to identify the volume of audio streams for the phone ring */ 388 public static final int STREAM_RING = AudioSystem.STREAM_RING; 389 /** Used to identify the volume of audio streams for music playback */ 390 public static final int STREAM_MUSIC = AudioSystem.STREAM_MUSIC; 391 /** Used to identify the volume of audio streams for alarms */ 392 public static final int STREAM_ALARM = AudioSystem.STREAM_ALARM; 393 /** Used to identify the volume of audio streams for notifications */ 394 public static final int STREAM_NOTIFICATION = AudioSystem.STREAM_NOTIFICATION; 395 /** @hide Used to identify the volume of audio streams for phone calls when connected 396 * to bluetooth */ 397 @SystemApi 398 public static final int STREAM_BLUETOOTH_SCO = AudioSystem.STREAM_BLUETOOTH_SCO; 399 /** @hide Used to identify the volume of audio streams for enforced system sounds 400 * in certain countries (e.g camera in Japan) */ 401 @UnsupportedAppUsage 402 public static final int STREAM_SYSTEM_ENFORCED = AudioSystem.STREAM_SYSTEM_ENFORCED; 403 /** Used to identify the volume of audio streams for DTMF Tones */ 404 public static final int STREAM_DTMF = AudioSystem.STREAM_DTMF; 405 /** @hide Used to identify the volume of audio streams exclusively transmitted through the 406 * speaker (TTS) of the device */ 407 @UnsupportedAppUsage 408 public static final int STREAM_TTS = AudioSystem.STREAM_TTS; 409 /** Used to identify the volume of audio streams for accessibility prompts */ 410 public static final int STREAM_ACCESSIBILITY = AudioSystem.STREAM_ACCESSIBILITY; 411 /** @hide Used to identify the volume of audio streams for virtual assistant */ 412 @SystemApi 413 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) 414 public static final int STREAM_ASSISTANT = AudioSystem.STREAM_ASSISTANT; 415 416 /** Number of audio streams */ 417 /** 418 * @deprecated Do not iterate on volume stream type values. 419 */ 420 @Deprecated public static final int NUM_STREAMS = AudioSystem.NUM_STREAMS; 421 422 /** @hide */ 423 private static final int[] PUBLIC_STREAM_TYPES = { AudioManager.STREAM_VOICE_CALL, 424 AudioManager.STREAM_SYSTEM, AudioManager.STREAM_RING, AudioManager.STREAM_MUSIC, 425 AudioManager.STREAM_ALARM, AudioManager.STREAM_NOTIFICATION, 426 AudioManager.STREAM_DTMF, AudioManager.STREAM_ACCESSIBILITY }; 427 428 /** @hide */ 429 @TestApi getPublicStreamTypes()430 public static final int[] getPublicStreamTypes() { 431 return PUBLIC_STREAM_TYPES; 432 } 433 434 /** 435 * Increase the ringer volume. 436 * 437 * @see #adjustVolume(int, int) 438 * @see #adjustStreamVolume(int, int, int) 439 */ 440 public static final int ADJUST_RAISE = 1; 441 442 /** 443 * Decrease the ringer volume. 444 * 445 * @see #adjustVolume(int, int) 446 * @see #adjustStreamVolume(int, int, int) 447 */ 448 public static final int ADJUST_LOWER = -1; 449 450 /** 451 * Maintain the previous ringer volume. This may be useful when needing to 452 * show the volume toast without actually modifying the volume. 453 * 454 * @see #adjustVolume(int, int) 455 * @see #adjustStreamVolume(int, int, int) 456 */ 457 public static final int ADJUST_SAME = 0; 458 459 /** 460 * Mute the volume. Has no effect if the stream is already muted. 461 * 462 * @see #adjustVolume(int, int) 463 * @see #adjustStreamVolume(int, int, int) 464 */ 465 public static final int ADJUST_MUTE = -100; 466 467 /** 468 * Unmute the volume. Has no effect if the stream is not muted. 469 * 470 * @see #adjustVolume(int, int) 471 * @see #adjustStreamVolume(int, int, int) 472 */ 473 public static final int ADJUST_UNMUTE = 100; 474 475 /** 476 * Toggle the mute state. If muted the stream will be unmuted. If not muted 477 * the stream will be muted. 478 * 479 * @see #adjustVolume(int, int) 480 * @see #adjustStreamVolume(int, int, int) 481 */ 482 public static final int ADJUST_TOGGLE_MUTE = 101; 483 484 /** @hide */ 485 @IntDef(flag = false, prefix = "ADJUST", value = { 486 ADJUST_RAISE, 487 ADJUST_LOWER, 488 ADJUST_SAME, 489 ADJUST_MUTE, 490 ADJUST_UNMUTE, 491 ADJUST_TOGGLE_MUTE } 492 ) 493 @Retention(RetentionPolicy.SOURCE) 494 public @interface VolumeAdjustment {} 495 496 /** @hide */ adjustToString(int adj)497 public static final String adjustToString(int adj) { 498 switch (adj) { 499 case ADJUST_RAISE: return "ADJUST_RAISE"; 500 case ADJUST_LOWER: return "ADJUST_LOWER"; 501 case ADJUST_SAME: return "ADJUST_SAME"; 502 case ADJUST_MUTE: return "ADJUST_MUTE"; 503 case ADJUST_UNMUTE: return "ADJUST_UNMUTE"; 504 case ADJUST_TOGGLE_MUTE: return "ADJUST_TOGGLE_MUTE"; 505 default: return new StringBuilder("unknown adjust mode ").append(adj).toString(); 506 } 507 } 508 509 // Flags should be powers of 2! 510 511 /** 512 * Show a toast containing the current volume. 513 * 514 * @see #adjustStreamVolume(int, int, int) 515 * @see #adjustVolume(int, int) 516 * @see #setStreamVolume(int, int, int) 517 * @see #setRingerMode(int) 518 */ 519 public static final int FLAG_SHOW_UI = 1 << 0; 520 521 /** 522 * Whether to include ringer modes as possible options when changing volume. 523 * For example, if true and volume level is 0 and the volume is adjusted 524 * with {@link #ADJUST_LOWER}, then the ringer mode may switch the silent or 525 * vibrate mode. 526 * <p> 527 * By default this is on for the ring stream. If this flag is included, 528 * this behavior will be present regardless of the stream type being 529 * affected by the ringer mode. 530 * 531 * @see #adjustVolume(int, int) 532 * @see #adjustStreamVolume(int, int, int) 533 */ 534 public static final int FLAG_ALLOW_RINGER_MODES = 1 << 1; 535 536 /** 537 * Whether to play a sound when changing the volume. 538 * <p> 539 * If this is given to {@link #adjustVolume(int, int)} or 540 * {@link #adjustSuggestedStreamVolume(int, int, int)}, it may be ignored 541 * in some cases (for example, the decided stream type is not 542 * {@link AudioManager#STREAM_RING}, or the volume is being adjusted 543 * downward). 544 * 545 * @see #adjustStreamVolume(int, int, int) 546 * @see #adjustVolume(int, int) 547 * @see #setStreamVolume(int, int, int) 548 */ 549 public static final int FLAG_PLAY_SOUND = 1 << 2; 550 551 /** 552 * Removes any sounds/vibrate that may be in the queue, or are playing (related to 553 * changing volume). 554 */ 555 public static final int FLAG_REMOVE_SOUND_AND_VIBRATE = 1 << 3; 556 557 /** 558 * Whether to vibrate if going into the vibrate ringer mode. 559 */ 560 public static final int FLAG_VIBRATE = 1 << 4; 561 562 /** 563 * Indicates to VolumePanel that the volume slider should be disabled as user 564 * cannot change the stream volume 565 * @hide 566 */ 567 public static final int FLAG_FIXED_VOLUME = 1 << 5; 568 569 /** 570 * Indicates the volume set/adjust call is for Bluetooth absolute volume 571 * @hide 572 */ 573 @SystemApi 574 public static final int FLAG_BLUETOOTH_ABS_VOLUME = 1 << 6; 575 576 /** 577 * Adjusting the volume was prevented due to silent mode, display a hint in the UI. 578 * @hide 579 */ 580 public static final int FLAG_SHOW_SILENT_HINT = 1 << 7; 581 582 /** 583 * Indicates the volume call is for Hdmi Cec system audio volume 584 * @hide 585 */ 586 public static final int FLAG_HDMI_SYSTEM_AUDIO_VOLUME = 1 << 8; 587 588 /** 589 * Indicates that this should only be handled if media is actively playing. 590 * @hide 591 */ 592 public static final int FLAG_ACTIVE_MEDIA_ONLY = 1 << 9; 593 594 /** 595 * Like FLAG_SHOW_UI, but only dialog warnings and confirmations, no sliders. 596 * @hide 597 */ 598 public static final int FLAG_SHOW_UI_WARNINGS = 1 << 10; 599 600 /** 601 * Adjusting the volume down from vibrated was prevented, display a hint in the UI. 602 * @hide 603 */ 604 public static final int FLAG_SHOW_VIBRATE_HINT = 1 << 11; 605 606 /** 607 * Adjusting the volume due to a hardware key press. 608 * This flag can be used in the places in order to denote (or check) that a volume adjustment 609 * request is from a hardware key press. (e.g. {@link MediaController}). 610 * @hide 611 */ 612 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 613 public static final int FLAG_FROM_KEY = 1 << 12; 614 615 /** 616 * Indicates that an absolute volume controller is notifying AudioService of a change in the 617 * volume or mute status of an external audio system. 618 * @hide 619 */ 620 public static final int FLAG_ABSOLUTE_VOLUME = 1 << 13; 621 622 /** @hide */ 623 @IntDef(prefix = {"ENCODED_SURROUND_OUTPUT_"}, value = { 624 ENCODED_SURROUND_OUTPUT_UNKNOWN, 625 ENCODED_SURROUND_OUTPUT_AUTO, 626 ENCODED_SURROUND_OUTPUT_NEVER, 627 ENCODED_SURROUND_OUTPUT_ALWAYS, 628 ENCODED_SURROUND_OUTPUT_MANUAL 629 }) 630 @Retention(RetentionPolicy.SOURCE) 631 public @interface EncodedSurroundOutputMode {} 632 633 /** 634 * The mode for surround sound formats is unknown. 635 */ 636 public static final int ENCODED_SURROUND_OUTPUT_UNKNOWN = -1; 637 638 /** 639 * The surround sound formats are available for use if they are detected. This is the default 640 * mode. 641 */ 642 public static final int ENCODED_SURROUND_OUTPUT_AUTO = 0; 643 644 /** 645 * The surround sound formats are NEVER available, even if they are detected by the hardware. 646 * Those formats will not be reported. 647 */ 648 public static final int ENCODED_SURROUND_OUTPUT_NEVER = 1; 649 650 /** 651 * The surround sound formats are ALWAYS available, even if they are not detected by the 652 * hardware. Those formats will be reported as part of the HDMI output capability. 653 * Applications are then free to use either PCM or encoded output. 654 */ 655 public static final int ENCODED_SURROUND_OUTPUT_ALWAYS = 2; 656 657 /** 658 * Surround sound formats are available according to the choice of user, even if they are not 659 * detected by the hardware. Those formats will be reported as part of the HDMI output 660 * capability. Applications are then free to use either PCM or encoded output. 661 */ 662 public static final int ENCODED_SURROUND_OUTPUT_MANUAL = 3; 663 664 /** 665 * @hide 666 * This list contains all the flags that can be used in internal APIs for volume 667 * related operations */ 668 @IntDef(flag = true, prefix = "FLAG", value = { 669 FLAG_SHOW_UI, 670 FLAG_ALLOW_RINGER_MODES, 671 FLAG_PLAY_SOUND, 672 FLAG_REMOVE_SOUND_AND_VIBRATE, 673 FLAG_VIBRATE, 674 FLAG_FIXED_VOLUME, 675 FLAG_BLUETOOTH_ABS_VOLUME, 676 FLAG_SHOW_SILENT_HINT, 677 FLAG_HDMI_SYSTEM_AUDIO_VOLUME, 678 FLAG_ACTIVE_MEDIA_ONLY, 679 FLAG_SHOW_UI_WARNINGS, 680 FLAG_SHOW_VIBRATE_HINT, 681 FLAG_FROM_KEY, 682 FLAG_ABSOLUTE_VOLUME, 683 }) 684 @Retention(RetentionPolicy.SOURCE) 685 public @interface Flags {} 686 687 /** 688 * @hide 689 * This list contains all the flags that can be used in SDK-visible methods for volume 690 * related operations. 691 * See for instance {@link #adjustVolume(int, int)}, 692 * {@link #adjustStreamVolume(int, int, int)}, 693 * {@link #adjustSuggestedStreamVolume(int, int, int)}, 694 * {@link #adjustVolumeGroupVolume(int, int, int)}, 695 * {@link #setStreamVolume(int, int, int)} 696 * The list contains all volume flags, but the values commented out of the list are there for 697 * maintenance reasons (for when adding flags or changing their visibility), 698 * and to document why some are not in the list (hidden or SystemApi). */ 699 @IntDef(flag = true, prefix = "FLAG", value = { 700 FLAG_SHOW_UI, 701 FLAG_ALLOW_RINGER_MODES, 702 FLAG_PLAY_SOUND, 703 FLAG_REMOVE_SOUND_AND_VIBRATE, 704 FLAG_VIBRATE, 705 //FLAG_FIXED_VOLUME, removed due to @hide 706 //FLAG_BLUETOOTH_ABS_VOLUME, removed due to @SystemApi 707 //FLAG_SHOW_SILENT_HINT, removed due to @hide 708 //FLAG_HDMI_SYSTEM_AUDIO_VOLUME, removed due to @hide 709 //FLAG_ACTIVE_MEDIA_ONLY, removed due to @hide 710 //FLAG_SHOW_UI_WARNINGS, removed due to @hide 711 //FLAG_SHOW_VIBRATE_HINT, removed due to @hide 712 //FLAG_FROM_KEY, removed due to @SystemApi 713 //FLAG_ABSOLUTE_VOLUME, removed due to @hide 714 }) 715 @Retention(RetentionPolicy.SOURCE) 716 public @interface PublicVolumeFlags {} 717 718 /** 719 * @hide 720 * Like PublicVolumeFlags, but for all the flags that can be used in @SystemApi methods for 721 * volume related operations. 722 * See for instance {@link #setVolumeIndexForAttributes(AudioAttributes, int, int)}, 723 * {@link #setVolumeGroupVolumeIndex(int, int, int)}, 724 * {@link #setStreamVolumeForUid(int, int, int, String, int, int, int)}, 725 * {@link #adjustStreamVolumeForUid(int, int, int, String, int, int, int)}, 726 * {@link #adjustSuggestedStreamVolumeForUid(int, int, int, String, int, int, int)} 727 * The list contains all volume flags, but the values commented out of the list are there for 728 * maintenance reasons (for when adding flags or changing their visibility), 729 * and to document which hidden values are not in the list. */ 730 @IntDef(flag = true, prefix = "FLAG", value = { 731 FLAG_SHOW_UI, 732 FLAG_ALLOW_RINGER_MODES, 733 FLAG_PLAY_SOUND, 734 FLAG_REMOVE_SOUND_AND_VIBRATE, 735 FLAG_VIBRATE, 736 //FLAG_FIXED_VOLUME, removed due to @hide 737 FLAG_BLUETOOTH_ABS_VOLUME, 738 //FLAG_SHOW_SILENT_HINT, removed due to @hide 739 //FLAG_HDMI_SYSTEM_AUDIO_VOLUME, removed due to @hide 740 //FLAG_ACTIVE_MEDIA_ONLY, removed due to @hide 741 //FLAG_SHOW_UI_WARNINGS, removed due to @hide 742 //FLAG_SHOW_VIBRATE_HINT, removed due to @hide 743 FLAG_FROM_KEY, 744 //FLAG_ABSOLUTE_VOLUME, removed due to @hide 745 }) 746 @Retention(RetentionPolicy.SOURCE) 747 public @interface SystemVolumeFlags {} 748 749 // The iterator of TreeMap#entrySet() returns the entries in ascending key order. 750 private static final TreeMap<Integer, String> FLAG_NAMES = new TreeMap<>(); 751 752 static { FLAG_NAMES.put(FLAG_SHOW_UI, R)753 FLAG_NAMES.put(FLAG_SHOW_UI, "FLAG_SHOW_UI"); FLAG_NAMES.put(FLAG_ALLOW_RINGER_MODES, R)754 FLAG_NAMES.put(FLAG_ALLOW_RINGER_MODES, "FLAG_ALLOW_RINGER_MODES"); FLAG_NAMES.put(FLAG_PLAY_SOUND, R)755 FLAG_NAMES.put(FLAG_PLAY_SOUND, "FLAG_PLAY_SOUND"); FLAG_NAMES.put(FLAG_REMOVE_SOUND_AND_VIBRATE, R)756 FLAG_NAMES.put(FLAG_REMOVE_SOUND_AND_VIBRATE, "FLAG_REMOVE_SOUND_AND_VIBRATE"); FLAG_NAMES.put(FLAG_VIBRATE, R)757 FLAG_NAMES.put(FLAG_VIBRATE, "FLAG_VIBRATE"); FLAG_NAMES.put(FLAG_FIXED_VOLUME, R)758 FLAG_NAMES.put(FLAG_FIXED_VOLUME, "FLAG_FIXED_VOLUME"); FLAG_NAMES.put(FLAG_BLUETOOTH_ABS_VOLUME, R)759 FLAG_NAMES.put(FLAG_BLUETOOTH_ABS_VOLUME, "FLAG_BLUETOOTH_ABS_VOLUME"); FLAG_NAMES.put(FLAG_SHOW_SILENT_HINT, R)760 FLAG_NAMES.put(FLAG_SHOW_SILENT_HINT, "FLAG_SHOW_SILENT_HINT"); FLAG_NAMES.put(FLAG_HDMI_SYSTEM_AUDIO_VOLUME, R)761 FLAG_NAMES.put(FLAG_HDMI_SYSTEM_AUDIO_VOLUME, "FLAG_HDMI_SYSTEM_AUDIO_VOLUME"); FLAG_NAMES.put(FLAG_ACTIVE_MEDIA_ONLY, R)762 FLAG_NAMES.put(FLAG_ACTIVE_MEDIA_ONLY, "FLAG_ACTIVE_MEDIA_ONLY"); FLAG_NAMES.put(FLAG_SHOW_UI_WARNINGS, R)763 FLAG_NAMES.put(FLAG_SHOW_UI_WARNINGS, "FLAG_SHOW_UI_WARNINGS"); FLAG_NAMES.put(FLAG_SHOW_VIBRATE_HINT, R)764 FLAG_NAMES.put(FLAG_SHOW_VIBRATE_HINT, "FLAG_SHOW_VIBRATE_HINT"); FLAG_NAMES.put(FLAG_FROM_KEY, R)765 FLAG_NAMES.put(FLAG_FROM_KEY, "FLAG_FROM_KEY"); FLAG_NAMES.put(FLAG_ABSOLUTE_VOLUME, R)766 FLAG_NAMES.put(FLAG_ABSOLUTE_VOLUME, "FLAG_ABSOLUTE_VOLUME"); 767 } 768 769 /** @hide */ flagsToString(int flags)770 public static String flagsToString(int flags) { 771 final StringBuilder sb = new StringBuilder(); 772 for (Map.Entry<Integer, String> entry : FLAG_NAMES.entrySet()) { 773 final int flag = entry.getKey(); 774 if ((flags & flag) != 0) { 775 if (sb.length() > 0) { 776 sb.append(','); 777 } 778 sb.append(entry.getValue()); 779 flags &= ~flag; 780 } 781 } 782 if (flags != 0) { 783 if (sb.length() > 0) { 784 sb.append(','); 785 } 786 sb.append(flags); 787 } 788 return sb.toString(); 789 } 790 791 /** 792 * Ringer mode that will be silent and will not vibrate. (This overrides the 793 * vibrate setting.) 794 * 795 * @see #setRingerMode(int) 796 * @see #getRingerMode() 797 */ 798 public static final int RINGER_MODE_SILENT = 0; 799 800 /** 801 * Ringer mode that will be silent and will vibrate. (This will cause the 802 * phone ringer to always vibrate, but the notification vibrate to only 803 * vibrate if set.) 804 * 805 * @see #setRingerMode(int) 806 * @see #getRingerMode() 807 */ 808 public static final int RINGER_MODE_VIBRATE = 1; 809 810 /** 811 * Ringer mode that may be audible and may vibrate. It will be audible if 812 * the volume before changing out of this mode was audible. It will vibrate 813 * if the vibrate setting is on. 814 * 815 * @see #setRingerMode(int) 816 * @see #getRingerMode() 817 */ 818 public static final int RINGER_MODE_NORMAL = 2; 819 820 /** 821 * Maximum valid ringer mode value. Values must start from 0 and be contiguous. 822 * @hide 823 */ 824 public static final int RINGER_MODE_MAX = RINGER_MODE_NORMAL; 825 826 /** 827 * Vibrate type that corresponds to the ringer. 828 * 829 * @see #setVibrateSetting(int, int) 830 * @see #getVibrateSetting(int) 831 * @see #shouldVibrate(int) 832 * @deprecated Applications should maintain their own vibrate policy based on 833 * current ringer mode that can be queried via {@link #getRingerMode()}. 834 */ 835 public static final int VIBRATE_TYPE_RINGER = 0; 836 837 /** 838 * Vibrate type that corresponds to notifications. 839 * 840 * @see #setVibrateSetting(int, int) 841 * @see #getVibrateSetting(int) 842 * @see #shouldVibrate(int) 843 * @deprecated Applications should maintain their own vibrate policy based on 844 * current ringer mode that can be queried via {@link #getRingerMode()}. 845 */ 846 public static final int VIBRATE_TYPE_NOTIFICATION = 1; 847 848 /** 849 * Vibrate setting that suggests to never vibrate. 850 * 851 * @see #setVibrateSetting(int, int) 852 * @see #getVibrateSetting(int) 853 * @deprecated Applications should maintain their own vibrate policy based on 854 * current ringer mode that can be queried via {@link #getRingerMode()}. 855 */ 856 public static final int VIBRATE_SETTING_OFF = 0; 857 858 /** 859 * Vibrate setting that suggests to vibrate when possible. 860 * 861 * @see #setVibrateSetting(int, int) 862 * @see #getVibrateSetting(int) 863 * @deprecated Applications should maintain their own vibrate policy based on 864 * current ringer mode that can be queried via {@link #getRingerMode()}. 865 */ 866 public static final int VIBRATE_SETTING_ON = 1; 867 868 /** 869 * Vibrate setting that suggests to only vibrate when in the vibrate ringer 870 * mode. 871 * 872 * @see #setVibrateSetting(int, int) 873 * @see #getVibrateSetting(int) 874 * @deprecated Applications should maintain their own vibrate policy based on 875 * current ringer mode that can be queried via {@link #getRingerMode()}. 876 */ 877 public static final int VIBRATE_SETTING_ONLY_SILENT = 2; 878 879 /** 880 * Suggests using the default stream type. This may not be used in all 881 * places a stream type is needed. 882 */ 883 public static final int USE_DEFAULT_STREAM_TYPE = Integer.MIN_VALUE; 884 885 private static IAudioService sService; 886 887 /** 888 * @hide 889 * For test purposes only, will throw NPE with some methods that require a Context. 890 */ 891 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) AudioManager()892 public AudioManager() { 893 } 894 895 /** 896 * @hide 897 */ 898 @UnsupportedAppUsage AudioManager(Context context)899 public AudioManager(Context context) { 900 setContext(context); 901 } 902 getContext()903 private Context getContext() { 904 if (mApplicationContext == null) { 905 setContext(mOriginalContext); 906 } 907 if (mApplicationContext != null) { 908 return mApplicationContext; 909 } 910 return mOriginalContext; 911 } 912 setContext(Context context)913 private void setContext(Context context) { 914 mOriginalContextDeviceId = context.getDeviceId(); 915 mApplicationContext = context.getApplicationContext(); 916 if (mApplicationContext != null) { 917 mOriginalContext = null; 918 } else { 919 mOriginalContext = context; 920 } 921 sContext = new WeakReference<>(context); 922 } 923 924 @UnsupportedAppUsage getService()925 static IAudioService getService() 926 { 927 if (sService != null) { 928 return sService; 929 } 930 IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE); 931 sService = IAudioService.Stub.asInterface(b); 932 return sService; 933 } 934 getVirtualDeviceManager()935 private VirtualDeviceManager getVirtualDeviceManager() { 936 if (mVirtualDeviceManager != null) { 937 return mVirtualDeviceManager; 938 } 939 mVirtualDeviceManager = getContext().getSystemService(VirtualDeviceManager.class); 940 return mVirtualDeviceManager; 941 } 942 943 /** 944 * Sends a simulated key event for a media button. 945 * To simulate a key press, you must first send a KeyEvent built with a 946 * {@link KeyEvent#ACTION_DOWN} action, then another event with the {@link KeyEvent#ACTION_UP} 947 * action. 948 * <p>The key event will be sent to the current media key event consumer which registered with 949 * {@link AudioManager#registerMediaButtonEventReceiver(PendingIntent)}. 950 * @param keyEvent a {@link KeyEvent} instance whose key code is one of 951 * {@link KeyEvent#KEYCODE_MUTE}, 952 * {@link KeyEvent#KEYCODE_HEADSETHOOK}, 953 * {@link KeyEvent#KEYCODE_MEDIA_PLAY}, 954 * {@link KeyEvent#KEYCODE_MEDIA_PAUSE}, 955 * {@link KeyEvent#KEYCODE_MEDIA_PLAY_PAUSE}, 956 * {@link KeyEvent#KEYCODE_MEDIA_STOP}, 957 * {@link KeyEvent#KEYCODE_MEDIA_NEXT}, 958 * {@link KeyEvent#KEYCODE_MEDIA_PREVIOUS}, 959 * {@link KeyEvent#KEYCODE_MEDIA_REWIND}, 960 * {@link KeyEvent#KEYCODE_MEDIA_RECORD}, 961 * {@link KeyEvent#KEYCODE_MEDIA_FAST_FORWARD}, 962 * {@link KeyEvent#KEYCODE_MEDIA_CLOSE}, 963 * {@link KeyEvent#KEYCODE_MEDIA_EJECT}, 964 * or {@link KeyEvent#KEYCODE_MEDIA_AUDIO_TRACK}. 965 */ dispatchMediaKeyEvent(KeyEvent keyEvent)966 public void dispatchMediaKeyEvent(KeyEvent keyEvent) { 967 MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(getContext()); 968 helper.sendMediaButtonEvent(keyEvent, false); 969 } 970 971 /** 972 * @hide 973 */ preDispatchKeyEvent(KeyEvent event, int stream)974 public void preDispatchKeyEvent(KeyEvent event, int stream) { 975 /* 976 * If the user hits another key within the play sound delay, then 977 * cancel the sound 978 */ 979 int keyCode = event.getKeyCode(); 980 if (keyCode != KeyEvent.KEYCODE_VOLUME_DOWN && keyCode != KeyEvent.KEYCODE_VOLUME_UP 981 && keyCode != KeyEvent.KEYCODE_VOLUME_MUTE 982 && AudioSystem.PLAY_SOUND_DELAY > SystemClock.uptimeMillis()) { 983 /* 984 * The user has hit another key during the delay (e.g., 300ms) 985 * since the last volume key up, so cancel any sounds. 986 */ 987 adjustSuggestedStreamVolume(ADJUST_SAME, 988 stream, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE); 989 } 990 } 991 992 /** 993 * Indicates if the device implements a fixed volume policy. 994 * <p>Some devices may not have volume control and may operate at a fixed volume, 995 * and may not enable muting or changing the volume of audio streams. 996 * This method will return true on such devices. 997 * <p>The following APIs have no effect when volume is fixed: 998 * <ul> 999 * <li> {@link #adjustVolume(int, int)} 1000 * <li> {@link #adjustSuggestedStreamVolume(int, int, int)} 1001 * <li> {@link #adjustStreamVolume(int, int, int)} 1002 * <li> {@link #setStreamVolume(int, int, int)} 1003 * <li> {@link #setRingerMode(int)} 1004 * <li> {@link #setStreamSolo(int, boolean)} 1005 * <li> {@link #setStreamMute(int, boolean)} 1006 * </ul> 1007 */ isVolumeFixed()1008 public boolean isVolumeFixed() { 1009 boolean res = false; 1010 try { 1011 res = getService().isVolumeFixed(); 1012 } catch (RemoteException e) { 1013 Log.e(TAG, "Error querying isVolumeFixed", e); 1014 } 1015 return res; 1016 } 1017 1018 /** 1019 * Adjusts the volume of a particular stream by one step in a direction. 1020 * <p> 1021 * This method should only be used by applications that replace the platform-wide 1022 * management of audio settings or the main telephony application. 1023 * <p>This method has no effect if the device implements a fixed volume policy 1024 * as indicated by {@link #isVolumeFixed()}. 1025 * <p>From N onward, ringer mode adjustments that would toggle Do Not Disturb are not allowed 1026 * unless the app has been granted Do Not Disturb Access. 1027 * See {@link NotificationManager#isNotificationPolicyAccessGranted()}. 1028 * 1029 * @param streamType The stream type to adjust. One of {@link #STREAM_VOICE_CALL}, 1030 * {@link #STREAM_SYSTEM}, {@link #STREAM_RING}, {@link #STREAM_MUSIC}, 1031 * {@link #STREAM_ALARM} or {@link #STREAM_ACCESSIBILITY}. 1032 * @param direction The direction to adjust the volume. One of 1033 * {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, or 1034 * {@link #ADJUST_SAME}. 1035 * @param flags 1036 * @see #adjustVolume(int, int) 1037 * @see #setStreamVolume(int, int, int) 1038 * @throws SecurityException if the adjustment triggers a Do Not Disturb change 1039 * and the caller is not granted notification policy access. 1040 */ adjustStreamVolume(int streamType, int direction, @PublicVolumeFlags int flags)1041 public void adjustStreamVolume(int streamType, int direction, @PublicVolumeFlags int flags) { 1042 final IAudioService service = getService(); 1043 try { 1044 service.adjustStreamVolumeWithAttribution(streamType, direction, flags, 1045 getContext().getOpPackageName(), getContext().getAttributionTag()); 1046 } catch (RemoteException e) { 1047 throw e.rethrowFromSystemServer(); 1048 } 1049 } 1050 1051 /** 1052 * Adjusts the volume of the most relevant stream. For example, if a call is 1053 * active, it will have the highest priority regardless of if the in-call 1054 * screen is showing. Another example, if music is playing in the background 1055 * and a call is not active, the music stream will be adjusted. 1056 * <p> 1057 * This method should only be used by applications that replace the 1058 * platform-wide management of audio settings or the main telephony 1059 * application. 1060 * <p> 1061 * This method has no effect if the device implements a fixed volume policy 1062 * as indicated by {@link #isVolumeFixed()}. 1063 * 1064 * @param direction The direction to adjust the volume. One of 1065 * {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, 1066 * {@link #ADJUST_SAME}, {@link #ADJUST_MUTE}, 1067 * {@link #ADJUST_UNMUTE}, or {@link #ADJUST_TOGGLE_MUTE}. 1068 * @param flags 1069 * @see #adjustSuggestedStreamVolume(int, int, int) 1070 * @see #adjustStreamVolume(int, int, int) 1071 * @see #setStreamVolume(int, int, int) 1072 * @see #isVolumeFixed() 1073 */ adjustVolume(int direction, @PublicVolumeFlags int flags)1074 public void adjustVolume(int direction, @PublicVolumeFlags int flags) { 1075 MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(getContext()); 1076 helper.sendAdjustVolumeBy(USE_DEFAULT_STREAM_TYPE, direction, flags); 1077 } 1078 1079 /** 1080 * Adjusts the volume of the most relevant stream, or the given fallback 1081 * stream. 1082 * <p> 1083 * This method should only be used by applications that replace the 1084 * platform-wide management of audio settings or the main telephony 1085 * application. 1086 * <p> 1087 * This method has no effect if the device implements a fixed volume policy 1088 * as indicated by {@link #isVolumeFixed()}. 1089 * 1090 * @param direction The direction to adjust the volume. One of 1091 * {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, 1092 * {@link #ADJUST_SAME}, {@link #ADJUST_MUTE}, 1093 * {@link #ADJUST_UNMUTE}, or {@link #ADJUST_TOGGLE_MUTE}. 1094 * @param suggestedStreamType The stream type that will be used if there 1095 * isn't a relevant stream. {@link #USE_DEFAULT_STREAM_TYPE} is 1096 * valid here. 1097 * @param flags 1098 * @see #adjustVolume(int, int) 1099 * @see #adjustStreamVolume(int, int, int) 1100 * @see #setStreamVolume(int, int, int) 1101 * @see #isVolumeFixed() 1102 */ adjustSuggestedStreamVolume(int direction, int suggestedStreamType, @PublicVolumeFlags int flags)1103 public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, 1104 @PublicVolumeFlags int flags) { 1105 MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(getContext()); 1106 helper.sendAdjustVolumeBy(suggestedStreamType, direction, flags); 1107 } 1108 1109 /** @hide */ 1110 @UnsupportedAppUsage 1111 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) setMasterMute(boolean mute, int flags)1112 public void setMasterMute(boolean mute, int flags) { 1113 final IAudioService service = getService(); 1114 try { 1115 service.setMasterMute(mute, flags, getContext().getOpPackageName(), 1116 UserHandle.getCallingUserId(), getContext().getAttributionTag()); 1117 } catch (RemoteException e) { 1118 throw e.rethrowFromSystemServer(); 1119 } 1120 } 1121 1122 /** 1123 * Returns the current ringtone mode. 1124 * 1125 * @return The current ringtone mode, one of {@link #RINGER_MODE_NORMAL}, 1126 * {@link #RINGER_MODE_SILENT}, or {@link #RINGER_MODE_VIBRATE}. 1127 * @see #setRingerMode(int) 1128 */ getRingerMode()1129 public int getRingerMode() { 1130 final IAudioService service = getService(); 1131 try { 1132 return service.getRingerModeExternal(); 1133 } catch (RemoteException e) { 1134 throw e.rethrowFromSystemServer(); 1135 } 1136 } 1137 1138 /** 1139 * Returns the current user setting for ramping ringer on incoming phone call ringtone. 1140 * 1141 * @return true if the incoming phone call ringtone is configured to gradually increase its 1142 * volume, false otherwise. 1143 */ isRampingRingerEnabled()1144 public boolean isRampingRingerEnabled() { 1145 return Settings.System.getInt(getContext().getContentResolver(), 1146 Settings.System.APPLY_RAMPING_RINGER, 0) != 0; 1147 } 1148 1149 /** 1150 * Sets the flag for enabling ramping ringer on incoming phone call ringtone. 1151 * 1152 * @see #isRampingRingerEnabled() 1153 * @hide 1154 */ 1155 @TestApi setRampingRingerEnabled(boolean enabled)1156 public void setRampingRingerEnabled(boolean enabled) { 1157 Settings.System.putInt(getContext().getContentResolver(), 1158 Settings.System.APPLY_RAMPING_RINGER, enabled ? 1 : 0); 1159 } 1160 1161 /** 1162 * Checks valid ringer mode values. 1163 * 1164 * @return true if the ringer mode indicated is valid, false otherwise. 1165 * 1166 * @see #setRingerMode(int) 1167 * @hide 1168 */ 1169 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) isValidRingerMode(int ringerMode)1170 public static boolean isValidRingerMode(int ringerMode) { 1171 if (ringerMode < 0 || ringerMode > RINGER_MODE_MAX) { 1172 return false; 1173 } 1174 final IAudioService service = getService(); 1175 try { 1176 return service.isValidRingerMode(ringerMode); 1177 } catch (RemoteException e) { 1178 throw e.rethrowFromSystemServer(); 1179 } 1180 } 1181 1182 /** 1183 * Returns the maximum volume index for a particular stream. 1184 * 1185 * @param streamType The stream type whose maximum volume index is returned. 1186 * @return The maximum valid volume index for the stream. 1187 * @see #getStreamVolume(int) 1188 */ getStreamMaxVolume(int streamType)1189 public int getStreamMaxVolume(int streamType) { 1190 final IAudioService service = getService(); 1191 try { 1192 return service.getStreamMaxVolume(streamType); 1193 } catch (RemoteException e) { 1194 throw e.rethrowFromSystemServer(); 1195 } 1196 } 1197 1198 /** 1199 * Returns the minimum volume index for a particular stream. 1200 * @param streamType The stream type whose minimum volume index is returned. Must be one of 1201 * {@link #STREAM_VOICE_CALL}, {@link #STREAM_SYSTEM}, 1202 * {@link #STREAM_RING}, {@link #STREAM_MUSIC}, {@link #STREAM_ALARM}, 1203 * {@link #STREAM_NOTIFICATION}, {@link #STREAM_DTMF} or {@link #STREAM_ACCESSIBILITY}. 1204 * @return The minimum valid volume index for the stream. 1205 * @see #getStreamVolume(int) 1206 */ getStreamMinVolume(int streamType)1207 public int getStreamMinVolume(int streamType) { 1208 if (!isPublicStreamType(streamType)) { 1209 throw new IllegalArgumentException("Invalid stream type " + streamType); 1210 } 1211 return getStreamMinVolumeInt(streamType); 1212 } 1213 1214 /** 1215 * @hide 1216 * Same as {@link #getStreamMinVolume(int)} but without the check on the public stream type. 1217 * @param streamType The stream type whose minimum volume index is returned. 1218 * @return The minimum valid volume index for the stream. 1219 * @see #getStreamVolume(int) 1220 */ 1221 @TestApi getStreamMinVolumeInt(int streamType)1222 public int getStreamMinVolumeInt(int streamType) { 1223 final IAudioService service = getService(); 1224 try { 1225 return service.getStreamMinVolume(streamType); 1226 } catch (RemoteException e) { 1227 throw e.rethrowFromSystemServer(); 1228 } 1229 } 1230 1231 /** 1232 * Returns the current volume index for a particular stream. 1233 * 1234 * @param streamType The stream type whose volume index is returned. 1235 * @return The current volume index for the stream. 1236 * @see #getStreamMaxVolume(int) 1237 * @see #setStreamVolume(int, int, int) 1238 */ getStreamVolume(int streamType)1239 public int getStreamVolume(int streamType) { 1240 final IAudioService service = getService(); 1241 try { 1242 return service.getStreamVolume(streamType); 1243 } catch (RemoteException e) { 1244 throw e.rethrowFromSystemServer(); 1245 } 1246 } 1247 1248 // keep in sync with frameworks/av/services/audiopolicy/common/include/Volume.h 1249 private static final float VOLUME_MIN_DB = -758.0f; 1250 1251 /** @hide */ 1252 @IntDef(flag = false, prefix = "STREAM", value = { 1253 STREAM_VOICE_CALL, 1254 STREAM_SYSTEM, 1255 STREAM_RING, 1256 STREAM_MUSIC, 1257 STREAM_ALARM, 1258 STREAM_NOTIFICATION, 1259 STREAM_DTMF, 1260 STREAM_ACCESSIBILITY } 1261 ) 1262 @Retention(RetentionPolicy.SOURCE) 1263 public @interface PublicStreamTypes {} 1264 1265 /** 1266 * Returns the volume in dB (decibel) for the given stream type at the given volume index, on 1267 * the given type of audio output device. 1268 * @param streamType stream type for which the volume is queried. 1269 * @param index the volume index for which the volume is queried. The index value must be 1270 * between the minimum and maximum index values for the given stream type (see 1271 * {@link #getStreamMinVolume(int)} and {@link #getStreamMaxVolume(int)}). 1272 * @param deviceType the type of audio output device for which volume is queried. 1273 * @return a volume expressed in dB. 1274 * A negative value indicates the audio signal is attenuated. A typical maximum value 1275 * at the maximum volume index is 0 dB (no attenuation nor amplification). Muting is 1276 * reflected by a value of {@link Float#NEGATIVE_INFINITY}. 1277 */ getStreamVolumeDb(@ublicStreamTypes int streamType, int index, @AudioDeviceInfo.AudioDeviceTypeOut int deviceType)1278 public float getStreamVolumeDb(@PublicStreamTypes int streamType, int index, 1279 @AudioDeviceInfo.AudioDeviceTypeOut int deviceType) { 1280 if (!isPublicStreamType(streamType)) { 1281 throw new IllegalArgumentException("Invalid stream type " + streamType); 1282 } 1283 if (index > getStreamMaxVolume(streamType) || index < getStreamMinVolume(streamType)) { 1284 throw new IllegalArgumentException("Invalid stream volume index " + index); 1285 } 1286 if (!AudioDeviceInfo.isValidAudioDeviceTypeOut(deviceType)) { 1287 throw new IllegalArgumentException("Invalid audio output device type " + deviceType); 1288 } 1289 final float gain = AudioSystem.getStreamVolumeDB(streamType, index, 1290 AudioDeviceInfo.convertDeviceTypeToInternalDevice(deviceType)); 1291 if (gain <= VOLUME_MIN_DB) { 1292 return Float.NEGATIVE_INFINITY; 1293 } else { 1294 return gain; 1295 } 1296 } 1297 1298 /** 1299 * @hide 1300 * Checks whether a stream type is part of the public SDK 1301 * @param streamType 1302 * @return true if the stream type is available in SDK 1303 */ isPublicStreamType(int streamType)1304 public static boolean isPublicStreamType(int streamType) { 1305 switch (streamType) { 1306 case STREAM_VOICE_CALL: 1307 case STREAM_SYSTEM: 1308 case STREAM_RING: 1309 case STREAM_MUSIC: 1310 case STREAM_ALARM: 1311 case STREAM_NOTIFICATION: 1312 case STREAM_DTMF: 1313 case STREAM_ACCESSIBILITY: 1314 return true; 1315 default: 1316 return false; 1317 } 1318 } 1319 1320 /** 1321 * Get last audible volume before stream was muted. 1322 * 1323 * @hide 1324 */ 1325 @SystemApi 1326 @RequiresPermission("android.permission.QUERY_AUDIO_STATE") getLastAudibleStreamVolume(int streamType)1327 public int getLastAudibleStreamVolume(int streamType) { 1328 final IAudioService service = getService(); 1329 try { 1330 return service.getLastAudibleStreamVolume(streamType); 1331 } catch (RemoteException e) { 1332 throw e.rethrowFromSystemServer(); 1333 } 1334 } 1335 1336 /** 1337 * Get the stream type whose volume is driving the UI sounds volume. 1338 * UI sounds are screen lock/unlock, camera shutter, key clicks... 1339 * It is assumed that this stream type is also tied to ringer mode changes. 1340 * @hide 1341 */ getUiSoundsStreamType()1342 public int getUiSoundsStreamType() { 1343 final IAudioService service = getService(); 1344 try { 1345 return service.getUiSoundsStreamType(); 1346 } catch (RemoteException e) { 1347 throw e.rethrowFromSystemServer(); 1348 } 1349 } 1350 1351 /** 1352 * Sets the ringer mode. 1353 * <p> 1354 * Silent mode will mute the volume and will not vibrate. Vibrate mode will 1355 * mute the volume and vibrate. Normal mode will be audible and may vibrate 1356 * according to user settings. 1357 * <p>This method has no effect if the device implements a fixed volume policy 1358 * as indicated by {@link #isVolumeFixed()}. 1359 * * <p>From N onward, ringer mode adjustments that would toggle Do Not Disturb are not allowed 1360 * unless the app has been granted Do Not Disturb Access. 1361 * See {@link NotificationManager#isNotificationPolicyAccessGranted()}. 1362 * @param ringerMode The ringer mode, one of {@link #RINGER_MODE_NORMAL}, 1363 * {@link #RINGER_MODE_SILENT}, or {@link #RINGER_MODE_VIBRATE}. 1364 * @see #getRingerMode() 1365 * @see #isVolumeFixed() 1366 */ setRingerMode(int ringerMode)1367 public void setRingerMode(int ringerMode) { 1368 if (!isValidRingerMode(ringerMode)) { 1369 return; 1370 } 1371 final IAudioService service = getService(); 1372 try { 1373 service.setRingerModeExternal(ringerMode, getContext().getOpPackageName()); 1374 } catch (RemoteException e) { 1375 throw e.rethrowFromSystemServer(); 1376 } 1377 } 1378 1379 /** 1380 * Sets the volume index for a particular stream. 1381 * <p>This method has no effect if the device implements a fixed volume policy 1382 * as indicated by {@link #isVolumeFixed()}. 1383 * <p>From N onward, volume adjustments that would toggle Do Not Disturb are not allowed unless 1384 * the app has been granted Do Not Disturb Access. 1385 * See {@link NotificationManager#isNotificationPolicyAccessGranted()}. 1386 * @param streamType The stream whose volume index should be set. 1387 * @param index The volume index to set. See 1388 * {@link #getStreamMaxVolume(int)} for the largest valid value. 1389 * @param flags 1390 * @see #getStreamMaxVolume(int) 1391 * @see #getStreamVolume(int) 1392 * @see #isVolumeFixed() 1393 * @throws SecurityException if the volume change triggers a Do Not Disturb change 1394 * and the caller is not granted notification policy access. 1395 */ setStreamVolume(int streamType, int index, @PublicVolumeFlags int flags)1396 public void setStreamVolume(int streamType, int index, @PublicVolumeFlags int flags) { 1397 final IAudioService service = getService(); 1398 try { 1399 service.setStreamVolumeWithAttribution(streamType, index, flags, 1400 getContext().getOpPackageName(), getContext().getAttributionTag()); 1401 } catch (RemoteException e) { 1402 throw e.rethrowFromSystemServer(); 1403 } 1404 } 1405 1406 /** 1407 * Sets the volume index for a particular {@link AudioAttributes}. 1408 * @param attr The {@link AudioAttributes} whose volume index should be set. 1409 * @param index The volume index to set. See 1410 * {@link #getMaxVolumeIndexForAttributes(AudioAttributes)} for the largest valid value 1411 * {@link #getMinVolumeIndexForAttributes(AudioAttributes)} for the lowest valid value. 1412 * @param flags 1413 * @see #getMaxVolumeIndexForAttributes(AudioAttributes) 1414 * @see #getMinVolumeIndexForAttributes(AudioAttributes) 1415 * @see #isVolumeFixed() 1416 * @hide 1417 */ 1418 @SystemApi 1419 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) setVolumeIndexForAttributes(@onNull AudioAttributes attr, int index, @SystemVolumeFlags int flags)1420 public void setVolumeIndexForAttributes(@NonNull AudioAttributes attr, int index, 1421 @SystemVolumeFlags int flags) { 1422 Preconditions.checkNotNull(attr, "attr must not be null"); 1423 final IAudioService service = getService(); 1424 int groupId = getVolumeGroupIdForAttributes(attr); 1425 setVolumeGroupVolumeIndex(groupId, index, flags); 1426 } 1427 1428 /** 1429 * Returns the current volume index for a particular {@link AudioAttributes}. 1430 * 1431 * @param attr The {@link AudioAttributes} whose volume index is returned. 1432 * @return The current volume index for the stream. 1433 * @see #getMaxVolumeIndexForAttributes(AudioAttributes) 1434 * @see #getMinVolumeIndexForAttributes(AudioAttributes) 1435 * @see #setVolumeForAttributes(AudioAttributes, int, int) 1436 * @hide 1437 */ 1438 @SystemApi 1439 @IntRange(from = 0) 1440 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) getVolumeIndexForAttributes(@onNull AudioAttributes attr)1441 public int getVolumeIndexForAttributes(@NonNull AudioAttributes attr) { 1442 Preconditions.checkNotNull(attr, "attr must not be null"); 1443 final IAudioService service = getService(); 1444 int groupId = getVolumeGroupIdForAttributes(attr); 1445 return getVolumeGroupVolumeIndex(groupId); 1446 } 1447 1448 /** 1449 * Returns the maximum volume index for a particular {@link AudioAttributes}. 1450 * 1451 * @param attr The {@link AudioAttributes} whose maximum volume index is returned. 1452 * @return The maximum valid volume index for the {@link AudioAttributes}. 1453 * @see #getVolumeIndexForAttributes(AudioAttributes) 1454 * @hide 1455 */ 1456 @SystemApi 1457 @IntRange(from = 0) 1458 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) getMaxVolumeIndexForAttributes(@onNull AudioAttributes attr)1459 public int getMaxVolumeIndexForAttributes(@NonNull AudioAttributes attr) { 1460 Preconditions.checkNotNull(attr, "attr must not be null"); 1461 final IAudioService service = getService(); 1462 int groupId = getVolumeGroupIdForAttributes(attr); 1463 return getVolumeGroupMaxVolumeIndex(groupId); 1464 } 1465 1466 /** 1467 * Returns the minimum volume index for a particular {@link AudioAttributes}. 1468 * 1469 * @param attr The {@link AudioAttributes} whose minimum volume index is returned. 1470 * @return The minimum valid volume index for the {@link AudioAttributes}. 1471 * @see #getVolumeIndexForAttributes(AudioAttributes) 1472 * @hide 1473 */ 1474 @SystemApi 1475 @IntRange(from = 0) 1476 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) getMinVolumeIndexForAttributes(@onNull AudioAttributes attr)1477 public int getMinVolumeIndexForAttributes(@NonNull AudioAttributes attr) { 1478 Preconditions.checkNotNull(attr, "attr must not be null"); 1479 final IAudioService service = getService(); 1480 int groupId = getVolumeGroupIdForAttributes(attr); 1481 return getVolumeGroupMinVolumeIndex(groupId); 1482 } 1483 1484 /** 1485 * Returns the volume group id associated to the given {@link AudioAttributes}. 1486 * 1487 * @param attributes The {@link AudioAttributes} to consider. 1488 * @return {@link android.media.audiopolicy.AudioVolumeGroup} id supporting the given 1489 * {@link AudioAttributes} if found, 1490 * {@code android.media.audiopolicy.AudioVolumeGroup.DEFAULT_VOLUME_GROUP} otherwise. 1491 */ getVolumeGroupIdForAttributes(@onNull AudioAttributes attributes)1492 public int getVolumeGroupIdForAttributes(@NonNull AudioAttributes attributes) { 1493 Preconditions.checkNotNull(attributes, "Audio Attributes must not be null"); 1494 return AudioProductStrategy.getVolumeGroupIdForAudioAttributes(attributes, 1495 /* fallbackOnDefault= */ true); 1496 } 1497 1498 /** 1499 * Sets the volume index for a particular group associated to given id. 1500 * <p> Call first in prior {@link #getVolumeGroupIdForAttributes(AudioAttributes)} 1501 * to retrieve the volume group id supporting the given {@link AudioAttributes}. 1502 * 1503 * @param groupId of the {@link android.media.audiopolicy.AudioVolumeGroup} to consider. 1504 * @param index The volume index to set. See 1505 * {@link #getVolumeGroupMaxVolumeIndex(id)} for the largest valid value 1506 * {@link #getVolumeGroupMinVolumeIndex(id)} for the lowest valid value. 1507 * @param flags 1508 * @hide 1509 */ 1510 @SystemApi 1511 @RequiresPermission(anyOf = { 1512 android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED, 1513 android.Manifest.permission.MODIFY_AUDIO_ROUTING 1514 }) setVolumeGroupVolumeIndex(int groupId, int index, @SystemVolumeFlags int flags)1515 public void setVolumeGroupVolumeIndex(int groupId, int index, @SystemVolumeFlags int flags) { 1516 final IAudioService service = getService(); 1517 try { 1518 service.setVolumeGroupVolumeIndex(groupId, index, flags, 1519 getContext().getOpPackageName(), getContext().getAttributionTag()); 1520 } catch (RemoteException e) { 1521 throw e.rethrowFromSystemServer(); 1522 } 1523 } 1524 1525 /** 1526 * Returns the current volume index for a particular group associated to given id. 1527 * <p> Call first in prior {@link #getVolumeGroupIdForAttributes(AudioAttributes)} 1528 * to retrieve the volume group id supporting the given {@link AudioAttributes}. 1529 * 1530 * @param groupId of the {@link android.media.audiopolicy.AudioVolumeGroup} to consider. 1531 * @return The current volume index for the stream. 1532 * @hide 1533 */ 1534 @SystemApi 1535 @IntRange(from = 0) 1536 @RequiresPermission(anyOf = { 1537 android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED, 1538 android.Manifest.permission.MODIFY_AUDIO_ROUTING 1539 }) getVolumeGroupVolumeIndex(int groupId)1540 public int getVolumeGroupVolumeIndex(int groupId) { 1541 final IAudioService service = getService(); 1542 try { 1543 return service.getVolumeGroupVolumeIndex(groupId); 1544 } catch (RemoteException e) { 1545 throw e.rethrowFromSystemServer(); 1546 } 1547 } 1548 1549 /** 1550 * Returns the maximum volume index for a particular group associated to given id. 1551 * <p> Call first in prior {@link #getVolumeGroupIdForAttributes(AudioAttributes)} 1552 * to retrieve the volume group id supporting the given {@link AudioAttributes}. 1553 * 1554 * @param groupId of the {@link android.media.audiopolicy.AudioVolumeGroup} to consider. 1555 * @return The maximum valid volume index for the {@link AudioAttributes}. 1556 * @hide 1557 */ 1558 @SystemApi 1559 @IntRange(from = 0) 1560 @RequiresPermission(anyOf = { 1561 android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED, 1562 android.Manifest.permission.MODIFY_AUDIO_ROUTING 1563 }) getVolumeGroupMaxVolumeIndex(int groupId)1564 public int getVolumeGroupMaxVolumeIndex(int groupId) { 1565 final IAudioService service = getService(); 1566 try { 1567 return service.getVolumeGroupMaxVolumeIndex(groupId); 1568 } catch (RemoteException e) { 1569 throw e.rethrowFromSystemServer(); 1570 } 1571 } 1572 1573 /** 1574 * Returns the minimum volume index for a particular group associated to given id. 1575 * <p> Call first in prior {@link #getVolumeGroupIdForAttributes(AudioAttributes)} 1576 * to retrieve the volume group id supporting the given {@link AudioAttributes}. 1577 * 1578 * @param groupId of the {@link android.media.audiopolicy.AudioVolumeGroup} to consider. 1579 * @return The minimum valid volume index for the {@link AudioAttributes}. 1580 * @hide 1581 */ 1582 @SystemApi 1583 @IntRange(from = 0) 1584 @RequiresPermission(anyOf = { 1585 android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED, 1586 android.Manifest.permission.MODIFY_AUDIO_ROUTING 1587 }) getVolumeGroupMinVolumeIndex(int groupId)1588 public int getVolumeGroupMinVolumeIndex(int groupId) { 1589 final IAudioService service = getService(); 1590 try { 1591 return service.getVolumeGroupMinVolumeIndex(groupId); 1592 } catch (RemoteException e) { 1593 throw e.rethrowFromSystemServer(); 1594 } 1595 } 1596 1597 /** 1598 * Adjusts the volume of a particular group associated to given id by one step in a direction. 1599 * <p> If the volume group is associated to a stream type, it fallbacks on 1600 * {@link #adjustStreamVolume(int, int, int)} for compatibility reason. 1601 * <p> Call first in prior {@link #getVolumeGroupIdForAttributes(AudioAttributes)} to retrieve 1602 * the volume group id supporting the given {@link AudioAttributes}. 1603 * 1604 * @param groupId of the {@link android.media.audiopolicy.AudioVolumeGroup} to consider. 1605 * @param direction The direction to adjust the volume. One of 1606 * {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, or 1607 * {@link #ADJUST_SAME}. 1608 * @param flags 1609 * @throws SecurityException if the adjustment triggers a Do Not Disturb change and the caller 1610 * is not granted notification policy access. 1611 */ adjustVolumeGroupVolume(int groupId, int direction, @PublicVolumeFlags int flags)1612 public void adjustVolumeGroupVolume(int groupId, int direction, @PublicVolumeFlags int flags) { 1613 IAudioService service = getService(); 1614 try { 1615 service.adjustVolumeGroupVolume(groupId, direction, flags, 1616 getContext().getOpPackageName()); 1617 } catch (RemoteException e) { 1618 throw e.rethrowFromSystemServer(); 1619 } 1620 } 1621 1622 /** 1623 * Get last audible volume of the group associated to given id before it was muted. 1624 * <p> Call first in prior {@link #getVolumeGroupIdForAttributes(AudioAttributes)} to retrieve 1625 * the volume group id supporting the given {@link AudioAttributes}. 1626 * 1627 * @param groupId of the {@link android.media.audiopolicy.AudioVolumeGroup} to consider. 1628 * @return current volume if not muted, volume before muted otherwise. 1629 * @hide 1630 */ 1631 @SystemApi 1632 @RequiresPermission("android.permission.QUERY_AUDIO_STATE") 1633 @IntRange(from = 0) getLastAudibleVolumeForVolumeGroup(int groupId)1634 public int getLastAudibleVolumeForVolumeGroup(int groupId) { 1635 IAudioService service = getService(); 1636 try { 1637 return service.getLastAudibleVolumeForVolumeGroup(groupId); 1638 } catch (RemoteException e) { 1639 throw e.rethrowFromSystemServer(); 1640 } 1641 } 1642 1643 /** 1644 * Returns the current mute state for a particular volume group associated to the given id. 1645 * <p> Call first in prior {@link #getVolumeGroupIdForAttributes(AudioAttributes)} to retrieve 1646 * the volume group id supporting the given {@link AudioAttributes}. 1647 * 1648 * @param groupId of the {@link android.media.audiopolicy.AudioVolumeGroup} to consider. 1649 * @return The mute state for the given {@link android.media.audiopolicy.AudioVolumeGroup} id. 1650 * @see #adjustVolumeGroupVolume(int, int, int) 1651 */ isVolumeGroupMuted(int groupId)1652 public boolean isVolumeGroupMuted(int groupId) { 1653 IAudioService service = getService(); 1654 try { 1655 return service.isVolumeGroupMuted(groupId); 1656 } catch (RemoteException e) { 1657 throw e.rethrowFromSystemServer(); 1658 } 1659 } 1660 1661 /** 1662 * Set the system usages to be supported on this device. 1663 * @param systemUsages array of system usages to support {@link AttributeSystemUsage} 1664 * @hide 1665 */ 1666 @SystemApi 1667 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) setSupportedSystemUsages(@onNull @ttributeSystemUsage int[] systemUsages)1668 public void setSupportedSystemUsages(@NonNull @AttributeSystemUsage int[] systemUsages) { 1669 Objects.requireNonNull(systemUsages, "systemUsages must not be null"); 1670 final IAudioService service = getService(); 1671 try { 1672 service.setSupportedSystemUsages(systemUsages); 1673 } catch (RemoteException e) { 1674 throw e.rethrowFromSystemServer(); 1675 } 1676 } 1677 1678 /** 1679 * Get the system usages supported on this device. 1680 * @return array of supported system usages {@link AttributeSystemUsage} 1681 * @hide 1682 */ 1683 @SystemApi 1684 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) getSupportedSystemUsages()1685 public @NonNull @AttributeSystemUsage int[] getSupportedSystemUsages() { 1686 final IAudioService service = getService(); 1687 try { 1688 return service.getSupportedSystemUsages(); 1689 } catch (RemoteException e) { 1690 throw e.rethrowFromSystemServer(); 1691 } 1692 } 1693 1694 /** 1695 * Solo or unsolo a particular stream. 1696 * <p> 1697 * Do not use. This method has been deprecated and is now a no-op. 1698 * {@link #requestAudioFocus} should be used for exclusive audio playback. 1699 * 1700 * @param streamType The stream to be soloed/unsoloed. 1701 * @param state The required solo state: true for solo ON, false for solo 1702 * OFF 1703 * @see #isVolumeFixed() 1704 * @deprecated Do not use. If you need exclusive audio playback use 1705 * {@link #requestAudioFocus}. 1706 */ 1707 @Deprecated setStreamSolo(int streamType, boolean state)1708 public void setStreamSolo(int streamType, boolean state) { 1709 Log.w(TAG, "setStreamSolo has been deprecated. Do not use."); 1710 } 1711 1712 /** 1713 * Mute or unmute an audio stream. 1714 * <p> 1715 * This method should only be used by applications that replace the 1716 * platform-wide management of audio settings or the main telephony 1717 * application. 1718 * <p> 1719 * This method has no effect if the device implements a fixed volume policy 1720 * as indicated by {@link #isVolumeFixed()}. 1721 * <p> 1722 * This method was deprecated in API level 22. Prior to API level 22 this 1723 * method had significantly different behavior and should be used carefully. 1724 * The following applies only to pre-22 platforms: 1725 * <ul> 1726 * <li>The mute command is protected against client process death: if a 1727 * process with an active mute request on a stream dies, this stream will be 1728 * unmuted automatically.</li> 1729 * <li>The mute requests for a given stream are cumulative: the AudioManager 1730 * can receive several mute requests from one or more clients and the stream 1731 * will be unmuted only when the same number of unmute requests are 1732 * received.</li> 1733 * <li>For a better user experience, applications MUST unmute a muted stream 1734 * in onPause() and mute is again in onResume() if appropriate.</li> 1735 * </ul> 1736 * 1737 * @param streamType The stream to be muted/unmuted. 1738 * @param state The required mute state: true for mute ON, false for mute 1739 * OFF 1740 * @see #isVolumeFixed() 1741 * @deprecated Use {@link #adjustStreamVolume(int, int, int)} with 1742 * {@link #ADJUST_MUTE} or {@link #ADJUST_UNMUTE} instead. 1743 */ 1744 @Deprecated setStreamMute(int streamType, boolean state)1745 public void setStreamMute(int streamType, boolean state) { 1746 Log.w(TAG, "setStreamMute is deprecated. adjustStreamVolume should be used instead."); 1747 int direction = state ? ADJUST_MUTE : ADJUST_UNMUTE; 1748 if (streamType == AudioManager.USE_DEFAULT_STREAM_TYPE) { 1749 adjustSuggestedStreamVolume(direction, streamType, 0); 1750 } else { 1751 adjustStreamVolume(streamType, direction, 0); 1752 } 1753 } 1754 1755 /** 1756 * Returns the current mute state for a particular stream. 1757 * 1758 * @param streamType The stream to get mute state for. 1759 * @return The mute state for the given stream. 1760 * @see #adjustStreamVolume(int, int, int) 1761 */ isStreamMute(int streamType)1762 public boolean isStreamMute(int streamType) { 1763 final IAudioService service = getService(); 1764 try { 1765 return service.isStreamMute(streamType); 1766 } catch (RemoteException e) { 1767 throw e.rethrowFromSystemServer(); 1768 } 1769 } 1770 1771 /** 1772 * get master mute state. 1773 * 1774 * @hide 1775 */ 1776 @UnsupportedAppUsage isMasterMute()1777 public boolean isMasterMute() { 1778 final IAudioService service = getService(); 1779 try { 1780 return service.isMasterMute(); 1781 } catch (RemoteException e) { 1782 throw e.rethrowFromSystemServer(); 1783 } 1784 } 1785 1786 /** 1787 * forces the stream controlled by hard volume keys 1788 * specifying streamType == -1 releases control to the 1789 * logic. 1790 * 1791 * @hide 1792 */ 1793 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) 1794 @UnsupportedAppUsage forceVolumeControlStream(int streamType)1795 public void forceVolumeControlStream(int streamType) { 1796 final IAudioService service = getService(); 1797 try { 1798 service.forceVolumeControlStream(streamType, mICallBack); 1799 } catch (RemoteException e) { 1800 throw e.rethrowFromSystemServer(); 1801 } 1802 } 1803 1804 /** 1805 * Returns whether a particular type should vibrate according to user 1806 * settings and the current ringer mode. 1807 * <p> 1808 * This shouldn't be needed by most clients that use notifications to 1809 * vibrate. The notification manager will not vibrate if the policy doesn't 1810 * allow it, so the client should always set a vibrate pattern and let the 1811 * notification manager control whether or not to actually vibrate. 1812 * 1813 * @param vibrateType The type of vibrate. One of 1814 * {@link #VIBRATE_TYPE_NOTIFICATION} or 1815 * {@link #VIBRATE_TYPE_RINGER}. 1816 * @return Whether the type should vibrate at the instant this method is 1817 * called. 1818 * @see #setVibrateSetting(int, int) 1819 * @see #getVibrateSetting(int) 1820 * @deprecated Applications should maintain their own vibrate policy based on 1821 * current ringer mode that can be queried via {@link #getRingerMode()}. 1822 */ shouldVibrate(int vibrateType)1823 public boolean shouldVibrate(int vibrateType) { 1824 final IAudioService service = getService(); 1825 try { 1826 return service.shouldVibrate(vibrateType); 1827 } catch (RemoteException e) { 1828 throw e.rethrowFromSystemServer(); 1829 } 1830 } 1831 1832 /** 1833 * Returns whether the user's vibrate setting for a vibrate type. 1834 * <p> 1835 * This shouldn't be needed by most clients that want to vibrate, instead 1836 * see {@link #shouldVibrate(int)}. 1837 * 1838 * @param vibrateType The type of vibrate. One of 1839 * {@link #VIBRATE_TYPE_NOTIFICATION} or 1840 * {@link #VIBRATE_TYPE_RINGER}. 1841 * @return The vibrate setting, one of {@link #VIBRATE_SETTING_ON}, 1842 * {@link #VIBRATE_SETTING_OFF}, or 1843 * {@link #VIBRATE_SETTING_ONLY_SILENT}. 1844 * @see #setVibrateSetting(int, int) 1845 * @see #shouldVibrate(int) 1846 * @deprecated Applications should maintain their own vibrate policy based on 1847 * current ringer mode that can be queried via {@link #getRingerMode()}. 1848 */ getVibrateSetting(int vibrateType)1849 public int getVibrateSetting(int vibrateType) { 1850 final IAudioService service = getService(); 1851 try { 1852 return service.getVibrateSetting(vibrateType); 1853 } catch (RemoteException e) { 1854 throw e.rethrowFromSystemServer(); 1855 } 1856 } 1857 1858 /** 1859 * Sets the setting for when the vibrate type should vibrate. 1860 * <p> 1861 * This method should only be used by applications that replace the platform-wide 1862 * management of audio settings or the main telephony application. 1863 * 1864 * @param vibrateType The type of vibrate. One of 1865 * {@link #VIBRATE_TYPE_NOTIFICATION} or 1866 * {@link #VIBRATE_TYPE_RINGER}. 1867 * @param vibrateSetting The vibrate setting, one of 1868 * {@link #VIBRATE_SETTING_ON}, 1869 * {@link #VIBRATE_SETTING_OFF}, or 1870 * {@link #VIBRATE_SETTING_ONLY_SILENT}. 1871 * @see #getVibrateSetting(int) 1872 * @see #shouldVibrate(int) 1873 * @deprecated Applications should maintain their own vibrate policy based on 1874 * current ringer mode that can be queried via {@link #getRingerMode()}. 1875 */ setVibrateSetting(int vibrateType, int vibrateSetting)1876 public void setVibrateSetting(int vibrateType, int vibrateSetting) { 1877 final IAudioService service = getService(); 1878 try { 1879 service.setVibrateSetting(vibrateType, vibrateSetting); 1880 } catch (RemoteException e) { 1881 throw e.rethrowFromSystemServer(); 1882 } 1883 } 1884 1885 /** 1886 * Sets the speakerphone on or off. 1887 * <p> 1888 * This method should only be used by applications that replace the platform-wide 1889 * management of audio settings or the main telephony application. 1890 * 1891 * @param on set <var>true</var> to turn on speakerphone; 1892 * <var>false</var> to turn it off 1893 * @deprecated Use {@link AudioManager#setCommunicationDevice(AudioDeviceInfo)} or 1894 * {@link AudioManager#clearCommunicationDevice()} instead. 1895 */ setSpeakerphoneOn(boolean on)1896 @Deprecated public void setSpeakerphoneOn(boolean on) { 1897 final IAudioService service = getService(); 1898 try { 1899 service.setSpeakerphoneOn(mICallBack, on); 1900 } catch (RemoteException e) { 1901 throw e.rethrowFromSystemServer(); 1902 } 1903 } 1904 1905 /** 1906 * Checks whether the speakerphone is on or off. 1907 * 1908 * @return true if speakerphone is on, false if it's off 1909 * @deprecated Use {@link AudioManager#getCommunicationDevice()} instead. 1910 */ isSpeakerphoneOn()1911 @Deprecated public boolean isSpeakerphoneOn() { 1912 final IAudioService service = getService(); 1913 try { 1914 return service.isSpeakerphoneOn(); 1915 } catch (RemoteException e) { 1916 throw e.rethrowFromSystemServer(); 1917 } 1918 } 1919 1920 /** 1921 * Specifies whether the audio played by this app may or may not be captured by other apps or 1922 * the system. 1923 * 1924 * The default is {@link AudioAttributes#ALLOW_CAPTURE_BY_ALL}. 1925 * 1926 * There are multiple ways to set this policy: 1927 * <ul> 1928 * <li> for each track independently, see 1929 * {@link AudioAttributes.Builder#setAllowedCapturePolicy(int)} </li> 1930 * <li> application-wide at runtime, with this method </li> 1931 * <li> application-wide at build time, see {@code allowAudioPlaybackCapture} in the application 1932 * manifest. </li> 1933 * </ul> 1934 * The most restrictive policy is always applied. 1935 * 1936 * See {@link AudioPlaybackCaptureConfiguration} for more details on 1937 * which audio signals can be captured. 1938 * 1939 * @param capturePolicy one of 1940 * {@link AudioAttributes#ALLOW_CAPTURE_BY_ALL}, 1941 * {@link AudioAttributes#ALLOW_CAPTURE_BY_SYSTEM}, 1942 * {@link AudioAttributes#ALLOW_CAPTURE_BY_NONE}. 1943 * @throws RuntimeException if the argument is not a valid value. 1944 */ setAllowedCapturePolicy(@udioAttributes.CapturePolicy int capturePolicy)1945 public void setAllowedCapturePolicy(@AudioAttributes.CapturePolicy int capturePolicy) { 1946 // TODO: also pass the package in case multiple packages have the same UID 1947 final IAudioService service = getService(); 1948 try { 1949 int result = service.setAllowedCapturePolicy(capturePolicy); 1950 if (result != AudioSystem.AUDIO_STATUS_OK) { 1951 Log.e(TAG, "Could not setAllowedCapturePolicy: " + result); 1952 return; 1953 } 1954 } catch (RemoteException e) { 1955 throw e.rethrowFromSystemServer(); 1956 } 1957 } 1958 1959 /** 1960 * Return the capture policy. 1961 * @return the capture policy set by {@link #setAllowedCapturePolicy(int)} or 1962 * the default if it was not called. 1963 */ 1964 @AudioAttributes.CapturePolicy getAllowedCapturePolicy()1965 public int getAllowedCapturePolicy() { 1966 int result = AudioAttributes.ALLOW_CAPTURE_BY_ALL; 1967 try { 1968 result = getService().getAllowedCapturePolicy(); 1969 } catch (RemoteException e) { 1970 Log.e(TAG, "Failed to query allowed capture policy: " + e); 1971 } 1972 return result; 1973 } 1974 1975 //==================================================================== 1976 // Audio Product Strategy routing 1977 1978 /** 1979 * @hide 1980 * Set the preferred device for a given strategy, i.e. the audio routing to be used by 1981 * this audio strategy. Note that the device may not be available at the time the preferred 1982 * device is set, but it will be used once made available. 1983 * <p>Use {@link #removePreferredDeviceForStrategy(AudioProductStrategy)} to cancel setting 1984 * this preference for this strategy.</p> 1985 * @param strategy the audio strategy whose routing will be affected 1986 * @param device the audio device to route to when available 1987 * @return true if the operation was successful, false otherwise 1988 */ 1989 @SystemApi 1990 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) setPreferredDeviceForStrategy(@onNull AudioProductStrategy strategy, @NonNull AudioDeviceAttributes device)1991 public boolean setPreferredDeviceForStrategy(@NonNull AudioProductStrategy strategy, 1992 @NonNull AudioDeviceAttributes device) { 1993 return setPreferredDevicesForStrategy(strategy, Arrays.asList(device)); 1994 } 1995 1996 /** 1997 * @hide 1998 * Removes the preferred audio device(s) previously set with 1999 * {@link #setPreferredDeviceForStrategy(AudioProductStrategy, AudioDeviceAttributes)} or 2000 * {@link #setPreferredDevicesForStrategy(AudioProductStrategy, List<AudioDeviceAttributes>)}. 2001 * @param strategy the audio strategy whose routing will be affected 2002 * @return true if the operation was successful, false otherwise (invalid strategy, or no 2003 * device set for example) 2004 */ 2005 @SystemApi 2006 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) removePreferredDeviceForStrategy(@onNull AudioProductStrategy strategy)2007 public boolean removePreferredDeviceForStrategy(@NonNull AudioProductStrategy strategy) { 2008 Objects.requireNonNull(strategy); 2009 try { 2010 final int status = 2011 getService().removePreferredDevicesForStrategy(strategy.getId()); 2012 return status == AudioSystem.SUCCESS; 2013 } catch (RemoteException e) { 2014 throw e.rethrowFromSystemServer(); 2015 } 2016 } 2017 2018 /** 2019 * @hide 2020 * Return the preferred device for an audio strategy, previously set with 2021 * {@link #setPreferredDeviceForStrategy(AudioProductStrategy, AudioDeviceAttributes)} or 2022 * {@link #setPreferredDevicesForStrategy(AudioProductStrategy, List<AudioDeviceAttributes>)} 2023 * @param strategy the strategy to query 2024 * @return the preferred device for that strategy, if multiple devices are set as preferred 2025 * devices, the first one in the list will be returned. Null will be returned if none was 2026 * ever set or if the strategy is invalid 2027 */ 2028 @SystemApi 2029 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) 2030 @Nullable getPreferredDeviceForStrategy( @onNull AudioProductStrategy strategy)2031 public AudioDeviceAttributes getPreferredDeviceForStrategy( 2032 @NonNull AudioProductStrategy strategy) { 2033 List<AudioDeviceAttributes> devices = getPreferredDevicesForStrategy(strategy); 2034 return devices.isEmpty() ? null : devices.get(0); 2035 } 2036 2037 /** 2038 * @hide 2039 * Set the preferred devices for a given strategy, i.e. the audio routing to be used by 2040 * this audio strategy. Note that the devices may not be available at the time the preferred 2041 * devices is set, but it will be used once made available. 2042 * <p>Use {@link #removePreferredDeviceForStrategy(AudioProductStrategy)} to cancel setting 2043 * this preference for this strategy.</p> 2044 * Note that the list of devices is not a list ranked by preference, but a list of one or more 2045 * devices used simultaneously to output the same audio signal. 2046 * @param strategy the audio strategy whose routing will be affected 2047 * @param devices a non-empty list of the audio devices to route to when available 2048 * @return true if the operation was successful, false otherwise 2049 */ 2050 @SystemApi 2051 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) setPreferredDevicesForStrategy(@onNull AudioProductStrategy strategy, @NonNull List<AudioDeviceAttributes> devices)2052 public boolean setPreferredDevicesForStrategy(@NonNull AudioProductStrategy strategy, 2053 @NonNull List<AudioDeviceAttributes> devices) { 2054 Objects.requireNonNull(strategy); 2055 Objects.requireNonNull(devices); 2056 if (devices.isEmpty()) { 2057 throw new IllegalArgumentException( 2058 "Tried to set preferred devices for strategy with a empty list"); 2059 } 2060 for (AudioDeviceAttributes device : devices) { 2061 Objects.requireNonNull(device); 2062 } 2063 try { 2064 final int status = 2065 getService().setPreferredDevicesForStrategy(strategy.getId(), devices); 2066 return status == AudioSystem.SUCCESS; 2067 } catch (RemoteException e) { 2068 throw e.rethrowFromSystemServer(); 2069 } 2070 } 2071 2072 /** 2073 * @hide 2074 * Return the preferred devices for an audio strategy, previously set with 2075 * {@link #setPreferredDeviceForStrategy(AudioProductStrategy, AudioDeviceAttributes)} 2076 * {@link #setPreferredDevicesForStrategy(AudioProductStrategy, List<AudioDeviceAttributes>)} 2077 * @param strategy the strategy to query 2078 * @return list of the preferred devices for that strategy 2079 */ 2080 @SystemApi 2081 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) 2082 @NonNull getPreferredDevicesForStrategy( @onNull AudioProductStrategy strategy)2083 public List<AudioDeviceAttributes> getPreferredDevicesForStrategy( 2084 @NonNull AudioProductStrategy strategy) { 2085 Objects.requireNonNull(strategy); 2086 try { 2087 return getService().getPreferredDevicesForStrategy(strategy.getId()); 2088 } catch (RemoteException e) { 2089 throw e.rethrowFromSystemServer(); 2090 } 2091 } 2092 2093 /** 2094 * @hide 2095 * Set a device as non-default for a given strategy, i.e. the audio routing to be avoided by 2096 * this audio strategy. 2097 * <p>Use 2098 * {@link #removeDeviceAsNonDefaultForStrategy(AudioProductStrategy, AudioDeviceAttributes)} 2099 * to cancel setting this preference for this strategy.</p> 2100 * @param strategy the audio strategy whose routing will be affected 2101 * @param device the audio device to not route to when available 2102 * @return true if the operation was successful, false otherwise 2103 */ 2104 @SystemApi 2105 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) setDeviceAsNonDefaultForStrategy(@onNull AudioProductStrategy strategy, @NonNull AudioDeviceAttributes device)2106 public boolean setDeviceAsNonDefaultForStrategy(@NonNull AudioProductStrategy strategy, 2107 @NonNull AudioDeviceAttributes device) { 2108 Objects.requireNonNull(strategy); 2109 Objects.requireNonNull(device); 2110 try { 2111 final int status = 2112 getService().setDeviceAsNonDefaultForStrategy(strategy.getId(), device); 2113 return status == AudioSystem.SUCCESS; 2114 } catch (RemoteException e) { 2115 throw e.rethrowFromSystemServer(); 2116 } 2117 } 2118 2119 /** 2120 * @hide 2121 * Removes the audio device(s) from the non-default device list previously set with 2122 * {@link #setDeviceAsNonDefaultForStrategy(AudioProductStrategy, AudioDeviceAttributes)} 2123 * @param strategy the audio strategy whose routing will be affected 2124 * @param device the audio device to remove from the non-default device list 2125 * @return true if the operation was successful, false otherwise (invalid strategy, or no 2126 * device set for example) 2127 */ 2128 @SystemApi 2129 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) removeDeviceAsNonDefaultForStrategy(@onNull AudioProductStrategy strategy, @NonNull AudioDeviceAttributes device)2130 public boolean removeDeviceAsNonDefaultForStrategy(@NonNull AudioProductStrategy strategy, 2131 @NonNull AudioDeviceAttributes device) { 2132 Objects.requireNonNull(strategy); 2133 Objects.requireNonNull(device); 2134 try { 2135 final int status = 2136 getService().removeDeviceAsNonDefaultForStrategy(strategy.getId(), device); 2137 return status == AudioSystem.SUCCESS; 2138 } catch (RemoteException e) { 2139 throw e.rethrowFromSystemServer(); 2140 } 2141 } 2142 2143 /** 2144 * @hide 2145 * Gets the audio device(s) from the non-default device list previously set with 2146 * {@link #setDeviceAsNonDefaultForStrategy(AudioProductStrategy, AudioDeviceAttributes)} 2147 * @param strategy the audio strategy to query 2148 * @return list of non-default devices for the strategy 2149 */ 2150 @SystemApi 2151 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) 2152 @NonNull getNonDefaultDevicesForStrategy( @onNull AudioProductStrategy strategy)2153 public List<AudioDeviceAttributes> getNonDefaultDevicesForStrategy( 2154 @NonNull AudioProductStrategy strategy) { 2155 Objects.requireNonNull(strategy); 2156 try { 2157 return getService().getNonDefaultDevicesForStrategy(strategy.getId()); 2158 } catch (RemoteException e) { 2159 throw e.rethrowFromSystemServer(); 2160 } 2161 } 2162 2163 /** 2164 * @hide 2165 * Interface to be notified of changes in the preferred audio device set for a given audio 2166 * strategy. 2167 * <p>Note that this listener will only be invoked whenever 2168 * {@link #setPreferredDeviceForStrategy(AudioProductStrategy, AudioDeviceAttributes)} or 2169 * {@link #setPreferredDevicesForStrategy(AudioProductStrategy, List<AudioDeviceAttributes>)} 2170 * {@link #removePreferredDeviceForStrategy(AudioProductStrategy)} causes a change in 2171 * preferred device. It will not be invoked directly after registration with 2172 * {@link #addOnPreferredDeviceForStrategyChangedListener(Executor, OnPreferredDeviceForStrategyChangedListener)} 2173 * to indicate which strategies had preferred devices at the time of registration.</p> 2174 * @see #setPreferredDeviceForStrategy(AudioProductStrategy, AudioDeviceAttributes) 2175 * @see #removePreferredDeviceForStrategy(AudioProductStrategy) 2176 * @see #getPreferredDeviceForStrategy(AudioProductStrategy) 2177 * @deprecated use #OnPreferredDevicesForStrategyChangedListener 2178 */ 2179 @SystemApi 2180 @Deprecated 2181 public interface OnPreferredDeviceForStrategyChangedListener { 2182 /** 2183 * Called on the listener to indicate that the preferred audio device for the given 2184 * strategy has changed. 2185 * @param strategy the {@link AudioProductStrategy} whose preferred device changed 2186 * @param device <code>null</code> if the preferred device was removed, or the newly set 2187 * preferred audio device 2188 */ onPreferredDeviceForStrategyChanged(@onNull AudioProductStrategy strategy, @Nullable AudioDeviceAttributes device)2189 void onPreferredDeviceForStrategyChanged(@NonNull AudioProductStrategy strategy, 2190 @Nullable AudioDeviceAttributes device); 2191 } 2192 2193 /** 2194 * @hide 2195 * Interface to be notified of changes in the preferred audio devices set for a given audio 2196 * strategy. 2197 * <p>Note that this listener will only be invoked whenever 2198 * {@link #setPreferredDeviceForStrategy(AudioProductStrategy, AudioDeviceAttributes)}, 2199 * {@link #setPreferredDevicesForStrategy(AudioProductStrategy, List<AudioDeviceAttributes>)}, 2200 * {@link #setDeviceAsNonDefaultForStrategy(AudioProductStrategy, AudioDeviceAttributes)}, 2201 * {@link #removeDeviceAsNonDefaultForStrategy(AudioProductStrategy, AudioDeviceAttributes)} 2202 * or {@link #removePreferredDeviceForStrategy(AudioProductStrategy)} causes a change in 2203 * preferred device(s). It will not be invoked directly after registration with 2204 * {@link #addOnPreferredDevicesForStrategyChangedListener( 2205 * Executor, OnPreferredDevicesForStrategyChangedListener)} 2206 * to indicate which strategies had preferred devices at the time of registration.</p> 2207 * @see #setPreferredDeviceForStrategy(AudioProductStrategy, AudioDeviceAttributes) 2208 * @see #setPreferredDevicesForStrategy(AudioProductStrategy, List) 2209 * @see #removePreferredDeviceForStrategy(AudioProductStrategy) 2210 * @see #getPreferredDevicesForStrategy(AudioProductStrategy) 2211 */ 2212 @SystemApi 2213 public interface OnPreferredDevicesForStrategyChangedListener { 2214 /** 2215 * Called on the listener to indicate that the preferred audio devices for the given 2216 * strategy has changed. 2217 * @param strategy the {@link AudioProductStrategy} whose preferred device changed 2218 * @param devices a list of newly set preferred audio devices 2219 */ onPreferredDevicesForStrategyChanged(@onNull AudioProductStrategy strategy, @NonNull List<AudioDeviceAttributes> devices)2220 void onPreferredDevicesForStrategyChanged(@NonNull AudioProductStrategy strategy, 2221 @NonNull List<AudioDeviceAttributes> devices); 2222 } 2223 2224 /** 2225 * @hide 2226 * Adds a listener for being notified of changes to the strategy-preferred audio device. 2227 * @param executor 2228 * @param listener 2229 * @throws SecurityException if the caller doesn't hold the required permission 2230 * @deprecated use {@link #addOnPreferredDevicesForStrategyChangedListener( 2231 * Executor, AudioManager.OnPreferredDevicesForStrategyChangedListener)} instead 2232 */ 2233 @SystemApi 2234 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) 2235 @Deprecated addOnPreferredDeviceForStrategyChangedListener( @onNull @allbackExecutor Executor executor, @NonNull OnPreferredDeviceForStrategyChangedListener listener)2236 public void addOnPreferredDeviceForStrategyChangedListener( 2237 @NonNull @CallbackExecutor Executor executor, 2238 @NonNull OnPreferredDeviceForStrategyChangedListener listener) 2239 throws SecurityException { 2240 // No-op, the method is deprecated. 2241 } 2242 2243 /** 2244 * @hide 2245 * Removes a previously added listener of changes to the strategy-preferred audio device. 2246 * @param listener 2247 * @deprecated use {@link #removeOnPreferredDevicesForStrategyChangedListener( 2248 * AudioManager.OnPreferredDevicesForStrategyChangedListener)} instead 2249 */ 2250 @SystemApi 2251 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) 2252 @Deprecated removeOnPreferredDeviceForStrategyChangedListener( @onNull OnPreferredDeviceForStrategyChangedListener listener)2253 public void removeOnPreferredDeviceForStrategyChangedListener( 2254 @NonNull OnPreferredDeviceForStrategyChangedListener listener) { 2255 // No-op, the method is deprecated. 2256 } 2257 2258 /** 2259 * @hide 2260 * Adds a listener for being notified of changes to the strategy-preferred audio device. 2261 * @param executor 2262 * @param listener 2263 * @throws SecurityException if the caller doesn't hold the required permission 2264 */ 2265 @SystemApi 2266 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) addOnPreferredDevicesForStrategyChangedListener( @onNull @allbackExecutor Executor executor, @NonNull OnPreferredDevicesForStrategyChangedListener listener)2267 public void addOnPreferredDevicesForStrategyChangedListener( 2268 @NonNull @CallbackExecutor Executor executor, 2269 @NonNull OnPreferredDevicesForStrategyChangedListener listener) 2270 throws SecurityException { 2271 Objects.requireNonNull(executor); 2272 Objects.requireNonNull(listener); 2273 mPrefDevListenerMgr.addListener( 2274 executor, listener, "addOnPreferredDevicesForStrategyChangedListener", 2275 () -> new StrategyPreferredDevicesDispatcherStub()); 2276 } 2277 2278 /** 2279 * @hide 2280 * Removes a previously added listener of changes to the strategy-preferred audio device. 2281 * @param listener 2282 */ 2283 @SystemApi 2284 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) removeOnPreferredDevicesForStrategyChangedListener( @onNull OnPreferredDevicesForStrategyChangedListener listener)2285 public void removeOnPreferredDevicesForStrategyChangedListener( 2286 @NonNull OnPreferredDevicesForStrategyChangedListener listener) { 2287 Objects.requireNonNull(listener); 2288 mPrefDevListenerMgr.removeListener( 2289 listener, "removeOnPreferredDevicesForStrategyChangedListener"); 2290 } 2291 2292 /** 2293 * @hide 2294 * Interface to be notified of changes in the non-default audio devices set for a given audio 2295 * strategy. 2296 * <p>Note that this listener will only be invoked whenever 2297 * {@link #setPreferredDeviceForStrategy(AudioProductStrategy, AudioDeviceAttributes)}, 2298 * {@link #setPreferredDevicesForStrategy(AudioProductStrategy, List<AudioDeviceAttributes>)}, 2299 * {@link #setDeviceAsNonDefaultForStrategy(AudioProductStrategy, AudioDeviceAttributes)}, 2300 * {@link #removeDeviceAsNonDefaultForStrategy(AudioProductStrategy, AudioDeviceAttributes)} 2301 * or {@link #removePreferredDeviceForStrategy(AudioProductStrategy)} causes a change in 2302 * non-default device(s). It will not be invoked directly after registration with 2303 * {@link #addOnNonDefaultDevicesForStrategyChangedListener( 2304 * Executor, OnNonDefaultDevicesForStrategyChangedListener)} 2305 * to indicate which strategies had preferred devices at the time of registration.</p> 2306 * @see #setDeviceAsNonDefaultForStrategy(AudioProductStrategy, AudioDeviceAttributes) 2307 * @see #removeDeviceAsNonDefaultForStrategy(AudioProductStrategy, AudioDeviceAttributes) 2308 */ 2309 @SystemApi 2310 public interface OnNonDefaultDevicesForStrategyChangedListener { 2311 /** 2312 * Called on the listener to indicate that the non-default audio devices for the given 2313 * strategy has changed. 2314 * @param strategy the {@link AudioProductStrategy} whose non-default device changed 2315 * @param devices a list of newly set non-default audio devices 2316 */ onNonDefaultDevicesForStrategyChanged(@onNull AudioProductStrategy strategy, @NonNull List<AudioDeviceAttributes> devices)2317 void onNonDefaultDevicesForStrategyChanged(@NonNull AudioProductStrategy strategy, 2318 @NonNull List<AudioDeviceAttributes> devices); 2319 } 2320 2321 /** 2322 * @hide 2323 * Adds a listener for being notified of changes to the non-default audio devices for 2324 * strategies. 2325 * @param executor 2326 * @param listener 2327 * @throws SecurityException if the caller doesn't hold the required permission 2328 */ 2329 @SystemApi 2330 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) addOnNonDefaultDevicesForStrategyChangedListener( @onNull @allbackExecutor Executor executor, @NonNull OnNonDefaultDevicesForStrategyChangedListener listener)2331 public void addOnNonDefaultDevicesForStrategyChangedListener( 2332 @NonNull @CallbackExecutor Executor executor, 2333 @NonNull OnNonDefaultDevicesForStrategyChangedListener listener) 2334 throws SecurityException { 2335 Objects.requireNonNull(executor); 2336 Objects.requireNonNull(listener); 2337 2338 mNonDefDevListenerMgr.addListener( 2339 executor, listener, "addOnNonDefaultDevicesForStrategyChangedListener", 2340 () -> new StrategyNonDefaultDevicesDispatcherStub()); 2341 } 2342 2343 /** 2344 * @hide 2345 * Removes a previously added listener of changes to the non-default audio device for 2346 * strategies. 2347 * @param listener 2348 */ 2349 @SystemApi 2350 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) removeOnNonDefaultDevicesForStrategyChangedListener( @onNull OnNonDefaultDevicesForStrategyChangedListener listener)2351 public void removeOnNonDefaultDevicesForStrategyChangedListener( 2352 @NonNull OnNonDefaultDevicesForStrategyChangedListener listener) { 2353 Objects.requireNonNull(listener); 2354 mNonDefDevListenerMgr.removeListener( 2355 listener, "removeOnNonDefaultDevicesForStrategyChangedListener"); 2356 } 2357 2358 /** 2359 * Manages the OnPreferredDevicesForStrategyChangedListener listeners and the 2360 * StrategyPreferredDevicesDispatcherStub 2361 */ 2362 private final CallbackUtil.LazyListenerManager<OnPreferredDevicesForStrategyChangedListener> 2363 mPrefDevListenerMgr = new CallbackUtil.LazyListenerManager(); 2364 2365 /** 2366 * Manages the OnNonDefaultDevicesForStrategyChangedListener listeners and the 2367 * StrategyNonDefaultDevicesDispatcherStub 2368 */ 2369 private final CallbackUtil.LazyListenerManager<OnNonDefaultDevicesForStrategyChangedListener> 2370 mNonDefDevListenerMgr = new CallbackUtil.LazyListenerManager(); 2371 2372 private final class StrategyPreferredDevicesDispatcherStub 2373 extends IStrategyPreferredDevicesDispatcher.Stub 2374 implements CallbackUtil.DispatcherStub { 2375 2376 @Override dispatchPrefDevicesChanged(int strategyId, @NonNull List<AudioDeviceAttributes> devices)2377 public void dispatchPrefDevicesChanged(int strategyId, 2378 @NonNull List<AudioDeviceAttributes> devices) { 2379 final AudioProductStrategy strategy = 2380 AudioProductStrategy.getAudioProductStrategyWithId(strategyId); 2381 2382 mPrefDevListenerMgr.callListeners( 2383 (listener) -> listener.onPreferredDevicesForStrategyChanged(strategy, devices)); 2384 } 2385 2386 @Override register(boolean register)2387 public void register(boolean register) { 2388 try { 2389 if (register) { 2390 getService().registerStrategyPreferredDevicesDispatcher(this); 2391 } else { 2392 getService().unregisterStrategyPreferredDevicesDispatcher(this); 2393 } 2394 } catch (RemoteException e) { 2395 e.rethrowFromSystemServer(); 2396 } 2397 } 2398 } 2399 2400 private final class StrategyNonDefaultDevicesDispatcherStub 2401 extends IStrategyNonDefaultDevicesDispatcher.Stub 2402 implements CallbackUtil.DispatcherStub { 2403 2404 @Override dispatchNonDefDevicesChanged(int strategyId, @NonNull List<AudioDeviceAttributes> devices)2405 public void dispatchNonDefDevicesChanged(int strategyId, 2406 @NonNull List<AudioDeviceAttributes> devices) { 2407 final AudioProductStrategy strategy = 2408 AudioProductStrategy.getAudioProductStrategyWithId(strategyId); 2409 2410 mNonDefDevListenerMgr.callListeners( 2411 (listener) -> listener.onNonDefaultDevicesForStrategyChanged( 2412 strategy, devices)); 2413 } 2414 2415 @Override register(boolean register)2416 public void register(boolean register) { 2417 try { 2418 if (register) { 2419 getService().registerStrategyNonDefaultDevicesDispatcher(this); 2420 } else { 2421 getService().unregisterStrategyNonDefaultDevicesDispatcher(this); 2422 } 2423 } catch (RemoteException e) { 2424 e.rethrowFromSystemServer(); 2425 } 2426 } 2427 } 2428 2429 //==================================================================== 2430 // Audio Capture Preset routing 2431 2432 /** 2433 * @hide 2434 * Set the preferred device for a given capture preset, i.e. the audio routing to be used by 2435 * this capture preset. Note that the device may not be available at the time the preferred 2436 * device is set, but it will be used once made available. 2437 * <p>Use {@link #clearPreferredDevicesForCapturePreset(int)} to cancel setting this preference 2438 * for this capture preset.</p> 2439 * @param capturePreset the audio capture preset whose routing will be affected 2440 * @param device the audio device to route to when available 2441 * @return true if the operation was successful, false otherwise 2442 */ 2443 @SystemApi 2444 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) setPreferredDeviceForCapturePreset(@ediaRecorder.SystemSource int capturePreset, @NonNull AudioDeviceAttributes device)2445 public boolean setPreferredDeviceForCapturePreset(@MediaRecorder.SystemSource int capturePreset, 2446 @NonNull AudioDeviceAttributes device) { 2447 return setPreferredDevicesForCapturePreset(capturePreset, Arrays.asList(device)); 2448 } 2449 2450 /** 2451 * @hide 2452 * Remove all the preferred audio devices previously set 2453 * @param capturePreset the audio capture preset whose routing will be affected 2454 * @return true if the operation was successful, false otherwise (invalid capture preset, or no 2455 * device set for example) 2456 */ 2457 @SystemApi 2458 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) clearPreferredDevicesForCapturePreset( @ediaRecorder.SystemSource int capturePreset)2459 public boolean clearPreferredDevicesForCapturePreset( 2460 @MediaRecorder.SystemSource int capturePreset) { 2461 if (!MediaRecorder.isValidAudioSource(capturePreset)) { 2462 return false; 2463 } 2464 try { 2465 final int status = getService().clearPreferredDevicesForCapturePreset(capturePreset); 2466 return status == AudioSystem.SUCCESS; 2467 } catch (RemoteException e) { 2468 throw e.rethrowFromSystemServer(); 2469 } 2470 } 2471 2472 /** 2473 * @hide 2474 * Return the preferred devices for an audio capture preset, previously set with 2475 * {@link #setPreferredDeviceForCapturePreset(int, AudioDeviceAttributes)} 2476 * @param capturePreset the capture preset to query 2477 * @return a list that contains preferred devices for that capture preset. 2478 */ 2479 @NonNull 2480 @SystemApi 2481 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) getPreferredDevicesForCapturePreset( @ediaRecorder.SystemSource int capturePreset)2482 public List<AudioDeviceAttributes> getPreferredDevicesForCapturePreset( 2483 @MediaRecorder.SystemSource int capturePreset) { 2484 if (!MediaRecorder.isValidAudioSource(capturePreset)) { 2485 return new ArrayList<AudioDeviceAttributes>(); 2486 } 2487 try { 2488 return getService().getPreferredDevicesForCapturePreset(capturePreset); 2489 } catch (RemoteException e) { 2490 throw e.rethrowFromSystemServer(); 2491 } 2492 } 2493 setPreferredDevicesForCapturePreset( @ediaRecorder.SystemSource int capturePreset, @NonNull List<AudioDeviceAttributes> devices)2494 private boolean setPreferredDevicesForCapturePreset( 2495 @MediaRecorder.SystemSource int capturePreset, 2496 @NonNull List<AudioDeviceAttributes> devices) { 2497 Objects.requireNonNull(devices); 2498 if (!MediaRecorder.isValidAudioSource(capturePreset)) { 2499 return false; 2500 } 2501 if (devices.size() != 1) { 2502 throw new IllegalArgumentException( 2503 "Only support setting one preferred devices for capture preset"); 2504 } 2505 for (AudioDeviceAttributes device : devices) { 2506 Objects.requireNonNull(device); 2507 } 2508 try { 2509 final int status = 2510 getService().setPreferredDevicesForCapturePreset(capturePreset, devices); 2511 return status == AudioSystem.SUCCESS; 2512 } catch (RemoteException e) { 2513 throw e.rethrowFromSystemServer(); 2514 } 2515 } 2516 2517 /** 2518 * @hide 2519 * Interface to be notified of changes in the preferred audio devices set for a given capture 2520 * preset. 2521 * <p>Note that this listener will only be invoked whenever 2522 * {@link #setPreferredDeviceForCapturePreset(int, AudioDeviceAttributes)} or 2523 * {@link #clearPreferredDevicesForCapturePreset(int)} causes a change in 2524 * preferred device. It will not be invoked directly after registration with 2525 * {@link #addOnPreferredDevicesForCapturePresetChangedListener( 2526 * Executor, OnPreferredDevicesForCapturePresetChangedListener)} 2527 * to indicate which strategies had preferred devices at the time of registration.</p> 2528 * @see #setPreferredDeviceForCapturePreset(int, AudioDeviceAttributes) 2529 * @see #clearPreferredDevicesForCapturePreset(int) 2530 * @see #getPreferredDevicesForCapturePreset(int) 2531 */ 2532 @SystemApi 2533 public interface OnPreferredDevicesForCapturePresetChangedListener { 2534 /** 2535 * Called on the listener to indicate that the preferred audio devices for the given 2536 * capture preset has changed. 2537 * @param capturePreset the capture preset whose preferred device changed 2538 * @param devices a list of newly set preferred audio devices 2539 */ onPreferredDevicesForCapturePresetChanged( @ediaRecorder.SystemSource int capturePreset, @NonNull List<AudioDeviceAttributes> devices)2540 void onPreferredDevicesForCapturePresetChanged( 2541 @MediaRecorder.SystemSource int capturePreset, 2542 @NonNull List<AudioDeviceAttributes> devices); 2543 } 2544 2545 /** 2546 * @hide 2547 * Adds a listener for being notified of changes to the capture-preset-preferred audio device. 2548 * @param executor 2549 * @param listener 2550 * @throws SecurityException if the caller doesn't hold the required permission 2551 */ 2552 @SystemApi 2553 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) addOnPreferredDevicesForCapturePresetChangedListener( @onNull @allbackExecutor Executor executor, @NonNull OnPreferredDevicesForCapturePresetChangedListener listener)2554 public void addOnPreferredDevicesForCapturePresetChangedListener( 2555 @NonNull @CallbackExecutor Executor executor, 2556 @NonNull OnPreferredDevicesForCapturePresetChangedListener listener) 2557 throws SecurityException { 2558 Objects.requireNonNull(executor); 2559 Objects.requireNonNull(listener); 2560 int status = addOnDevRoleForCapturePresetChangedListener( 2561 executor, listener, AudioSystem.DEVICE_ROLE_PREFERRED); 2562 if (status == AudioSystem.ERROR) { 2563 // This must not happen 2564 throw new RuntimeException("Unknown error happened"); 2565 } 2566 if (status == AudioSystem.BAD_VALUE) { 2567 throw new IllegalArgumentException( 2568 "attempt to call addOnPreferredDevicesForCapturePresetChangedListener() " 2569 + "on a previously registered listener"); 2570 } 2571 } 2572 2573 /** 2574 * @hide 2575 * Removes a previously added listener of changes to the capture-preset-preferred audio device. 2576 * @param listener 2577 */ 2578 @SystemApi 2579 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) removeOnPreferredDevicesForCapturePresetChangedListener( @onNull OnPreferredDevicesForCapturePresetChangedListener listener)2580 public void removeOnPreferredDevicesForCapturePresetChangedListener( 2581 @NonNull OnPreferredDevicesForCapturePresetChangedListener listener) { 2582 Objects.requireNonNull(listener); 2583 int status = removeOnDevRoleForCapturePresetChangedListener( 2584 listener, AudioSystem.DEVICE_ROLE_PREFERRED); 2585 if (status == AudioSystem.ERROR) { 2586 // This must not happen 2587 throw new RuntimeException("Unknown error happened"); 2588 } 2589 if (status == AudioSystem.BAD_VALUE) { 2590 throw new IllegalArgumentException( 2591 "attempt to call removeOnPreferredDevicesForCapturePresetChangedListener() " 2592 + "on an unregistered listener"); 2593 } 2594 } 2595 addOnDevRoleForCapturePresetChangedListener( @onNull @allbackExecutor Executor executor, @NonNull T listener, int deviceRole)2596 private <T> int addOnDevRoleForCapturePresetChangedListener( 2597 @NonNull @CallbackExecutor Executor executor, 2598 @NonNull T listener, int deviceRole) { 2599 Objects.requireNonNull(executor); 2600 Objects.requireNonNull(listener); 2601 DevRoleListeners<T> devRoleListeners = 2602 (DevRoleListeners<T>) mDevRoleForCapturePresetListeners.get(deviceRole); 2603 if (devRoleListeners == null) { 2604 return AudioSystem.ERROR; 2605 } 2606 synchronized (devRoleListeners.mDevRoleListenersLock) { 2607 if (devRoleListeners.hasDevRoleListener(listener)) { 2608 return AudioSystem.BAD_VALUE; 2609 } 2610 // lazy initialization of the list of device role listener 2611 if (devRoleListeners.mListenerInfos == null) { 2612 devRoleListeners.mListenerInfos = new ArrayList<>(); 2613 } 2614 final int oldCbCount = devRoleListeners.mListenerInfos.size(); 2615 devRoleListeners.mListenerInfos.add(new DevRoleListenerInfo<T>(executor, listener)); 2616 if (oldCbCount == 0 && devRoleListeners.mListenerInfos.size() > 0) { 2617 // register binder for callbacks 2618 synchronized (mDevRoleForCapturePresetListenersLock) { 2619 int deviceRoleListenerStatus = mDeviceRoleListenersStatus; 2620 mDeviceRoleListenersStatus |= (1 << deviceRole); 2621 if (deviceRoleListenerStatus != 0) { 2622 // There are already device role changed listeners active. 2623 return AudioSystem.SUCCESS; 2624 } 2625 if (mDevicesRoleForCapturePresetDispatcherStub == null) { 2626 mDevicesRoleForCapturePresetDispatcherStub = 2627 new CapturePresetDevicesRoleDispatcherStub(); 2628 } 2629 try { 2630 getService().registerCapturePresetDevicesRoleDispatcher( 2631 mDevicesRoleForCapturePresetDispatcherStub); 2632 } catch (RemoteException e) { 2633 throw e.rethrowFromSystemServer(); 2634 } 2635 } 2636 } 2637 } 2638 return AudioSystem.SUCCESS; 2639 } 2640 removeOnDevRoleForCapturePresetChangedListener( @onNull T listener, int deviceRole)2641 private <T> int removeOnDevRoleForCapturePresetChangedListener( 2642 @NonNull T listener, int deviceRole) { 2643 Objects.requireNonNull(listener); 2644 DevRoleListeners<T> devRoleListeners = 2645 (DevRoleListeners<T>) mDevRoleForCapturePresetListeners.get(deviceRole); 2646 if (devRoleListeners == null) { 2647 return AudioSystem.ERROR; 2648 } 2649 synchronized (devRoleListeners.mDevRoleListenersLock) { 2650 if (!devRoleListeners.removeDevRoleListener(listener)) { 2651 return AudioSystem.BAD_VALUE; 2652 } 2653 if (devRoleListeners.mListenerInfos.size() == 0) { 2654 // unregister binder for callbacks 2655 synchronized (mDevRoleForCapturePresetListenersLock) { 2656 mDeviceRoleListenersStatus ^= (1 << deviceRole); 2657 if (mDeviceRoleListenersStatus != 0) { 2658 // There are some other device role changed listeners active. 2659 return AudioSystem.SUCCESS; 2660 } 2661 try { 2662 getService().unregisterCapturePresetDevicesRoleDispatcher( 2663 mDevicesRoleForCapturePresetDispatcherStub); 2664 } catch (RemoteException e) { 2665 throw e.rethrowFromSystemServer(); 2666 } 2667 } 2668 } 2669 } 2670 return AudioSystem.SUCCESS; 2671 } 2672 2673 private final Map<Integer, Object> mDevRoleForCapturePresetListeners = Map.of( 2674 AudioSystem.DEVICE_ROLE_PREFERRED, 2675 new DevRoleListeners<OnPreferredDevicesForCapturePresetChangedListener>()); 2676 2677 private class DevRoleListenerInfo<T> { 2678 final @NonNull Executor mExecutor; 2679 final @NonNull T mListener; DevRoleListenerInfo(Executor executor, T listener)2680 DevRoleListenerInfo(Executor executor, T listener) { 2681 mExecutor = executor; 2682 mListener = listener; 2683 } 2684 } 2685 2686 private class DevRoleListeners<T> { 2687 private final Object mDevRoleListenersLock = new Object(); 2688 @GuardedBy("mDevRoleListenersLock") 2689 private @Nullable ArrayList<DevRoleListenerInfo<T>> mListenerInfos; 2690 2691 @GuardedBy("mDevRoleListenersLock") getDevRoleListenerInfo(T listener)2692 private @Nullable DevRoleListenerInfo<T> getDevRoleListenerInfo(T listener) { 2693 if (mListenerInfos == null) { 2694 return null; 2695 } 2696 for (DevRoleListenerInfo<T> listenerInfo : mListenerInfos) { 2697 if (listenerInfo.mListener == listener) { 2698 return listenerInfo; 2699 } 2700 } 2701 return null; 2702 } 2703 2704 @GuardedBy("mDevRoleListenersLock") hasDevRoleListener(T listener)2705 private boolean hasDevRoleListener(T listener) { 2706 return getDevRoleListenerInfo(listener) != null; 2707 } 2708 2709 @GuardedBy("mDevRoleListenersLock") removeDevRoleListener(T listener)2710 private boolean removeDevRoleListener(T listener) { 2711 final DevRoleListenerInfo<T> infoToRemove = getDevRoleListenerInfo(listener); 2712 if (infoToRemove != null) { 2713 mListenerInfos.remove(infoToRemove); 2714 return true; 2715 } 2716 return false; 2717 } 2718 } 2719 2720 private final Object mDevRoleForCapturePresetListenersLock = new Object(); 2721 /** 2722 * Record if there is a listener added for device role change. If there is a listener added for 2723 * a specified device role change, the bit at position `1 << device_role` is set. 2724 */ 2725 @GuardedBy("mDevRoleForCapturePresetListenersLock") 2726 private int mDeviceRoleListenersStatus = 0; 2727 @GuardedBy("mDevRoleForCapturePresetListenersLock") 2728 private CapturePresetDevicesRoleDispatcherStub mDevicesRoleForCapturePresetDispatcherStub; 2729 2730 private final class CapturePresetDevicesRoleDispatcherStub 2731 extends ICapturePresetDevicesRoleDispatcher.Stub { 2732 2733 @Override dispatchDevicesRoleChanged( int capturePreset, int role, List<AudioDeviceAttributes> devices)2734 public void dispatchDevicesRoleChanged( 2735 int capturePreset, int role, List<AudioDeviceAttributes> devices) { 2736 final Object listenersObj = mDevRoleForCapturePresetListeners.get(role); 2737 if (listenersObj == null) { 2738 return; 2739 } 2740 switch (role) { 2741 case AudioSystem.DEVICE_ROLE_PREFERRED: { 2742 final DevRoleListeners<OnPreferredDevicesForCapturePresetChangedListener> 2743 listeners = 2744 (DevRoleListeners<OnPreferredDevicesForCapturePresetChangedListener>) 2745 listenersObj; 2746 final ArrayList<DevRoleListenerInfo< 2747 OnPreferredDevicesForCapturePresetChangedListener>> prefDevListeners; 2748 synchronized (listeners.mDevRoleListenersLock) { 2749 if (listeners.mListenerInfos.isEmpty()) { 2750 return; 2751 } 2752 prefDevListeners = (ArrayList<DevRoleListenerInfo< 2753 OnPreferredDevicesForCapturePresetChangedListener>>) 2754 listeners.mListenerInfos.clone(); 2755 } 2756 final long ident = Binder.clearCallingIdentity(); 2757 try { 2758 for (DevRoleListenerInfo< 2759 OnPreferredDevicesForCapturePresetChangedListener> info : 2760 prefDevListeners) { 2761 info.mExecutor.execute(() -> 2762 info.mListener.onPreferredDevicesForCapturePresetChanged( 2763 capturePreset, devices)); 2764 } 2765 } finally { 2766 Binder.restoreCallingIdentity(ident); 2767 } 2768 } break; 2769 default: 2770 break; 2771 } 2772 } 2773 } 2774 2775 //==================================================================== 2776 // Direct playback query 2777 2778 /** Return value for {@link #getDirectPlaybackSupport(AudioFormat, AudioAttributes)}: 2779 direct playback not supported. */ 2780 public static final int DIRECT_PLAYBACK_NOT_SUPPORTED = AudioSystem.DIRECT_NOT_SUPPORTED; 2781 /** Return value for {@link #getDirectPlaybackSupport(AudioFormat, AudioAttributes)}: 2782 direct offload playback supported. Compressed offload is a variant of direct playback. 2783 It is the feature that allows audio processing tasks to be done on the Android device but 2784 not on the application processor, instead, it is handled by dedicated hardware such as audio 2785 DSPs. That will allow the application processor to be idle as much as possible, which is 2786 good for power saving. Compressed offload playback supports 2787 {@link AudioTrack.StreamEventCallback} for event notifications. */ 2788 public static final int DIRECT_PLAYBACK_OFFLOAD_SUPPORTED = 2789 AudioSystem.DIRECT_OFFLOAD_SUPPORTED; 2790 /** Return value for {@link #getDirectPlaybackSupport(AudioFormat, AudioAttributes)}: 2791 direct offload playback supported with gapless transitions. Compressed offload is a variant 2792 of direct playback. It is the feature that allows audio processing tasks to be done on the 2793 Android device but not on the application processor, instead, it is handled by dedicated 2794 hardware such as audio DSPs. That will allow the application processor to be idle as much as 2795 possible, which is good for power saving. Compressed offload playback supports 2796 {@link AudioTrack.StreamEventCallback} for event notifications. Gapless transitions 2797 indicates the ability to play consecutive audio tracks without an audio silence in 2798 between. */ 2799 public static final int DIRECT_PLAYBACK_OFFLOAD_GAPLESS_SUPPORTED = 2800 AudioSystem.DIRECT_OFFLOAD_GAPLESS_SUPPORTED; 2801 /** Return value for {@link #getDirectPlaybackSupport(AudioFormat, AudioAttributes)}: 2802 direct playback supported. This value covers direct playback that is bitstream pass-through 2803 such as compressed pass-through. */ 2804 public static final int DIRECT_PLAYBACK_BITSTREAM_SUPPORTED = 2805 AudioSystem.DIRECT_BITSTREAM_SUPPORTED; 2806 2807 /** @hide */ 2808 @IntDef(flag = true, prefix = "DIRECT_PLAYBACK_", value = { 2809 DIRECT_PLAYBACK_NOT_SUPPORTED, 2810 DIRECT_PLAYBACK_OFFLOAD_SUPPORTED, 2811 DIRECT_PLAYBACK_OFFLOAD_GAPLESS_SUPPORTED, 2812 DIRECT_PLAYBACK_BITSTREAM_SUPPORTED} 2813 ) 2814 @Retention(RetentionPolicy.SOURCE) 2815 public @interface AudioDirectPlaybackMode {} 2816 2817 /** 2818 * Returns a bitfield representing the different forms of direct playback currently available 2819 * for a given audio format. 2820 * <p>Direct playback means that the audio stream is not altered by the framework. The audio 2821 * stream will not be resampled, volume scaled, downmixed or mixed with other content by 2822 * the framework. But it may be wrapped in a higher level protocol such as IEC61937 for 2823 * passthrough. 2824 * <p>Checking for direct support can help the app select the representation of audio content 2825 * that most closely matches the capabilities of the device and peripherals (e.g. A/V receiver) 2826 * connected to it. Note that the provided stream can still be re-encoded or mixed with other 2827 * streams, if needed. 2828 * @param format the audio format (codec, sample rate, channels) being checked. 2829 * @param attributes the {@link AudioAttributes} to be used for playback 2830 * @return the direct playback mode available with given format and attributes. The returned 2831 * value will be {@link #DIRECT_PLAYBACK_NOT_SUPPORTED} or a combination of 2832 * {@link #DIRECT_PLAYBACK_OFFLOAD_SUPPORTED}, 2833 * {@link #DIRECT_PLAYBACK_OFFLOAD_GAPLESS_SUPPORTED} and 2834 * {@link #DIRECT_PLAYBACK_BITSTREAM_SUPPORTED}. Note that if 2835 * {@link #DIRECT_PLAYBACK_OFFLOAD_GAPLESS_SUPPORTED} is present in the returned value, 2836 * then {@link #DIRECT_PLAYBACK_OFFLOAD_SUPPORTED} will be too. 2837 */ 2838 @AudioDirectPlaybackMode getDirectPlaybackSupport(@onNull AudioFormat format, @NonNull AudioAttributes attributes)2839 public static int getDirectPlaybackSupport(@NonNull AudioFormat format, 2840 @NonNull AudioAttributes attributes) { 2841 Objects.requireNonNull(format); 2842 Objects.requireNonNull(attributes); 2843 return AudioSystem.getDirectPlaybackSupport(format, attributes); 2844 } 2845 2846 //==================================================================== 2847 // Offload query 2848 /** 2849 * Returns whether offloaded playback of an audio format is supported on the device. 2850 * <p>Offloaded playback is the feature where the decoding and playback of an audio stream 2851 * is not competing with other software resources. In general, it is supported by dedicated 2852 * hardware, such as audio DSPs. 2853 * <p>Note that this query only provides information about the support of an audio format, 2854 * it does not indicate whether the resources necessary for the offloaded playback are 2855 * available at that instant. 2856 * @param format the audio format (codec, sample rate, channels) being checked. 2857 * @param attributes the {@link AudioAttributes} to be used for playback 2858 * @return true if the given audio format can be offloaded. 2859 */ isOffloadedPlaybackSupported(@onNull AudioFormat format, @NonNull AudioAttributes attributes)2860 public static boolean isOffloadedPlaybackSupported(@NonNull AudioFormat format, 2861 @NonNull AudioAttributes attributes) { 2862 if (format == null) { 2863 throw new NullPointerException("Illegal null AudioFormat"); 2864 } 2865 if (attributes == null) { 2866 throw new NullPointerException("Illegal null AudioAttributes"); 2867 } 2868 return AudioSystem.getOffloadSupport(format, attributes) != PLAYBACK_OFFLOAD_NOT_SUPPORTED; 2869 } 2870 2871 /** Return value for {@link #getPlaybackOffloadSupport(AudioFormat, AudioAttributes)}: 2872 offload playback not supported */ 2873 public static final int PLAYBACK_OFFLOAD_NOT_SUPPORTED = AudioSystem.OFFLOAD_NOT_SUPPORTED; 2874 /** Return value for {@link #getPlaybackOffloadSupport(AudioFormat, AudioAttributes)}: 2875 offload playback supported */ 2876 public static final int PLAYBACK_OFFLOAD_SUPPORTED = AudioSystem.OFFLOAD_SUPPORTED; 2877 /** Return value for {@link #getPlaybackOffloadSupport(AudioFormat, AudioAttributes)}: 2878 offload playback supported with gapless transitions */ 2879 public static final int PLAYBACK_OFFLOAD_GAPLESS_SUPPORTED = 2880 AudioSystem.OFFLOAD_GAPLESS_SUPPORTED; 2881 2882 /** @hide */ 2883 @IntDef(flag = false, prefix = "PLAYBACK_OFFLOAD_", value = { 2884 PLAYBACK_OFFLOAD_NOT_SUPPORTED, 2885 PLAYBACK_OFFLOAD_SUPPORTED, 2886 PLAYBACK_OFFLOAD_GAPLESS_SUPPORTED } 2887 ) 2888 @Retention(RetentionPolicy.SOURCE) 2889 public @interface AudioOffloadMode {} 2890 2891 /** 2892 * Returns whether offloaded playback of an audio format is supported on the device or not and 2893 * when supported whether gapless transitions are possible or not. 2894 * <p>Offloaded playback is the feature where the decoding and playback of an audio stream 2895 * is not competing with other software resources. In general, it is supported by dedicated 2896 * hardware, such as audio DSPs. 2897 * <p>Note that this query only provides information about the support of an audio format, 2898 * it does not indicate whether the resources necessary for the offloaded playback are 2899 * available at that instant. 2900 * @param format the audio format (codec, sample rate, channels) being checked. 2901 * @param attributes the {@link AudioAttributes} to be used for playback 2902 * @return {@link #PLAYBACK_OFFLOAD_NOT_SUPPORTED} if offload playback if not supported, 2903 * {@link #PLAYBACK_OFFLOAD_SUPPORTED} if offload playback is supported or 2904 * {@link #PLAYBACK_OFFLOAD_GAPLESS_SUPPORTED} if gapless transitions are 2905 * also supported. 2906 * @deprecated Use {@link #getDirectPlaybackSupport(AudioFormat, AudioAttributes)} instead 2907 */ 2908 @Deprecated 2909 @AudioOffloadMode getPlaybackOffloadSupport(@onNull AudioFormat format, @NonNull AudioAttributes attributes)2910 public static int getPlaybackOffloadSupport(@NonNull AudioFormat format, 2911 @NonNull AudioAttributes attributes) { 2912 if (format == null) { 2913 throw new NullPointerException("Illegal null AudioFormat"); 2914 } 2915 if (attributes == null) { 2916 throw new NullPointerException("Illegal null AudioAttributes"); 2917 } 2918 return AudioSystem.getOffloadSupport(format, attributes); 2919 } 2920 2921 //==================================================================== 2922 // Immersive audio 2923 2924 /** 2925 * Return a handle to the optional platform's {@link Spatializer} 2926 * @return the {@code Spatializer} instance. 2927 * @see Spatializer#getImmersiveAudioLevel() to check for the level of support of the effect 2928 * on the platform 2929 */ getSpatializer()2930 public @NonNull Spatializer getSpatializer() { 2931 return new Spatializer(this); 2932 } 2933 2934 //==================================================================== 2935 // Bluetooth SCO control 2936 /** 2937 * Sticky broadcast intent action indicating that the Bluetooth SCO audio 2938 * connection state has changed. The intent contains on extra {@link #EXTRA_SCO_AUDIO_STATE} 2939 * indicating the new state which is either {@link #SCO_AUDIO_STATE_DISCONNECTED} 2940 * or {@link #SCO_AUDIO_STATE_CONNECTED} 2941 * 2942 * @see #startBluetoothSco() 2943 * @deprecated Use {@link #ACTION_SCO_AUDIO_STATE_UPDATED} instead 2944 */ 2945 @Deprecated 2946 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 2947 public static final String ACTION_SCO_AUDIO_STATE_CHANGED = 2948 "android.media.SCO_AUDIO_STATE_CHANGED"; 2949 2950 /** 2951 * Sticky broadcast intent action indicating that the Bluetooth SCO audio 2952 * connection state has been updated. 2953 * <p>This intent has two extras: 2954 * <ul> 2955 * <li> {@link #EXTRA_SCO_AUDIO_STATE} - The new SCO audio state. </li> 2956 * <li> {@link #EXTRA_SCO_AUDIO_PREVIOUS_STATE}- The previous SCO audio state. </li> 2957 * </ul> 2958 * <p> EXTRA_SCO_AUDIO_STATE or EXTRA_SCO_AUDIO_PREVIOUS_STATE can be any of: 2959 * <ul> 2960 * <li> {@link #SCO_AUDIO_STATE_DISCONNECTED}, </li> 2961 * <li> {@link #SCO_AUDIO_STATE_CONNECTING} or </li> 2962 * <li> {@link #SCO_AUDIO_STATE_CONNECTED}, </li> 2963 * </ul> 2964 * @see #startBluetoothSco() 2965 */ 2966 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 2967 public static final String ACTION_SCO_AUDIO_STATE_UPDATED = 2968 "android.media.ACTION_SCO_AUDIO_STATE_UPDATED"; 2969 2970 /** 2971 * Extra for intent {@link #ACTION_SCO_AUDIO_STATE_CHANGED} or 2972 * {@link #ACTION_SCO_AUDIO_STATE_UPDATED} containing the new bluetooth SCO connection state. 2973 */ 2974 public static final String EXTRA_SCO_AUDIO_STATE = 2975 "android.media.extra.SCO_AUDIO_STATE"; 2976 2977 /** 2978 * Extra for intent {@link #ACTION_SCO_AUDIO_STATE_UPDATED} containing the previous 2979 * bluetooth SCO connection state. 2980 */ 2981 public static final String EXTRA_SCO_AUDIO_PREVIOUS_STATE = 2982 "android.media.extra.SCO_AUDIO_PREVIOUS_STATE"; 2983 2984 /** 2985 * Value for extra EXTRA_SCO_AUDIO_STATE or EXTRA_SCO_AUDIO_PREVIOUS_STATE 2986 * indicating that the SCO audio channel is not established 2987 */ 2988 public static final int SCO_AUDIO_STATE_DISCONNECTED = 0; 2989 /** 2990 * Value for extra {@link #EXTRA_SCO_AUDIO_STATE} or {@link #EXTRA_SCO_AUDIO_PREVIOUS_STATE} 2991 * indicating that the SCO audio channel is established 2992 */ 2993 public static final int SCO_AUDIO_STATE_CONNECTED = 1; 2994 /** 2995 * Value for extra EXTRA_SCO_AUDIO_STATE or EXTRA_SCO_AUDIO_PREVIOUS_STATE 2996 * indicating that the SCO audio channel is being established 2997 */ 2998 public static final int SCO_AUDIO_STATE_CONNECTING = 2; 2999 /** 3000 * Value for extra EXTRA_SCO_AUDIO_STATE indicating that 3001 * there was an error trying to obtain the state 3002 */ 3003 public static final int SCO_AUDIO_STATE_ERROR = -1; 3004 3005 3006 /** 3007 * Indicates if current platform supports use of SCO for off call use cases. 3008 * Application wanted to use bluetooth SCO audio when the phone is not in call 3009 * must first call this method to make sure that the platform supports this 3010 * feature. 3011 * @return true if bluetooth SCO can be used for audio when not in call 3012 * false otherwise 3013 * @see #startBluetoothSco() 3014 */ isBluetoothScoAvailableOffCall()3015 public boolean isBluetoothScoAvailableOffCall() { 3016 return getContext().getResources().getBoolean( 3017 com.android.internal.R.bool.config_bluetooth_sco_off_call); 3018 } 3019 3020 /** 3021 * Start bluetooth SCO audio connection. 3022 * <p>Requires Permission: 3023 * {@link Manifest.permission#MODIFY_AUDIO_SETTINGS}. 3024 * <p>This method can be used by applications wanting to send and received audio 3025 * to/from a bluetooth SCO headset while the phone is not in call. 3026 * <p>As the SCO connection establishment can take several seconds, 3027 * applications should not rely on the connection to be available when the method 3028 * returns but instead register to receive the intent {@link #ACTION_SCO_AUDIO_STATE_UPDATED} 3029 * and wait for the state to be {@link #SCO_AUDIO_STATE_CONNECTED}. 3030 * <p>As the ACTION_SCO_AUDIO_STATE_UPDATED intent is sticky, the application can check the SCO 3031 * audio state before calling startBluetoothSco() by reading the intent returned by the receiver 3032 * registration. If the state is already CONNECTED, no state change will be received via the 3033 * intent after calling startBluetoothSco(). It is however useful to call startBluetoothSco() 3034 * so that the connection stays active in case the current initiator stops the connection. 3035 * <p>Unless the connection is already active as described above, the state will always 3036 * transition from DISCONNECTED to CONNECTING and then either to CONNECTED if the connection 3037 * succeeds or back to DISCONNECTED if the connection fails (e.g no headset is connected). 3038 * <p>When finished with the SCO connection or if the establishment fails, the application must 3039 * call {@link #stopBluetoothSco()} to clear the request and turn down the bluetooth connection. 3040 * <p>Even if a SCO connection is established, the following restrictions apply on audio 3041 * output streams so that they can be routed to SCO headset: 3042 * <ul> 3043 * <li> the stream type must be {@link #STREAM_VOICE_CALL} </li> 3044 * <li> the format must be mono </li> 3045 * <li> the sampling must be 16kHz or 8kHz </li> 3046 * </ul> 3047 * <p>The following restrictions apply on input streams: 3048 * <ul> 3049 * <li> the format must be mono </li> 3050 * <li> the sampling must be 8kHz </li> 3051 * </ul> 3052 * <p>Note that the phone application always has the priority on the usage of the SCO 3053 * connection for telephony. If this method is called while the phone is in call 3054 * it will be ignored. Similarly, if a call is received or sent while an application 3055 * is using the SCO connection, the connection will be lost for the application and NOT 3056 * returned automatically when the call ends. 3057 * <p>NOTE: up to and including API version 3058 * {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}, this method initiates a virtual 3059 * voice call to the bluetooth headset. 3060 * After API version {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2} only a raw SCO audio 3061 * connection is established. 3062 * @see #stopBluetoothSco() 3063 * @see #ACTION_SCO_AUDIO_STATE_UPDATED 3064 * @deprecated Use {@link AudioManager#setCommunicationDevice(AudioDeviceInfo)} instead. 3065 */ startBluetoothSco()3066 @Deprecated public void startBluetoothSco() { 3067 final IAudioService service = getService(); 3068 try { 3069 service.startBluetoothSco(mICallBack, 3070 getContext().getApplicationInfo().targetSdkVersion); 3071 } catch (RemoteException e) { 3072 throw e.rethrowFromSystemServer(); 3073 } 3074 } 3075 3076 /** 3077 * @hide 3078 * Start bluetooth SCO audio connection in virtual call mode. 3079 * <p>Requires Permission: 3080 * {@link Manifest.permission#MODIFY_AUDIO_SETTINGS}. 3081 * <p>Similar to {@link #startBluetoothSco()} with explicit selection of virtual call mode. 3082 * Telephony and communication applications (VoIP, Video Chat) should preferably select 3083 * virtual call mode. 3084 * Applications using voice input for search or commands should first try raw audio connection 3085 * with {@link #startBluetoothSco()} and fall back to startBluetoothScoVirtualCall() in case of 3086 * failure. 3087 * @see #startBluetoothSco() 3088 * @see #stopBluetoothSco() 3089 * @see #ACTION_SCO_AUDIO_STATE_UPDATED 3090 */ 3091 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) startBluetoothScoVirtualCall()3092 public void startBluetoothScoVirtualCall() { 3093 final IAudioService service = getService(); 3094 try { 3095 service.startBluetoothScoVirtualCall(mICallBack); 3096 } catch (RemoteException e) { 3097 throw e.rethrowFromSystemServer(); 3098 } 3099 } 3100 3101 /** 3102 * Stop bluetooth SCO audio connection. 3103 * <p>Requires Permission: 3104 * {@link Manifest.permission#MODIFY_AUDIO_SETTINGS}. 3105 * <p>This method must be called by applications having requested the use of 3106 * bluetooth SCO audio with {@link #startBluetoothSco()} when finished with the SCO 3107 * connection or if connection fails. 3108 * @see #startBluetoothSco() 3109 * @deprecated Use {@link AudioManager#clearCommunicationDevice()} instead. 3110 */ 3111 // Also used for connections started with {@link #startBluetoothScoVirtualCall()} stopBluetoothSco()3112 @Deprecated public void stopBluetoothSco() { 3113 final IAudioService service = getService(); 3114 try { 3115 service.stopBluetoothSco(mICallBack); 3116 } catch (RemoteException e) { 3117 throw e.rethrowFromSystemServer(); 3118 } 3119 } 3120 3121 /** 3122 * Request use of Bluetooth SCO headset for communications. 3123 * <p> 3124 * This method should only be used by applications that replace the platform-wide 3125 * management of audio settings or the main telephony application. 3126 * 3127 * @param on set <var>true</var> to use bluetooth SCO for communications; 3128 * <var>false</var> to not use bluetooth SCO for communications 3129 */ setBluetoothScoOn(boolean on)3130 public void setBluetoothScoOn(boolean on){ 3131 final IAudioService service = getService(); 3132 try { 3133 service.setBluetoothScoOn(on); 3134 } catch (RemoteException e) { 3135 throw e.rethrowFromSystemServer(); 3136 } 3137 } 3138 3139 /** 3140 * Checks whether communications use Bluetooth SCO. 3141 * 3142 * @return true if SCO is used for communications; 3143 * false if otherwise 3144 * @deprecated Use {@link AudioManager#getCommunicationDevice()} instead. 3145 */ isBluetoothScoOn()3146 @Deprecated public boolean isBluetoothScoOn() { 3147 final IAudioService service = getService(); 3148 try { 3149 return service.isBluetoothScoOn(); 3150 } catch (RemoteException e) { 3151 throw e.rethrowFromSystemServer(); 3152 } 3153 } 3154 3155 /** 3156 * @deprecated Use {@link MediaRouter#selectRoute} instead. 3157 */ setBluetoothA2dpOn(boolean on)3158 @Deprecated public void setBluetoothA2dpOn(boolean on){ 3159 } 3160 3161 /** 3162 * Checks whether a Bluetooth A2DP audio peripheral is connected or not. 3163 * 3164 * @return true if a Bluetooth A2DP peripheral is connected 3165 * false if otherwise 3166 * @deprecated Use {@link AudioManager#getDevices(int)} instead to list available audio devices. 3167 */ isBluetoothA2dpOn()3168 public boolean isBluetoothA2dpOn() { 3169 if (AudioSystem.getDeviceConnectionState(DEVICE_OUT_BLUETOOTH_A2DP,"") 3170 == AudioSystem.DEVICE_STATE_AVAILABLE) { 3171 return true; 3172 } else if (AudioSystem.getDeviceConnectionState(DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES,"") 3173 == AudioSystem.DEVICE_STATE_AVAILABLE) { 3174 return true; 3175 } else if (AudioSystem.getDeviceConnectionState(DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER,"") 3176 == AudioSystem.DEVICE_STATE_AVAILABLE) { 3177 return true; 3178 } 3179 return false; 3180 } 3181 3182 /** 3183 * Sets audio routing to the wired headset on or off. 3184 * 3185 * @param on set <var>true</var> to route audio to/from wired 3186 * headset; <var>false</var> disable wired headset audio 3187 * @deprecated Do not use. 3188 */ setWiredHeadsetOn(boolean on)3189 @Deprecated public void setWiredHeadsetOn(boolean on){ 3190 } 3191 3192 /** 3193 * Checks whether a wired headset is connected or not. 3194 * <p>This is not a valid indication that audio playback is 3195 * actually over the wired headset as audio routing depends on other conditions. 3196 * 3197 * @return true if a wired headset is connected. 3198 * false if otherwise 3199 * @deprecated Use {@link AudioManager#getDevices(int)} instead to list available audio devices. 3200 */ isWiredHeadsetOn()3201 public boolean isWiredHeadsetOn() { 3202 if (AudioSystem.getDeviceConnectionState(DEVICE_OUT_WIRED_HEADSET,"") 3203 == AudioSystem.DEVICE_STATE_UNAVAILABLE && 3204 AudioSystem.getDeviceConnectionState(DEVICE_OUT_WIRED_HEADPHONE,"") 3205 == AudioSystem.DEVICE_STATE_UNAVAILABLE && 3206 AudioSystem.getDeviceConnectionState(DEVICE_OUT_USB_HEADSET, "") 3207 == AudioSystem.DEVICE_STATE_UNAVAILABLE) { 3208 return false; 3209 } else { 3210 return true; 3211 } 3212 } 3213 3214 /** 3215 * Sets the microphone mute on or off. 3216 * <p> 3217 * This method should only be used by applications that replace the platform-wide 3218 * management of audio settings or the main telephony application. 3219 * 3220 * @param on set <var>true</var> to mute the microphone; 3221 * <var>false</var> to turn mute off 3222 */ setMicrophoneMute(boolean on)3223 public void setMicrophoneMute(boolean on) { 3224 final IAudioService service = getService(); 3225 try { 3226 service.setMicrophoneMute(on, getContext().getOpPackageName(), 3227 UserHandle.getCallingUserId(), getContext().getAttributionTag()); 3228 } catch (RemoteException e) { 3229 throw e.rethrowFromSystemServer(); 3230 } 3231 } 3232 3233 /** 3234 * @hide 3235 * Sets the microphone from switch mute on or off. 3236 * <p> 3237 * This method should only be used by InputManager to notify 3238 * Audio Subsystem about Microphone Mute switch state. 3239 * 3240 * @param on set <var>true</var> to mute the microphone; 3241 * <var>false</var> to turn mute off 3242 */ 3243 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) setMicrophoneMuteFromSwitch(boolean on)3244 public void setMicrophoneMuteFromSwitch(boolean on) { 3245 final IAudioService service = getService(); 3246 try { 3247 service.setMicrophoneMuteFromSwitch(on); 3248 } catch (RemoteException e) { 3249 throw e.rethrowFromSystemServer(); 3250 } 3251 } 3252 3253 /** 3254 * Checks whether the microphone mute is on or off. 3255 * 3256 * @return true if microphone is muted, false if it's not 3257 */ isMicrophoneMute()3258 public boolean isMicrophoneMute() { 3259 final IAudioService service = getService(); 3260 try { 3261 return service.isMicrophoneMuted(); 3262 } catch (RemoteException e) { 3263 throw e.rethrowFromSystemServer(); 3264 } 3265 } 3266 3267 /** 3268 * Broadcast Action: microphone muting state changed. 3269 * 3270 * You <em>cannot</em> receive this through components declared 3271 * in manifests, only by explicitly registering for it with 3272 * {@link Context#registerReceiver(BroadcastReceiver, IntentFilter) 3273 * Context.registerReceiver()}. 3274 * 3275 * <p>The intent has no extra values, use {@link #isMicrophoneMute} to check whether the 3276 * microphone is muted. 3277 */ 3278 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 3279 public static final String ACTION_MICROPHONE_MUTE_CHANGED = 3280 "android.media.action.MICROPHONE_MUTE_CHANGED"; 3281 3282 /** 3283 * Broadcast Action: speakerphone state changed. 3284 * 3285 * You <em>cannot</em> receive this through components declared 3286 * in manifests, only by explicitly registering for it with 3287 * {@link Context#registerReceiver(BroadcastReceiver, IntentFilter) 3288 * Context.registerReceiver()}. 3289 * 3290 * <p>The intent has no extra values, use {@link #isSpeakerphoneOn} to check whether the 3291 * speakerphone functionality is enabled or not. 3292 */ 3293 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 3294 public static final String ACTION_SPEAKERPHONE_STATE_CHANGED = 3295 "android.media.action.SPEAKERPHONE_STATE_CHANGED"; 3296 3297 /** 3298 * Sets the audio mode. 3299 * <p> 3300 * The audio mode encompasses audio routing AND the behavior of 3301 * the telephony layer. Therefore this method should only be used by applications that 3302 * replace the platform-wide management of audio settings or the main telephony application. 3303 * In particular, the {@link #MODE_IN_CALL} mode should only be used by the telephony 3304 * application when it places a phone call, as it will cause signals from the radio layer 3305 * to feed the platform mixer. 3306 * 3307 * @param mode the requested audio mode. 3308 * Informs the HAL about the current audio state so that 3309 * it can route the audio appropriately. 3310 */ setMode(@udioMode int mode)3311 public void setMode(@AudioMode int mode) { 3312 final IAudioService service = getService(); 3313 try { 3314 service.setMode(mode, mICallBack, mApplicationContext.getOpPackageName()); 3315 } catch (RemoteException e) { 3316 throw e.rethrowFromSystemServer(); 3317 } 3318 } 3319 3320 /** 3321 * This change id controls use of audio modes for call audio redirection. 3322 * @hide 3323 */ 3324 @ChangeId 3325 @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU) 3326 public static final long CALL_REDIRECTION_AUDIO_MODES = 189472651L; // buganizer id 3327 3328 /** 3329 * Returns the current audio mode. 3330 * 3331 * @return the current audio mode. 3332 */ 3333 @AudioMode getMode()3334 public int getMode() { 3335 final IAudioService service = getService(); 3336 try { 3337 int mode = service.getMode(); 3338 int sdk; 3339 try { 3340 sdk = getContext().getApplicationInfo().targetSdkVersion; 3341 } catch (NullPointerException e) { 3342 // some tests don't have a Context 3343 sdk = Build.VERSION.SDK_INT; 3344 } 3345 if (mode == MODE_CALL_SCREENING && sdk <= Build.VERSION_CODES.Q) { 3346 mode = MODE_IN_CALL; 3347 } else if (mode == MODE_CALL_REDIRECT 3348 && !CompatChanges.isChangeEnabled(CALL_REDIRECTION_AUDIO_MODES)) { 3349 mode = MODE_IN_CALL; 3350 } else if (mode == MODE_COMMUNICATION_REDIRECT 3351 && !CompatChanges.isChangeEnabled(CALL_REDIRECTION_AUDIO_MODES)) { 3352 mode = MODE_IN_COMMUNICATION; 3353 } 3354 return mode; 3355 } catch (RemoteException e) { 3356 throw e.rethrowFromSystemServer(); 3357 } 3358 } 3359 3360 /** 3361 * Interface definition of a callback that is notified when the audio mode changes 3362 */ 3363 public interface OnModeChangedListener { 3364 /** 3365 * Called on the listener to indicate that the audio mode has changed 3366 * 3367 * @param mode The current audio mode 3368 */ onModeChanged(@udioMode int mode)3369 void onModeChanged(@AudioMode int mode); 3370 } 3371 3372 /** 3373 * manages the OnModeChangedListener listeners and the ModeDispatcherStub 3374 */ 3375 private final CallbackUtil.LazyListenerManager<OnModeChangedListener> mModeChangedListenerMgr = 3376 new CallbackUtil.LazyListenerManager(); 3377 3378 3379 final class ModeDispatcherStub extends IAudioModeDispatcher.Stub 3380 implements CallbackUtil.DispatcherStub { 3381 3382 @Override register(boolean register)3383 public void register(boolean register) { 3384 try { 3385 if (register) { 3386 getService().registerModeDispatcher(this); 3387 } else { 3388 getService().unregisterModeDispatcher(this); 3389 } 3390 } catch (RemoteException e) { 3391 e.rethrowFromSystemServer(); 3392 } 3393 } 3394 3395 @Override dispatchAudioModeChanged(int mode)3396 public void dispatchAudioModeChanged(int mode) { 3397 mModeChangedListenerMgr.callListeners((listener) -> listener.onModeChanged(mode)); 3398 } 3399 } 3400 3401 /** 3402 * Adds a listener to be notified of changes to the audio mode. 3403 * See {@link #getMode()} 3404 * @param executor 3405 * @param listener 3406 */ addOnModeChangedListener( @onNull @allbackExecutor Executor executor, @NonNull OnModeChangedListener listener)3407 public void addOnModeChangedListener( 3408 @NonNull @CallbackExecutor Executor executor, 3409 @NonNull OnModeChangedListener listener) { 3410 mModeChangedListenerMgr.addListener(executor, listener, "addOnModeChangedListener", 3411 () -> new ModeDispatcherStub()); 3412 } 3413 3414 /** 3415 * Removes a previously added listener for changes to audio mode. 3416 * See {@link #getMode()} 3417 * @param listener 3418 */ removeOnModeChangedListener(@onNull OnModeChangedListener listener)3419 public void removeOnModeChangedListener(@NonNull OnModeChangedListener listener) { 3420 mModeChangedListenerMgr.removeListener(listener, "removeOnModeChangedListener"); 3421 } 3422 3423 /** 3424 * Indicates if the platform supports a special call screening and call monitoring mode. 3425 * <p> 3426 * When this mode is supported, it is possible to perform call screening and monitoring 3427 * functions while other use cases like music or movie playback are active. 3428 * <p> 3429 * Use {@link #setMode(int)} with mode {@link #MODE_CALL_SCREENING} to place the platform in 3430 * call screening mode. 3431 * <p> 3432 * If call screening mode is not supported, setting mode to 3433 * MODE_CALL_SCREENING will be ignored and will not change current mode reported by 3434 * {@link #getMode()}. 3435 * @return true if call screening mode is supported, false otherwise. 3436 */ isCallScreeningModeSupported()3437 public boolean isCallScreeningModeSupported() { 3438 final IAudioService service = getService(); 3439 try { 3440 return service.isCallScreeningModeSupported(); 3441 } catch (RemoteException e) { 3442 throw e.rethrowFromSystemServer(); 3443 } 3444 } 3445 3446 /* modes for setMode/getMode/setRoute/getRoute */ 3447 /** 3448 * Audio harware modes. 3449 */ 3450 /** 3451 * Invalid audio mode. 3452 */ 3453 public static final int MODE_INVALID = AudioSystem.MODE_INVALID; 3454 /** 3455 * Current audio mode. Used to apply audio routing to current mode. 3456 */ 3457 public static final int MODE_CURRENT = AudioSystem.MODE_CURRENT; 3458 /** 3459 * Normal audio mode: not ringing and no call established. 3460 */ 3461 public static final int MODE_NORMAL = AudioSystem.MODE_NORMAL; 3462 /** 3463 * Ringing audio mode. An incoming is being signaled. 3464 */ 3465 public static final int MODE_RINGTONE = AudioSystem.MODE_RINGTONE; 3466 /** 3467 * In call audio mode. A telephony call is established. 3468 */ 3469 public static final int MODE_IN_CALL = AudioSystem.MODE_IN_CALL; 3470 /** 3471 * In communication audio mode. An audio/video chat or VoIP call is established. 3472 */ 3473 public static final int MODE_IN_COMMUNICATION = AudioSystem.MODE_IN_COMMUNICATION; 3474 /** 3475 * Call screening in progress. Call is connected and audio is accessible to call 3476 * screening applications but other audio use cases are still possible. 3477 */ 3478 public static final int MODE_CALL_SCREENING = AudioSystem.MODE_CALL_SCREENING; 3479 3480 /** 3481 * A telephony call is established and its audio is being redirected to another device. 3482 */ 3483 public static final int MODE_CALL_REDIRECT = AudioSystem.MODE_CALL_REDIRECT; 3484 3485 /** 3486 * An audio/video chat or VoIP call is established and its audio is being redirected to another 3487 * device. 3488 */ 3489 public static final int MODE_COMMUNICATION_REDIRECT = AudioSystem.MODE_COMMUNICATION_REDIRECT; 3490 3491 /** @hide */ 3492 @IntDef(flag = false, prefix = "MODE_", value = { 3493 MODE_NORMAL, 3494 MODE_RINGTONE, 3495 MODE_IN_CALL, 3496 MODE_IN_COMMUNICATION, 3497 MODE_CALL_SCREENING, 3498 MODE_CALL_REDIRECT, 3499 MODE_COMMUNICATION_REDIRECT} 3500 ) 3501 @Retention(RetentionPolicy.SOURCE) 3502 public @interface AudioMode {} 3503 3504 /* Routing bits for setRouting/getRouting API */ 3505 /** 3506 * Routing audio output to earpiece 3507 * @deprecated Do not set audio routing directly, use setSpeakerphoneOn(), 3508 * setBluetoothScoOn() methods instead. 3509 */ 3510 @Deprecated public static final int ROUTE_EARPIECE = AudioSystem.ROUTE_EARPIECE; 3511 /** 3512 * Routing audio output to speaker 3513 * @deprecated Do not set audio routing directly, use setSpeakerphoneOn(), 3514 * setBluetoothScoOn() methods instead. 3515 */ 3516 @Deprecated public static final int ROUTE_SPEAKER = AudioSystem.ROUTE_SPEAKER; 3517 /** 3518 * @deprecated use {@link #ROUTE_BLUETOOTH_SCO} 3519 * @deprecated Do not set audio routing directly, use setSpeakerphoneOn(), 3520 * setBluetoothScoOn() methods instead. 3521 */ 3522 @Deprecated public static final int ROUTE_BLUETOOTH = AudioSystem.ROUTE_BLUETOOTH_SCO; 3523 /** 3524 * Routing audio output to bluetooth SCO 3525 * @deprecated Do not set audio routing directly, use setSpeakerphoneOn(), 3526 * setBluetoothScoOn() methods instead. 3527 */ 3528 @Deprecated public static final int ROUTE_BLUETOOTH_SCO = AudioSystem.ROUTE_BLUETOOTH_SCO; 3529 /** 3530 * Routing audio output to headset 3531 * @deprecated Do not set audio routing directly, use setSpeakerphoneOn(), 3532 * setBluetoothScoOn() methods instead. 3533 */ 3534 @Deprecated public static final int ROUTE_HEADSET = AudioSystem.ROUTE_HEADSET; 3535 /** 3536 * Routing audio output to bluetooth A2DP 3537 * @deprecated Do not set audio routing directly, use setSpeakerphoneOn(), 3538 * setBluetoothScoOn() methods instead. 3539 */ 3540 @Deprecated public static final int ROUTE_BLUETOOTH_A2DP = AudioSystem.ROUTE_BLUETOOTH_A2DP; 3541 /** 3542 * Used for mask parameter of {@link #setRouting(int,int,int)}. 3543 * @deprecated Do not set audio routing directly, use setSpeakerphoneOn(), 3544 * setBluetoothScoOn() methods instead. 3545 */ 3546 @Deprecated public static final int ROUTE_ALL = AudioSystem.ROUTE_ALL; 3547 3548 /** 3549 * Sets the audio routing for a specified mode 3550 * 3551 * @param mode audio mode to change route. E.g., MODE_RINGTONE. 3552 * @param routes bit vector of routes requested, created from one or 3553 * more of ROUTE_xxx types. Set bits indicate that route should be on 3554 * @param mask bit vector of routes to change, created from one or more of 3555 * ROUTE_xxx types. Unset bits indicate the route should be left unchanged 3556 * 3557 * @deprecated Do not set audio routing directly, use setSpeakerphoneOn(), 3558 * setBluetoothScoOn() methods instead. 3559 */ 3560 @Deprecated setRouting(int mode, int routes, int mask)3561 public void setRouting(int mode, int routes, int mask) { 3562 } 3563 3564 /** 3565 * Returns the current audio routing bit vector for a specified mode. 3566 * 3567 * @param mode audio mode to get route (e.g., MODE_RINGTONE) 3568 * @return an audio route bit vector that can be compared with ROUTE_xxx 3569 * bits 3570 * @deprecated Do not query audio routing directly, use isSpeakerphoneOn(), 3571 * isBluetoothScoOn(), isBluetoothA2dpOn() and isWiredHeadsetOn() methods instead. 3572 */ 3573 @Deprecated getRouting(int mode)3574 public int getRouting(int mode) { 3575 return -1; 3576 } 3577 3578 /** 3579 * Checks whether any music is active. 3580 * 3581 * @return true if any music tracks are active. 3582 */ isMusicActive()3583 public boolean isMusicActive() { 3584 final IAudioService service = getService(); 3585 try { 3586 return service.isMusicActive(false /*remotely*/); 3587 } catch (RemoteException e) { 3588 throw e.rethrowFromSystemServer(); 3589 } 3590 } 3591 3592 /** 3593 * @hide 3594 * Checks whether any music or media is actively playing on a remote device (e.g. wireless 3595 * display). Note that BT audio sinks are not considered remote devices. 3596 * @return true if {@link AudioManager#STREAM_MUSIC} is active on a remote device 3597 */ 3598 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) isMusicActiveRemotely()3599 public boolean isMusicActiveRemotely() { 3600 final IAudioService service = getService(); 3601 try { 3602 return service.isMusicActive(true /*remotely*/); 3603 } catch (RemoteException e) { 3604 throw e.rethrowFromSystemServer(); 3605 } 3606 } 3607 3608 /** 3609 * @hide 3610 * Checks whether the current audio focus is exclusive. 3611 * @return true if the top of the audio focus stack requested focus 3612 * with {@link #AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE} 3613 */ isAudioFocusExclusive()3614 public boolean isAudioFocusExclusive() { 3615 final IAudioService service = getService(); 3616 try { 3617 return service.getCurrentAudioFocus() == AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE; 3618 } catch (RemoteException e) { 3619 throw e.rethrowFromSystemServer(); 3620 } 3621 } 3622 3623 /** 3624 * Return a new audio session identifier not associated with any player or effect. 3625 * An audio session identifier is a system wide unique identifier for a set of audio streams 3626 * (one or more mixed together). 3627 * <p>The primary use of the audio session ID is to associate audio effects to audio players, 3628 * such as {@link MediaPlayer} or {@link AudioTrack}: all audio effects sharing the same audio 3629 * session ID will be applied to the mixed audio content of the players that share the same 3630 * audio session. 3631 * <p>This method can for instance be used when creating one of the 3632 * {@link android.media.audiofx.AudioEffect} objects to define the audio session of the effect, 3633 * or to specify a session for a speech synthesis utterance 3634 * in {@link android.speech.tts.TextToSpeech.Engine}. 3635 * @return a new unclaimed and unused audio session identifier, or {@link #ERROR} when the 3636 * system failed to generate a new session, a condition in which audio playback or recording 3637 * will subsequently fail as well. 3638 */ generateAudioSessionId()3639 public int generateAudioSessionId() { 3640 int session = AudioSystem.newAudioSessionId(); 3641 if (session > 0) { 3642 return session; 3643 } else { 3644 Log.e(TAG, "Failure to generate a new audio session ID"); 3645 return ERROR; 3646 } 3647 } 3648 3649 /** 3650 * A special audio session ID to indicate that the audio session ID isn't known and the 3651 * framework should generate a new value. This can be used when building a new 3652 * {@link AudioTrack} instance with 3653 * {@link AudioTrack#AudioTrack(AudioAttributes, AudioFormat, int, int, int)}. 3654 */ 3655 public static final int AUDIO_SESSION_ID_GENERATE = AudioSystem.AUDIO_SESSION_ALLOCATE; 3656 3657 3658 /* 3659 * Sets a generic audio configuration parameter. The use of these parameters 3660 * are platform dependant, see libaudio 3661 * 3662 * ** Temporary interface - DO NOT USE 3663 * 3664 * TODO: Replace with a more generic key:value get/set mechanism 3665 * 3666 * param key name of parameter to set. Must not be null. 3667 * param value value of parameter. Must not be null. 3668 */ 3669 /** 3670 * @hide 3671 * @deprecated Use {@link #setParameters(String)} instead 3672 */ setParameter(String key, String value)3673 @Deprecated public void setParameter(String key, String value) { 3674 setParameters(key+"="+value); 3675 } 3676 3677 /** 3678 * Sets a variable number of parameter values to audio hardware. 3679 * 3680 * @param keyValuePairs list of parameters key value pairs in the form: 3681 * key1=value1;key2=value2;... 3682 * 3683 */ setParameters(String keyValuePairs)3684 public void setParameters(String keyValuePairs) { 3685 AudioSystem.setParameters(keyValuePairs); 3686 } 3687 3688 /** 3689 * @hide 3690 */ 3691 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 3692 @RequiresPermission(Manifest.permission.BLUETOOTH_STACK) setHfpEnabled(boolean enable)3693 public void setHfpEnabled(boolean enable) { 3694 AudioSystem.setParameters("hfp_enable=" + enable); 3695 } 3696 3697 /** 3698 * @hide 3699 */ 3700 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 3701 @RequiresPermission(Manifest.permission.BLUETOOTH_STACK) setHfpVolume(int volume)3702 public void setHfpVolume(int volume) { 3703 AudioSystem.setParameters("hfp_volume=" + volume); 3704 } 3705 3706 /** 3707 * @hide 3708 */ 3709 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 3710 @RequiresPermission(Manifest.permission.BLUETOOTH_STACK) setHfpSamplingRate(int rate)3711 public void setHfpSamplingRate(int rate) { 3712 AudioSystem.setParameters("hfp_set_sampling_rate=" + rate); 3713 } 3714 3715 /** 3716 * @hide 3717 */ 3718 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 3719 @RequiresPermission(Manifest.permission.BLUETOOTH_STACK) setBluetoothHeadsetProperties(@onNull String name, boolean hasNrecEnabled, boolean hasWbsEnabled)3720 public void setBluetoothHeadsetProperties(@NonNull String name, boolean hasNrecEnabled, 3721 boolean hasWbsEnabled) { 3722 AudioSystem.setParameters("bt_headset_name=" + name 3723 + ";bt_headset_nrec=" + (hasNrecEnabled ? "on" : "off") 3724 + ";bt_wbs=" + (hasWbsEnabled ? "on" : "off")); 3725 } 3726 3727 /** 3728 * @hide 3729 */ 3730 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 3731 @RequiresPermission(Manifest.permission.BLUETOOTH_STACK) setA2dpSuspended(boolean enable)3732 public void setA2dpSuspended(boolean enable) { 3733 final IAudioService service = getService(); 3734 try { 3735 service.setA2dpSuspended(enable); 3736 } catch (RemoteException e) { 3737 throw e.rethrowFromSystemServer(); 3738 } 3739 } 3740 3741 /** 3742 * Suspends the use of LE Audio. 3743 * 3744 * @param enable {@code true} to suspend le audio, {@code false} to unsuspend 3745 * 3746 * @hide 3747 */ 3748 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 3749 @RequiresPermission(Manifest.permission.BLUETOOTH_STACK) setLeAudioSuspended(boolean enable)3750 public void setLeAudioSuspended(boolean enable) { 3751 final IAudioService service = getService(); 3752 try { 3753 service.setLeAudioSuspended(enable); 3754 } catch (RemoteException e) { 3755 throw e.rethrowFromSystemServer(); 3756 } 3757 } 3758 3759 /** 3760 * Gets a variable number of parameter values from audio hardware. 3761 * 3762 * @param keys list of parameters 3763 * @return list of parameters key value pairs in the form: 3764 * key1=value1;key2=value2;... 3765 */ getParameters(String keys)3766 public String getParameters(String keys) { 3767 return AudioSystem.getParameters(keys); 3768 } 3769 3770 /* Sound effect identifiers */ 3771 /** 3772 * Keyboard and direction pad click sound 3773 * @see #playSoundEffect(int) 3774 */ 3775 public static final int FX_KEY_CLICK = 0; 3776 /** 3777 * Focus has moved up 3778 * @see #playSoundEffect(int) 3779 */ 3780 public static final int FX_FOCUS_NAVIGATION_UP = 1; 3781 /** 3782 * Focus has moved down 3783 * @see #playSoundEffect(int) 3784 */ 3785 public static final int FX_FOCUS_NAVIGATION_DOWN = 2; 3786 /** 3787 * Focus has moved left 3788 * @see #playSoundEffect(int) 3789 */ 3790 public static final int FX_FOCUS_NAVIGATION_LEFT = 3; 3791 /** 3792 * Focus has moved right 3793 * @see #playSoundEffect(int) 3794 */ 3795 public static final int FX_FOCUS_NAVIGATION_RIGHT = 4; 3796 /** 3797 * IME standard keypress sound 3798 * @see #playSoundEffect(int) 3799 */ 3800 public static final int FX_KEYPRESS_STANDARD = 5; 3801 /** 3802 * IME spacebar keypress sound 3803 * @see #playSoundEffect(int) 3804 */ 3805 public static final int FX_KEYPRESS_SPACEBAR = 6; 3806 /** 3807 * IME delete keypress sound 3808 * @see #playSoundEffect(int) 3809 */ 3810 public static final int FX_KEYPRESS_DELETE = 7; 3811 /** 3812 * IME return_keypress sound 3813 * @see #playSoundEffect(int) 3814 */ 3815 public static final int FX_KEYPRESS_RETURN = 8; 3816 3817 /** 3818 * Invalid keypress sound 3819 * @see #playSoundEffect(int) 3820 */ 3821 public static final int FX_KEYPRESS_INVALID = 9; 3822 3823 /** 3824 * Back sound 3825 * @see #playSoundEffect(int) 3826 */ 3827 public static final int FX_BACK = 10; 3828 3829 /** 3830 * @hide Home sound 3831 * <p> 3832 * To be played by the framework when the home app becomes active if config_enableHomeSound is 3833 * set to true. This is currently only used on TV devices. 3834 * Note that this sound is only available if a sound file is specified in audio_assets.xml. 3835 * @see #playSoundEffect(int) 3836 */ 3837 public static final int FX_HOME = 11; 3838 3839 /** 3840 * @hide Navigation repeat sound 1 3841 * <p> 3842 * To be played by the framework when a focus navigation is repeatedly triggered 3843 * (e.g. due to long-pressing) and {@link #areNavigationRepeatSoundEffectsEnabled()} is true. 3844 * This is currently only used on TV devices. 3845 * Note that this sound is only available if a sound file is specified in audio_assets.xml 3846 * @see #playSoundEffect(int) 3847 */ 3848 public static final int FX_FOCUS_NAVIGATION_REPEAT_1 = 12; 3849 3850 /** 3851 * @hide Navigation repeat sound 2 3852 * <p> 3853 * To be played by the framework when a focus navigation is repeatedly triggered 3854 * (e.g. due to long-pressing) and {@link #areNavigationRepeatSoundEffectsEnabled()} is true. 3855 * This is currently only used on TV devices. 3856 * Note that this sound is only available if a sound file is specified in audio_assets.xml 3857 * @see #playSoundEffect(int) 3858 */ 3859 public static final int FX_FOCUS_NAVIGATION_REPEAT_2 = 13; 3860 3861 /** 3862 * @hide Navigation repeat sound 3 3863 * <p> 3864 * To be played by the framework when a focus navigation is repeatedly triggered 3865 * (e.g. due to long-pressing) and {@link #areNavigationRepeatSoundEffectsEnabled()} is true. 3866 * This is currently only used on TV devices. 3867 * Note that this sound is only available if a sound file is specified in audio_assets.xml 3868 * @see #playSoundEffect(int) 3869 */ 3870 public static final int FX_FOCUS_NAVIGATION_REPEAT_3 = 14; 3871 3872 /** 3873 * @hide Navigation repeat sound 4 3874 * <p> 3875 * To be played by the framework when a focus navigation is repeatedly triggered 3876 * (e.g. due to long-pressing) and {@link #areNavigationRepeatSoundEffectsEnabled()} is true. 3877 * This is currently only used on TV devices. 3878 * Note that this sound is only available if a sound file is specified in audio_assets.xml 3879 * @see #playSoundEffect(int) 3880 */ 3881 public static final int FX_FOCUS_NAVIGATION_REPEAT_4 = 15; 3882 3883 /** 3884 * @hide Number of sound effects 3885 */ 3886 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 3887 public static final int NUM_SOUND_EFFECTS = 16; 3888 3889 /** @hide */ 3890 @IntDef(prefix = { "FX_" }, value = { 3891 FX_KEY_CLICK, 3892 FX_FOCUS_NAVIGATION_UP, 3893 FX_FOCUS_NAVIGATION_DOWN, 3894 FX_FOCUS_NAVIGATION_LEFT, 3895 FX_FOCUS_NAVIGATION_RIGHT, 3896 FX_KEYPRESS_STANDARD, 3897 FX_KEYPRESS_SPACEBAR, 3898 FX_KEYPRESS_DELETE, 3899 FX_KEYPRESS_RETURN, 3900 FX_KEYPRESS_INVALID, 3901 FX_BACK 3902 }) 3903 @Retention(RetentionPolicy.SOURCE) 3904 public @interface SystemSoundEffect {} 3905 3906 /** 3907 * @hide Number of FX_FOCUS_NAVIGATION_REPEAT_* sound effects 3908 */ 3909 public static final int NUM_NAVIGATION_REPEAT_SOUND_EFFECTS = 4; 3910 3911 /** 3912 * @hide 3913 * @param n a value in [0, {@link #NUM_NAVIGATION_REPEAT_SOUND_EFFECTS}[ 3914 * @return The id of a navigation repeat sound effect or -1 if out of bounds 3915 */ getNthNavigationRepeatSoundEffect(int n)3916 public static int getNthNavigationRepeatSoundEffect(int n) { 3917 switch (n) { 3918 case 0: 3919 return FX_FOCUS_NAVIGATION_REPEAT_1; 3920 case 1: 3921 return FX_FOCUS_NAVIGATION_REPEAT_2; 3922 case 2: 3923 return FX_FOCUS_NAVIGATION_REPEAT_3; 3924 case 3: 3925 return FX_FOCUS_NAVIGATION_REPEAT_4; 3926 default: 3927 Log.w(TAG, "Invalid navigation repeat sound effect id: " + n); 3928 return -1; 3929 } 3930 } 3931 3932 /** 3933 * @hide 3934 */ setNavigationRepeatSoundEffectsEnabled(boolean enabled)3935 public void setNavigationRepeatSoundEffectsEnabled(boolean enabled) { 3936 try { 3937 getService().setNavigationRepeatSoundEffectsEnabled(enabled); 3938 } catch (RemoteException e) { 3939 3940 } 3941 } 3942 3943 /** 3944 * @hide 3945 * @return true if the navigation repeat sound effects are enabled 3946 */ areNavigationRepeatSoundEffectsEnabled()3947 public boolean areNavigationRepeatSoundEffectsEnabled() { 3948 try { 3949 return getService().areNavigationRepeatSoundEffectsEnabled(); 3950 } catch (RemoteException e) { 3951 throw e.rethrowFromSystemServer(); 3952 } 3953 } 3954 3955 /** 3956 * @hide 3957 * @param enabled 3958 */ setHomeSoundEffectEnabled(boolean enabled)3959 public void setHomeSoundEffectEnabled(boolean enabled) { 3960 try { 3961 getService().setHomeSoundEffectEnabled(enabled); 3962 } catch (RemoteException e) { 3963 3964 } 3965 } 3966 3967 /** 3968 * @hide 3969 * @return true if the home sound effect is enabled 3970 */ isHomeSoundEffectEnabled()3971 public boolean isHomeSoundEffectEnabled() { 3972 try { 3973 return getService().isHomeSoundEffectEnabled(); 3974 } catch (RemoteException e) { 3975 throw e.rethrowFromSystemServer(); 3976 } 3977 } 3978 3979 /** 3980 * Plays a sound effect (Key clicks, lid open/close...) 3981 * @param effectType The type of sound effect. 3982 * NOTE: This version uses the UI settings to determine 3983 * whether sounds are heard or not. 3984 */ playSoundEffect(@ystemSoundEffect int effectType)3985 public void playSoundEffect(@SystemSoundEffect int effectType) { 3986 playSoundEffect(effectType, UserHandle.USER_CURRENT); 3987 } 3988 3989 /** 3990 * Plays a sound effect (Key clicks, lid open/close...) 3991 * @param effectType The type of sound effect. 3992 * @param userId The current user to pull sound settings from 3993 * NOTE: This version uses the UI settings to determine 3994 * whether sounds are heard or not. 3995 * @hide 3996 */ playSoundEffect(@ystemSoundEffect int effectType, int userId)3997 public void playSoundEffect(@SystemSoundEffect int effectType, int userId) { 3998 if (effectType < 0 || effectType >= NUM_SOUND_EFFECTS) { 3999 return; 4000 } 4001 4002 if (delegateSoundEffectToVdm(effectType)) { 4003 return; 4004 } 4005 4006 final IAudioService service = getService(); 4007 try { 4008 service.playSoundEffect(effectType, userId); 4009 } catch (RemoteException e) { 4010 throw e.rethrowFromSystemServer(); 4011 } 4012 } 4013 4014 /** 4015 * Plays a sound effect (Key clicks, lid open/close...) 4016 * @param effectType The type of sound effect. 4017 * @param volume Sound effect volume. 4018 * The volume value is a raw scalar so UI controls should be scaled logarithmically. 4019 * If a volume of -1 is specified, the AudioManager.STREAM_MUSIC stream volume minus 3dB will be used. 4020 * NOTE: This version is for applications that have their own 4021 * settings panel for enabling and controlling volume. 4022 */ playSoundEffect(@ystemSoundEffect int effectType, float volume)4023 public void playSoundEffect(@SystemSoundEffect int effectType, float volume) { 4024 if (effectType < 0 || effectType >= NUM_SOUND_EFFECTS) { 4025 return; 4026 } 4027 4028 if (delegateSoundEffectToVdm(effectType)) { 4029 return; 4030 } 4031 4032 final IAudioService service = getService(); 4033 try { 4034 service.playSoundEffectVolume(effectType, volume); 4035 } catch (RemoteException e) { 4036 throw e.rethrowFromSystemServer(); 4037 } 4038 } 4039 4040 /** 4041 * Checks whether this {@link AudioManager} instance is associated with {@link VirtualDevice} 4042 * configured with custom device policy for audio. If there is such device, request to play 4043 * sound effect is forwarded to {@link VirtualDeviceManager}. 4044 * 4045 * @param effectType - The type of sound effect. 4046 * @return true if the request was forwarded to {@link VirtualDeviceManager} instance, 4047 * false otherwise. 4048 */ delegateSoundEffectToVdm(@ystemSoundEffect int effectType)4049 private boolean delegateSoundEffectToVdm(@SystemSoundEffect int effectType) { 4050 if (hasCustomPolicyVirtualDeviceContext()) { 4051 VirtualDeviceManager vdm = getVirtualDeviceManager(); 4052 vdm.playSoundEffect(mOriginalContextDeviceId, effectType); 4053 return true; 4054 } 4055 return false; 4056 } 4057 hasCustomPolicyVirtualDeviceContext()4058 private boolean hasCustomPolicyVirtualDeviceContext() { 4059 if (mOriginalContextDeviceId == DEVICE_ID_DEFAULT) { 4060 return false; 4061 } 4062 4063 VirtualDeviceManager vdm = getVirtualDeviceManager(); 4064 return vdm != null && vdm.getDevicePolicy(mOriginalContextDeviceId, POLICY_TYPE_AUDIO) 4065 != DEVICE_POLICY_DEFAULT; 4066 } 4067 4068 /** 4069 * Load Sound effects. 4070 * This method must be called when sound effects are enabled. 4071 */ loadSoundEffects()4072 public void loadSoundEffects() { 4073 final IAudioService service = getService(); 4074 try { 4075 service.loadSoundEffects(); 4076 } catch (RemoteException e) { 4077 throw e.rethrowFromSystemServer(); 4078 } 4079 } 4080 4081 /** 4082 * Unload Sound effects. 4083 * This method can be called to free some memory when 4084 * sound effects are disabled. 4085 */ unloadSoundEffects()4086 public void unloadSoundEffects() { 4087 final IAudioService service = getService(); 4088 try { 4089 service.unloadSoundEffects(); 4090 } catch (RemoteException e) { 4091 throw e.rethrowFromSystemServer(); 4092 } 4093 } 4094 4095 /** 4096 * @hide 4097 */ audioFocusToString(int focus)4098 public static String audioFocusToString(int focus) { 4099 switch (focus) { 4100 case AUDIOFOCUS_NONE: 4101 return "AUDIOFOCUS_NONE"; 4102 case AUDIOFOCUS_GAIN: 4103 return "AUDIOFOCUS_GAIN"; 4104 case AUDIOFOCUS_GAIN_TRANSIENT: 4105 return "AUDIOFOCUS_GAIN_TRANSIENT"; 4106 case AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK: 4107 return "AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK"; 4108 case AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE: 4109 return "AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE"; 4110 case AUDIOFOCUS_LOSS: 4111 return "AUDIOFOCUS_LOSS"; 4112 case AUDIOFOCUS_LOSS_TRANSIENT: 4113 return "AUDIOFOCUS_LOSS_TRANSIENT"; 4114 case AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: // Note CAN_DUCK not MAY_DUCK. 4115 return "AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK"; 4116 default: 4117 return "AUDIO_FOCUS_UNKNOWN(" + focus + ")"; 4118 } 4119 } 4120 4121 /** 4122 * Used to indicate no audio focus has been gained or lost, or requested. 4123 */ 4124 public static final int AUDIOFOCUS_NONE = 0; 4125 4126 /** 4127 * Used to indicate a gain of audio focus, or a request of audio focus, of unknown duration. 4128 * @see OnAudioFocusChangeListener#onAudioFocusChange(int) 4129 * @see #requestAudioFocus(OnAudioFocusChangeListener, int, int) 4130 */ 4131 public static final int AUDIOFOCUS_GAIN = 1; 4132 /** 4133 * Used to indicate a temporary gain or request of audio focus, anticipated to last a short 4134 * amount of time. Examples of temporary changes are the playback of driving directions, or an 4135 * event notification. 4136 * @see OnAudioFocusChangeListener#onAudioFocusChange(int) 4137 * @see #requestAudioFocus(OnAudioFocusChangeListener, int, int) 4138 */ 4139 public static final int AUDIOFOCUS_GAIN_TRANSIENT = 2; 4140 /** 4141 * Used to indicate a temporary request of audio focus, anticipated to last a short 4142 * amount of time, and where it is acceptable for other audio applications to keep playing 4143 * after having lowered their output level (also referred to as "ducking"). 4144 * Examples of temporary changes are the playback of driving directions where playback of music 4145 * in the background is acceptable. 4146 * @see OnAudioFocusChangeListener#onAudioFocusChange(int) 4147 * @see #requestAudioFocus(OnAudioFocusChangeListener, int, int) 4148 */ 4149 public static final int AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK = 3; 4150 /** 4151 * Used to indicate a temporary request of audio focus, anticipated to last a short 4152 * amount of time, during which no other applications, or system components, should play 4153 * anything. Examples of exclusive and transient audio focus requests are voice 4154 * memo recording and speech recognition, during which the system shouldn't play any 4155 * notifications, and media playback should have paused. 4156 * @see #requestAudioFocus(OnAudioFocusChangeListener, int, int) 4157 */ 4158 public static final int AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE = 4; 4159 /** 4160 * Used to indicate a loss of audio focus of unknown duration. 4161 * @see OnAudioFocusChangeListener#onAudioFocusChange(int) 4162 */ 4163 public static final int AUDIOFOCUS_LOSS = -1 * AUDIOFOCUS_GAIN; 4164 /** 4165 * Used to indicate a transient loss of audio focus. 4166 * @see OnAudioFocusChangeListener#onAudioFocusChange(int) 4167 */ 4168 public static final int AUDIOFOCUS_LOSS_TRANSIENT = -1 * AUDIOFOCUS_GAIN_TRANSIENT; 4169 /** 4170 * Used to indicate a transient loss of audio focus where the loser of the audio focus can 4171 * lower its output volume if it wants to continue playing (also referred to as "ducking"), as 4172 * the new focus owner doesn't require others to be silent. 4173 * @see OnAudioFocusChangeListener#onAudioFocusChange(int) 4174 */ 4175 public static final int AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK = 4176 -1 * AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK; 4177 4178 /** 4179 * Interface definition for a callback to be invoked when the audio focus of the system is 4180 * updated. 4181 */ 4182 public interface OnAudioFocusChangeListener { 4183 /** 4184 * Called on the listener to notify it the audio focus for this listener has been changed. 4185 * The focusChange value indicates whether the focus was gained, 4186 * whether the focus was lost, and whether that loss is transient, or whether the new focus 4187 * holder will hold it for an unknown amount of time. 4188 * When losing focus, listeners can use the focus change information to decide what 4189 * behavior to adopt when losing focus. A music player could for instance elect to lower 4190 * the volume of its music stream (duck) for transient focus losses, and pause otherwise. 4191 * @param focusChange the type of focus change, one of {@link AudioManager#AUDIOFOCUS_GAIN}, 4192 * {@link AudioManager#AUDIOFOCUS_LOSS}, {@link AudioManager#AUDIOFOCUS_LOSS_TRANSIENT} 4193 * and {@link AudioManager#AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK}. 4194 */ onAudioFocusChange(int focusChange)4195 public void onAudioFocusChange(int focusChange); 4196 } 4197 4198 /** 4199 * Internal class to hold the AudioFocusRequest as well as the Handler for the callback 4200 */ 4201 private static class FocusRequestInfo { 4202 @NonNull final AudioFocusRequest mRequest; 4203 @Nullable final Handler mHandler; FocusRequestInfo(@onNull AudioFocusRequest afr, @Nullable Handler handler)4204 FocusRequestInfo(@NonNull AudioFocusRequest afr, @Nullable Handler handler) { 4205 mRequest = afr; 4206 mHandler = handler; 4207 } 4208 } 4209 4210 /** 4211 * Map to convert focus event listener IDs, as used in the AudioService audio focus stack, 4212 * to actual listener objects. 4213 */ 4214 @UnsupportedAppUsage 4215 private final ConcurrentHashMap<String, FocusRequestInfo> mAudioFocusIdListenerMap = 4216 new ConcurrentHashMap<String, FocusRequestInfo>(); 4217 findFocusRequestInfo(String id)4218 private FocusRequestInfo findFocusRequestInfo(String id) { 4219 return mAudioFocusIdListenerMap.get(id); 4220 } 4221 4222 /** 4223 * Handler for events (audio focus change, recording config change) coming from the 4224 * audio service. 4225 */ 4226 private final ServiceEventHandlerDelegate mServiceEventHandlerDelegate = 4227 new ServiceEventHandlerDelegate(null); 4228 4229 /** 4230 * Event types 4231 */ 4232 private final static int MSSG_FOCUS_CHANGE = 0; 4233 private final static int MSSG_RECORDING_CONFIG_CHANGE = 1; 4234 private final static int MSSG_PLAYBACK_CONFIG_CHANGE = 2; 4235 4236 /** 4237 * Helper class to handle the forwarding of audio service events to the appropriate listener 4238 */ 4239 private class ServiceEventHandlerDelegate { 4240 private final Handler mHandler; 4241 ServiceEventHandlerDelegate(Handler handler)4242 ServiceEventHandlerDelegate(Handler handler) { 4243 Looper looper; 4244 if (handler == null) { 4245 if ((looper = Looper.myLooper()) == null) { 4246 looper = Looper.getMainLooper(); 4247 } 4248 } else { 4249 looper = handler.getLooper(); 4250 } 4251 4252 if (looper != null) { 4253 // implement the event handler delegate to receive events from audio service 4254 mHandler = new Handler(looper) { 4255 @Override 4256 public void handleMessage(Message msg) { 4257 switch (msg.what) { 4258 case MSSG_FOCUS_CHANGE: { 4259 final FocusRequestInfo fri = findFocusRequestInfo((String)msg.obj); 4260 if (fri != null) { 4261 final OnAudioFocusChangeListener listener = 4262 fri.mRequest.getOnAudioFocusChangeListener(); 4263 if (listener != null) { 4264 Log.d(TAG, "dispatching onAudioFocusChange(" 4265 + msg.arg1 + ") to " + msg.obj); 4266 listener.onAudioFocusChange(msg.arg1); 4267 } 4268 } 4269 } break; 4270 case MSSG_RECORDING_CONFIG_CHANGE: { 4271 final RecordConfigChangeCallbackData cbData = 4272 (RecordConfigChangeCallbackData) msg.obj; 4273 if (cbData.mCb != null) { 4274 cbData.mCb.onRecordingConfigChanged(cbData.mConfigs); 4275 } 4276 } break; 4277 case MSSG_PLAYBACK_CONFIG_CHANGE: { 4278 final PlaybackConfigChangeCallbackData cbData = 4279 (PlaybackConfigChangeCallbackData) msg.obj; 4280 if (cbData.mCb != null) { 4281 if (DEBUG) { 4282 Log.d(TAG, "dispatching onPlaybackConfigChanged()"); 4283 } 4284 cbData.mCb.onPlaybackConfigChanged(cbData.mConfigs); 4285 } 4286 } break; 4287 default: 4288 Log.e(TAG, "Unknown event " + msg.what); 4289 } 4290 } 4291 }; 4292 } else { 4293 mHandler = null; 4294 } 4295 } 4296 getHandler()4297 Handler getHandler() { 4298 return mHandler; 4299 } 4300 } 4301 4302 private final IAudioFocusDispatcher mAudioFocusDispatcher = new IAudioFocusDispatcher.Stub() { 4303 @Override 4304 public void dispatchAudioFocusChange(int focusChange, String id) { 4305 final FocusRequestInfo fri = findFocusRequestInfo(id); 4306 if (fri != null) { 4307 final OnAudioFocusChangeListener listener = 4308 fri.mRequest.getOnAudioFocusChangeListener(); 4309 if (listener != null) { 4310 final Handler h = (fri.mHandler == null) ? 4311 mServiceEventHandlerDelegate.getHandler() : fri.mHandler; 4312 final Message m = h.obtainMessage( 4313 MSSG_FOCUS_CHANGE/*what*/, focusChange/*arg1*/, 0/*arg2 ignored*/, 4314 id/*obj*/); 4315 h.sendMessage(m); 4316 } 4317 } 4318 } 4319 4320 @Override 4321 public void dispatchFocusResultFromExtPolicy(int requestResult, String clientId) { 4322 synchronized (mFocusRequestsLock) { 4323 // TODO use generation counter as the key instead 4324 final BlockingFocusResultReceiver focusReceiver = 4325 mFocusRequestsAwaitingResult.remove(clientId); 4326 if (focusReceiver != null) { 4327 focusReceiver.notifyResult(requestResult); 4328 } else { 4329 Log.e(TAG, "dispatchFocusResultFromExtPolicy found no result receiver"); 4330 } 4331 } 4332 } 4333 }; 4334 getIdForAudioFocusListener(OnAudioFocusChangeListener l)4335 private String getIdForAudioFocusListener(OnAudioFocusChangeListener l) { 4336 if (l == null) { 4337 return new String(this.toString()); 4338 } else { 4339 return new String(this.toString() + l.toString()); 4340 } 4341 } 4342 4343 /** 4344 * @hide 4345 * Registers a listener to be called when audio focus changes and keeps track of the associated 4346 * focus request (including Handler to use for the listener). 4347 * @param afr the full request parameters 4348 */ registerAudioFocusRequest(@onNull AudioFocusRequest afr)4349 public void registerAudioFocusRequest(@NonNull AudioFocusRequest afr) { 4350 final Handler h = afr.getOnAudioFocusChangeListenerHandler(); 4351 final FocusRequestInfo fri = new FocusRequestInfo(afr, (h == null) ? null : 4352 new ServiceEventHandlerDelegate(h).getHandler()); 4353 final String key = getIdForAudioFocusListener(afr.getOnAudioFocusChangeListener()); 4354 mAudioFocusIdListenerMap.put(key, fri); 4355 } 4356 4357 /** 4358 * @hide 4359 * Causes the specified listener to not be called anymore when focus is gained or lost. 4360 * @param l the listener to unregister. 4361 */ unregisterAudioFocusRequest(OnAudioFocusChangeListener l)4362 public void unregisterAudioFocusRequest(OnAudioFocusChangeListener l) { 4363 // remove locally 4364 mAudioFocusIdListenerMap.remove(getIdForAudioFocusListener(l)); 4365 } 4366 4367 4368 /** 4369 * A failed focus change request. 4370 */ 4371 public static final int AUDIOFOCUS_REQUEST_FAILED = 0; 4372 /** 4373 * A successful focus change request. 4374 */ 4375 public static final int AUDIOFOCUS_REQUEST_GRANTED = 1; 4376 /** 4377 * A focus change request whose granting is delayed: the request was successful, but the 4378 * requester will only be granted audio focus once the condition that prevented immediate 4379 * granting has ended. 4380 * See {@link #requestAudioFocus(AudioFocusRequest)} and 4381 * {@link AudioFocusRequest.Builder#setAcceptsDelayedFocusGain(boolean)} 4382 */ 4383 public static final int AUDIOFOCUS_REQUEST_DELAYED = 2; 4384 4385 /** @hide */ 4386 @IntDef(flag = false, prefix = "AUDIOFOCUS_REQUEST", value = { 4387 AUDIOFOCUS_REQUEST_FAILED, 4388 AUDIOFOCUS_REQUEST_GRANTED, 4389 AUDIOFOCUS_REQUEST_DELAYED } 4390 ) 4391 @Retention(RetentionPolicy.SOURCE) 4392 public @interface FocusRequestResult {} 4393 4394 /** 4395 * @hide 4396 * code returned when a synchronous focus request on the client-side is to be blocked 4397 * until the external audio focus policy decides on the response for the client 4398 */ 4399 public static final int AUDIOFOCUS_REQUEST_WAITING_FOR_EXT_POLICY = 100; 4400 4401 /** 4402 * Timeout duration in ms when waiting on an external focus policy for the result for a 4403 * focus request 4404 */ 4405 private static final int EXT_FOCUS_POLICY_TIMEOUT_MS = 250; 4406 4407 private static final String FOCUS_CLIENT_ID_STRING = "android_audio_focus_client_id"; 4408 4409 private final Object mFocusRequestsLock = new Object(); 4410 /** 4411 * Map of all receivers of focus request results, one per unresolved focus request. 4412 * Receivers are added before sending the request to the external focus policy, 4413 * and are removed either after receiving the result, or after the timeout. 4414 * This variable is lazily initialized. 4415 */ 4416 @GuardedBy("mFocusRequestsLock") 4417 private HashMap<String, BlockingFocusResultReceiver> mFocusRequestsAwaitingResult; 4418 4419 4420 /** 4421 * Request audio focus. 4422 * Send a request to obtain the audio focus 4423 * @param l the listener to be notified of audio focus changes 4424 * @param streamType the main audio stream type affected by the focus request 4425 * @param durationHint use {@link #AUDIOFOCUS_GAIN_TRANSIENT} to indicate this focus request 4426 * is temporary, and focus will be abandonned shortly. Examples of transient requests are 4427 * for the playback of driving directions, or notifications sounds. 4428 * Use {@link #AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK} to indicate also that it's ok for 4429 * the previous focus owner to keep playing if it ducks its audio output. 4430 * Alternatively use {@link #AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE} for a temporary request 4431 * that benefits from the system not playing disruptive sounds like notifications, for 4432 * usecases such as voice memo recording, or speech recognition. 4433 * Use {@link #AUDIOFOCUS_GAIN} for a focus request of unknown duration such 4434 * as the playback of a song or a video. 4435 * @return {@link #AUDIOFOCUS_REQUEST_FAILED} or {@link #AUDIOFOCUS_REQUEST_GRANTED} 4436 * @deprecated use {@link #requestAudioFocus(AudioFocusRequest)} 4437 */ requestAudioFocus(OnAudioFocusChangeListener l, int streamType, int durationHint)4438 public int requestAudioFocus(OnAudioFocusChangeListener l, int streamType, int durationHint) { 4439 PlayerBase.deprecateStreamTypeForPlayback(streamType, 4440 "AudioManager", "requestAudioFocus()"); 4441 int status = AUDIOFOCUS_REQUEST_FAILED; 4442 4443 try { 4444 // status is guaranteed to be either AUDIOFOCUS_REQUEST_FAILED or 4445 // AUDIOFOCUS_REQUEST_GRANTED as focus is requested without the 4446 // AUDIOFOCUS_FLAG_DELAY_OK flag 4447 status = requestAudioFocus(l, 4448 new AudioAttributes.Builder() 4449 .setInternalLegacyStreamType(streamType).build(), 4450 durationHint, 4451 0 /* flags, legacy behavior */); 4452 } catch (IllegalArgumentException e) { 4453 Log.e(TAG, "Audio focus request denied due to ", e); 4454 } 4455 4456 return status; 4457 } 4458 4459 // when adding new flags, add them to the relevant AUDIOFOCUS_FLAGS_APPS or SYSTEM masks 4460 /** 4461 * @hide 4462 * Use this flag when requesting audio focus to indicate it is ok for the requester to not be 4463 * granted audio focus immediately (as indicated by {@link #AUDIOFOCUS_REQUEST_DELAYED}) when 4464 * the system is in a state where focus cannot change, but be granted focus later when 4465 * this condition ends. 4466 */ 4467 @SystemApi 4468 public static final int AUDIOFOCUS_FLAG_DELAY_OK = 0x1 << 0; 4469 /** 4470 * @hide 4471 * Use this flag when requesting audio focus to indicate that the requester 4472 * will pause its media playback (if applicable) when losing audio focus with 4473 * {@link #AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK}, rather than ducking. 4474 * <br>On some platforms, the ducking may be handled without the application being aware of it 4475 * (i.e. it will not transiently lose focus). For applications that for instance play spoken 4476 * content, such as audio book or podcast players, ducking may never be acceptable, and will 4477 * thus always pause. This flag enables them to be declared as such whenever they request focus. 4478 */ 4479 @SystemApi 4480 public static final int AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS = 0x1 << 1; 4481 /** 4482 * @hide 4483 * Use this flag to lock audio focus so granting is temporarily disabled. 4484 * <br>This flag can only be used by owners of a registered 4485 * {@link android.media.audiopolicy.AudioPolicy} in 4486 * {@link #requestAudioFocus(OnAudioFocusChangeListener, AudioAttributes, int, int, AudioPolicy)} 4487 */ 4488 @SystemApi 4489 public static final int AUDIOFOCUS_FLAG_LOCK = 0x1 << 2; 4490 4491 /** 4492 * @hide 4493 * flag set on test API calls, 4494 * see {@link #requestAudioFocusForTest(AudioFocusRequest, String, int, int)}, 4495 */ 4496 public static final int AUDIOFOCUS_FLAG_TEST = 0x1 << 3; 4497 /** @hide */ 4498 public static final int AUDIOFOCUS_FLAGS_APPS = AUDIOFOCUS_FLAG_DELAY_OK 4499 | AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS; 4500 /** @hide */ 4501 public static final int AUDIOFOCUS_FLAGS_SYSTEM = AUDIOFOCUS_FLAG_DELAY_OK 4502 | AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS | AUDIOFOCUS_FLAG_LOCK; 4503 4504 /** 4505 * Request audio focus. 4506 * See the {@link AudioFocusRequest} for information about the options available to configure 4507 * your request, and notification of focus gain and loss. 4508 * @param focusRequest a {@link AudioFocusRequest} instance used to configure how focus is 4509 * requested. 4510 * @return {@link #AUDIOFOCUS_REQUEST_FAILED}, {@link #AUDIOFOCUS_REQUEST_GRANTED} 4511 * or {@link #AUDIOFOCUS_REQUEST_DELAYED}. 4512 * <br>Note that the return value is never {@link #AUDIOFOCUS_REQUEST_DELAYED} when focus 4513 * is requested without building the {@link AudioFocusRequest} with 4514 * {@link AudioFocusRequest.Builder#setAcceptsDelayedFocusGain(boolean)} set to 4515 * {@code true}. 4516 * @throws NullPointerException if passed a null argument 4517 */ requestAudioFocus(@onNull AudioFocusRequest focusRequest)4518 public int requestAudioFocus(@NonNull AudioFocusRequest focusRequest) { 4519 return requestAudioFocus(focusRequest, null /* no AudioPolicy*/); 4520 } 4521 4522 /** 4523 * Abandon audio focus. Causes the previous focus owner, if any, to receive focus. 4524 * @param focusRequest the {@link AudioFocusRequest} that was used when requesting focus 4525 * with {@link #requestAudioFocus(AudioFocusRequest)}. 4526 * @return {@link #AUDIOFOCUS_REQUEST_FAILED} or {@link #AUDIOFOCUS_REQUEST_GRANTED} 4527 * @throws IllegalArgumentException if passed a null argument 4528 */ abandonAudioFocusRequest(@onNull AudioFocusRequest focusRequest)4529 public int abandonAudioFocusRequest(@NonNull AudioFocusRequest focusRequest) { 4530 if (focusRequest == null) { 4531 throw new IllegalArgumentException("Illegal null AudioFocusRequest"); 4532 } 4533 return abandonAudioFocus(focusRequest.getOnAudioFocusChangeListener(), 4534 focusRequest.getAudioAttributes()); 4535 } 4536 4537 /** 4538 * @hide 4539 * Request audio focus. 4540 * Send a request to obtain the audio focus. This method differs from 4541 * {@link #requestAudioFocus(OnAudioFocusChangeListener, int, int)} in that it can express 4542 * that the requester accepts delayed grants of audio focus. 4543 * @param l the listener to be notified of audio focus changes. It is not allowed to be null 4544 * when the request is flagged with {@link #AUDIOFOCUS_FLAG_DELAY_OK}. 4545 * @param requestAttributes non null {@link AudioAttributes} describing the main reason for 4546 * requesting audio focus. 4547 * @param durationHint use {@link #AUDIOFOCUS_GAIN_TRANSIENT} to indicate this focus request 4548 * is temporary, and focus will be abandonned shortly. Examples of transient requests are 4549 * for the playback of driving directions, or notifications sounds. 4550 * Use {@link #AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK} to indicate also that it's ok for 4551 * the previous focus owner to keep playing if it ducks its audio output. 4552 * Alternatively use {@link #AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE} for a temporary request 4553 * that benefits from the system not playing disruptive sounds like notifications, for 4554 * usecases such as voice memo recording, or speech recognition. 4555 * Use {@link #AUDIOFOCUS_GAIN} for a focus request of unknown duration such 4556 * as the playback of a song or a video. 4557 * @param flags 0 or a combination of {link #AUDIOFOCUS_FLAG_DELAY_OK}, 4558 * {@link #AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS} and {@link #AUDIOFOCUS_FLAG_LOCK}. 4559 * <br>Use 0 when not using any flags for the request, which behaves like 4560 * {@link #requestAudioFocus(OnAudioFocusChangeListener, int, int)}, where either audio 4561 * focus is granted immediately, or the grant request fails because the system is in a 4562 * state where focus cannot change (e.g. a phone call). 4563 * @return {@link #AUDIOFOCUS_REQUEST_FAILED}, {@link #AUDIOFOCUS_REQUEST_GRANTED} 4564 * or {@link #AUDIOFOCUS_REQUEST_DELAYED}. 4565 * The return value is never {@link #AUDIOFOCUS_REQUEST_DELAYED} when focus is requested 4566 * without the {@link #AUDIOFOCUS_FLAG_DELAY_OK} flag. 4567 * @throws IllegalArgumentException 4568 */ 4569 @SystemApi 4570 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) requestAudioFocus(OnAudioFocusChangeListener l, @NonNull AudioAttributes requestAttributes, int durationHint, int flags)4571 public int requestAudioFocus(OnAudioFocusChangeListener l, 4572 @NonNull AudioAttributes requestAttributes, 4573 int durationHint, 4574 int flags) throws IllegalArgumentException { 4575 if (flags != (flags & AUDIOFOCUS_FLAGS_APPS)) { 4576 throw new IllegalArgumentException("Invalid flags 0x" 4577 + Integer.toHexString(flags).toUpperCase()); 4578 } 4579 return requestAudioFocus(l, requestAttributes, durationHint, 4580 flags & AUDIOFOCUS_FLAGS_APPS, 4581 null /* no AudioPolicy*/); 4582 } 4583 4584 /** 4585 * @hide 4586 * Request or lock audio focus. 4587 * This method is to be used by system components that have registered an 4588 * {@link android.media.audiopolicy.AudioPolicy} to request audio focus, but also to "lock" it 4589 * so focus granting is temporarily disabled. 4590 * @param l see the description of the same parameter in 4591 * {@link #requestAudioFocus(OnAudioFocusChangeListener, AudioAttributes, int, int)} 4592 * @param requestAttributes non null {@link AudioAttributes} describing the main reason for 4593 * requesting audio focus. 4594 * @param durationHint see the description of the same parameter in 4595 * {@link #requestAudioFocus(OnAudioFocusChangeListener, AudioAttributes, int, int)} 4596 * @param flags 0 or a combination of {link #AUDIOFOCUS_FLAG_DELAY_OK}, 4597 * {@link #AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS}, and {@link #AUDIOFOCUS_FLAG_LOCK}. 4598 * <br>Use 0 when not using any flags for the request, which behaves like 4599 * {@link #requestAudioFocus(OnAudioFocusChangeListener, int, int)}, where either audio 4600 * focus is granted immediately, or the grant request fails because the system is in a 4601 * state where focus cannot change (e.g. a phone call). 4602 * @param ap a registered {@link android.media.audiopolicy.AudioPolicy} instance when locking 4603 * focus, or null. 4604 * @return see the description of the same return value in 4605 * {@link #requestAudioFocus(OnAudioFocusChangeListener, AudioAttributes, int, int)} 4606 * @throws IllegalArgumentException 4607 * @deprecated use {@link #requestAudioFocus(AudioFocusRequest, AudioPolicy)} 4608 */ 4609 @SystemApi 4610 @RequiresPermission(anyOf= { 4611 Manifest.permission.MODIFY_PHONE_STATE, 4612 Manifest.permission.MODIFY_AUDIO_ROUTING 4613 }) requestAudioFocus(OnAudioFocusChangeListener l, @NonNull AudioAttributes requestAttributes, int durationHint, int flags, AudioPolicy ap)4614 public int requestAudioFocus(OnAudioFocusChangeListener l, 4615 @NonNull AudioAttributes requestAttributes, 4616 int durationHint, 4617 int flags, 4618 AudioPolicy ap) throws IllegalArgumentException { 4619 // parameter checking 4620 if (requestAttributes == null) { 4621 throw new IllegalArgumentException("Illegal null AudioAttributes argument"); 4622 } 4623 if (!AudioFocusRequest.isValidFocusGain(durationHint)) { 4624 throw new IllegalArgumentException("Invalid duration hint"); 4625 } 4626 if (flags != (flags & AUDIOFOCUS_FLAGS_SYSTEM)) { 4627 throw new IllegalArgumentException("Illegal flags 0x" 4628 + Integer.toHexString(flags).toUpperCase()); 4629 } 4630 if (((flags & AUDIOFOCUS_FLAG_DELAY_OK) == AUDIOFOCUS_FLAG_DELAY_OK) && (l == null)) { 4631 throw new IllegalArgumentException( 4632 "Illegal null focus listener when flagged as accepting delayed focus grant"); 4633 } 4634 if (((flags & AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS) 4635 == AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS) && (l == null)) { 4636 throw new IllegalArgumentException( 4637 "Illegal null focus listener when flagged as pausing instead of ducking"); 4638 } 4639 if (((flags & AUDIOFOCUS_FLAG_LOCK) == AUDIOFOCUS_FLAG_LOCK) && (ap == null)) { 4640 throw new IllegalArgumentException( 4641 "Illegal null audio policy when locking audio focus"); 4642 } 4643 4644 final AudioFocusRequest afr = new AudioFocusRequest.Builder(durationHint) 4645 .setOnAudioFocusChangeListenerInt(l, null /* no Handler for this legacy API */) 4646 .setAudioAttributes(requestAttributes) 4647 .setAcceptsDelayedFocusGain((flags & AUDIOFOCUS_FLAG_DELAY_OK) 4648 == AUDIOFOCUS_FLAG_DELAY_OK) 4649 .setWillPauseWhenDucked((flags & AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS) 4650 == AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS) 4651 .setLocksFocus((flags & AUDIOFOCUS_FLAG_LOCK) == AUDIOFOCUS_FLAG_LOCK) 4652 .build(); 4653 return requestAudioFocus(afr, ap); 4654 } 4655 4656 /** 4657 * @hide 4658 * Test API to request audio focus for an arbitrary client operating from a (fake) given UID. 4659 * Used to simulate conditions of the test, not the behavior of the focus requester under test. 4660 * @param afr the parameters of the request 4661 * @param clientFakeId the identifier of the AudioManager the client would be requesting from 4662 * @param clientFakeUid the UID of the client, here an arbitrary int, 4663 * doesn't have to be a real UID 4664 * @param clientTargetSdk the target SDK used by the client 4665 * @return return code indicating status of the request 4666 */ 4667 @TestApi 4668 @RequiresPermission("android.permission.QUERY_AUDIO_STATE") requestAudioFocusForTest(@onNull AudioFocusRequest afr, @NonNull String clientFakeId, int clientFakeUid, int clientTargetSdk)4669 public @FocusRequestResult int requestAudioFocusForTest(@NonNull AudioFocusRequest afr, 4670 @NonNull String clientFakeId, int clientFakeUid, int clientTargetSdk) { 4671 Objects.requireNonNull(afr); 4672 Objects.requireNonNull(clientFakeId); 4673 int status; 4674 try { 4675 status = getService().requestAudioFocusForTest(afr.getAudioAttributes(), 4676 afr.getFocusGain(), 4677 mICallBack, 4678 mAudioFocusDispatcher, 4679 clientFakeId, "com.android.test.fakeclient", 4680 afr.getFlags() | AudioManager.AUDIOFOCUS_FLAG_TEST, 4681 clientFakeUid, clientTargetSdk); 4682 } catch (RemoteException e) { 4683 throw e.rethrowFromSystemServer(); 4684 } 4685 if (status != AudioManager.AUDIOFOCUS_REQUEST_WAITING_FOR_EXT_POLICY) { 4686 // default path with no external focus policy 4687 return status; 4688 } 4689 4690 BlockingFocusResultReceiver focusReceiver; 4691 synchronized (mFocusRequestsLock) { 4692 focusReceiver = addClientIdToFocusReceiverLocked(clientFakeId); 4693 } 4694 4695 return handleExternalAudioPolicyWaitIfNeeded(clientFakeId, focusReceiver); 4696 } 4697 4698 /** 4699 * @hide 4700 * Test API to abandon audio focus for an arbitrary client. 4701 * Used to simulate conditions of the test, not the behavior of the focus requester under test. 4702 * @param afr the parameters used for the request 4703 * @param clientFakeId clientFakeId the identifier of the AudioManager from which the client 4704 * would be requesting 4705 * @return return code indicating status of the request 4706 */ 4707 @TestApi 4708 @RequiresPermission("android.permission.QUERY_AUDIO_STATE") abandonAudioFocusForTest(@onNull AudioFocusRequest afr, @NonNull String clientFakeId)4709 public @FocusRequestResult int abandonAudioFocusForTest(@NonNull AudioFocusRequest afr, 4710 @NonNull String clientFakeId) { 4711 Objects.requireNonNull(afr); 4712 Objects.requireNonNull(clientFakeId); 4713 try { 4714 return getService().abandonAudioFocusForTest(mAudioFocusDispatcher, 4715 clientFakeId, afr.getAudioAttributes(), "com.android.test.fakeclient"); 4716 } catch (RemoteException e) { 4717 throw e.rethrowFromSystemServer(); 4718 } 4719 } 4720 4721 /** 4722 * @hide 4723 * Return the duration of the fade out applied when a player of the given AudioAttributes 4724 * is losing audio focus 4725 * @param aa the AudioAttributes of the player losing focus with {@link #AUDIOFOCUS_LOSS} 4726 * @return a duration in ms, 0 indicates no fade out is applied 4727 */ 4728 @TestApi 4729 @RequiresPermission("android.permission.QUERY_AUDIO_STATE") getFadeOutDurationOnFocusLossMillis(@onNull AudioAttributes aa)4730 public @IntRange(from = 0) long getFadeOutDurationOnFocusLossMillis(@NonNull AudioAttributes aa) 4731 { 4732 Objects.requireNonNull(aa); 4733 try { 4734 return getService().getFadeOutDurationOnFocusLossMillis(aa); 4735 } catch (RemoteException e) { 4736 throw e.rethrowFromSystemServer(); 4737 } 4738 } 4739 4740 /** 4741 * @hide 4742 * Request or lock audio focus. 4743 * This method is to be used by system components that have registered an 4744 * {@link android.media.audiopolicy.AudioPolicy} to request audio focus, but also to "lock" it 4745 * so focus granting is temporarily disabled. 4746 * @param afr see the description of the same parameter in 4747 * {@link #requestAudioFocus(AudioFocusRequest)} 4748 * @param ap a registered {@link android.media.audiopolicy.AudioPolicy} instance when locking 4749 * focus, or null. 4750 * @return {@link #AUDIOFOCUS_REQUEST_FAILED}, {@link #AUDIOFOCUS_REQUEST_GRANTED} 4751 * or {@link #AUDIOFOCUS_REQUEST_DELAYED}. 4752 * @throws NullPointerException if the AudioFocusRequest is null 4753 * @throws IllegalArgumentException when trying to lock focus without an AudioPolicy 4754 */ 4755 @SystemApi 4756 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) requestAudioFocus(@onNull AudioFocusRequest afr, @Nullable AudioPolicy ap)4757 public int requestAudioFocus(@NonNull AudioFocusRequest afr, @Nullable AudioPolicy ap) { 4758 if (afr == null) { 4759 throw new NullPointerException("Illegal null AudioFocusRequest"); 4760 } 4761 // this can only be checked now, not during the creation of the AudioFocusRequest instance 4762 if (afr.locksFocus() && ap == null) { 4763 throw new IllegalArgumentException( 4764 "Illegal null audio policy when locking audio focus"); 4765 } 4766 4767 if (hasCustomPolicyVirtualDeviceContext()) { 4768 // If the focus request was made within context associated with VirtualDevice 4769 // configured with custom device policy for audio, bypass audio service focus handling. 4770 // The custom device policy for audio means that audio associated with this device 4771 // is likely rerouted to VirtualAudioDevice and playback on the VirtualAudioDevice 4772 // shouldn't affect non-virtual audio tracks (and vice versa). 4773 return AUDIOFOCUS_REQUEST_GRANTED; 4774 } 4775 4776 registerAudioFocusRequest(afr); 4777 final IAudioService service = getService(); 4778 final int status; 4779 int sdk; 4780 try { 4781 sdk = getContext().getApplicationInfo().targetSdkVersion; 4782 } catch (NullPointerException e) { 4783 // some tests don't have a Context 4784 sdk = Build.VERSION.SDK_INT; 4785 } 4786 4787 final String clientId = getIdForAudioFocusListener(afr.getOnAudioFocusChangeListener()); 4788 BlockingFocusResultReceiver focusReceiver; 4789 synchronized (mFocusRequestsLock) { 4790 4791 try { 4792 // TODO status contains result and generation counter for ext policy 4793 status = service.requestAudioFocus(afr.getAudioAttributes(), 4794 afr.getFocusGain(), mICallBack, 4795 mAudioFocusDispatcher, 4796 clientId, 4797 getContext().getOpPackageName() /* package name */, 4798 getContext().getAttributionTag(), 4799 afr.getFlags(), 4800 ap != null ? ap.cb() : null, 4801 sdk); 4802 } catch (RemoteException e) { 4803 throw e.rethrowFromSystemServer(); 4804 } 4805 if (status != AudioManager.AUDIOFOCUS_REQUEST_WAITING_FOR_EXT_POLICY) { 4806 // default path with no external focus policy 4807 return status; 4808 } 4809 focusReceiver = addClientIdToFocusReceiverLocked(clientId); 4810 } 4811 4812 return handleExternalAudioPolicyWaitIfNeeded(clientId, focusReceiver); 4813 } 4814 4815 @GuardedBy("mFocusRequestsLock") addClientIdToFocusReceiverLocked(String clientId)4816 private BlockingFocusResultReceiver addClientIdToFocusReceiverLocked(String clientId) { 4817 BlockingFocusResultReceiver focusReceiver; 4818 if (mFocusRequestsAwaitingResult == null) { 4819 mFocusRequestsAwaitingResult = 4820 new HashMap<String, BlockingFocusResultReceiver>(1); 4821 } 4822 focusReceiver = new BlockingFocusResultReceiver(clientId); 4823 mFocusRequestsAwaitingResult.put(clientId, focusReceiver); 4824 return focusReceiver; 4825 } 4826 handleExternalAudioPolicyWaitIfNeeded(String clientId, BlockingFocusResultReceiver focusReceiver)4827 private @FocusRequestResult int handleExternalAudioPolicyWaitIfNeeded(String clientId, 4828 BlockingFocusResultReceiver focusReceiver) { 4829 focusReceiver.waitForResult(EXT_FOCUS_POLICY_TIMEOUT_MS); 4830 if (DEBUG && !focusReceiver.receivedResult()) { 4831 Log.e(TAG, "handleExternalAudioPolicyWaitIfNeeded" 4832 + " response from ext policy timed out, denying request"); 4833 } 4834 4835 synchronized (mFocusRequestsLock) { 4836 mFocusRequestsAwaitingResult.remove(clientId); 4837 } 4838 return focusReceiver.requestResult(); 4839 } 4840 4841 // helper class that abstracts out the handling of spurious wakeups in Object.wait() 4842 private static final class SafeWaitObject { 4843 private boolean mQuit = false; 4844 safeNotify()4845 public void safeNotify() { 4846 synchronized (this) { 4847 mQuit = true; 4848 this.notify(); 4849 } 4850 } 4851 safeWait(long millis)4852 public void safeWait(long millis) throws InterruptedException { 4853 final long timeOutTime = java.lang.System.currentTimeMillis() + millis; 4854 synchronized (this) { 4855 while (!mQuit) { 4856 final long timeToWait = timeOutTime - java.lang.System.currentTimeMillis(); 4857 if (timeToWait < 0) { break; } 4858 this.wait(timeToWait); 4859 } 4860 } 4861 } 4862 } 4863 4864 private static final class BlockingFocusResultReceiver { 4865 private final SafeWaitObject mLock = new SafeWaitObject(); 4866 @GuardedBy("mLock") 4867 private boolean mResultReceived = false; 4868 // request denied by default (e.g. timeout) 4869 private int mFocusRequestResult = AudioManager.AUDIOFOCUS_REQUEST_FAILED; 4870 private final String mFocusClientId; 4871 BlockingFocusResultReceiver(String clientId)4872 BlockingFocusResultReceiver(String clientId) { 4873 mFocusClientId = clientId; 4874 } 4875 receivedResult()4876 boolean receivedResult() { return mResultReceived; } requestResult()4877 int requestResult() { return mFocusRequestResult; } 4878 notifyResult(int requestResult)4879 void notifyResult(int requestResult) { 4880 synchronized (mLock) { 4881 mResultReceived = true; 4882 mFocusRequestResult = requestResult; 4883 mLock.safeNotify(); 4884 } 4885 } 4886 waitForResult(long timeOutMs)4887 public void waitForResult(long timeOutMs) { 4888 synchronized (mLock) { 4889 if (mResultReceived) { 4890 // the result was received before waiting 4891 return; 4892 } 4893 try { 4894 mLock.safeWait(timeOutMs); 4895 } catch (InterruptedException e) { } 4896 } 4897 } 4898 } 4899 4900 /** 4901 * @hide 4902 * Used internally by telephony package to request audio focus. Will cause the focus request 4903 * to be associated with the "voice communication" identifier only used in AudioService 4904 * to identify this use case. 4905 * @param streamType use STREAM_RING for focus requests when ringing, VOICE_CALL for 4906 * the establishment of the call 4907 * @param durationHint the type of focus request. AUDIOFOCUS_GAIN_TRANSIENT is recommended so 4908 * media applications resume after a call 4909 */ 4910 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) requestAudioFocusForCall(int streamType, int durationHint)4911 public void requestAudioFocusForCall(int streamType, int durationHint) { 4912 final IAudioService service = getService(); 4913 try { 4914 service.requestAudioFocus(new AudioAttributes.Builder() 4915 .setInternalLegacyStreamType(streamType).build(), 4916 durationHint, mICallBack, null, 4917 AudioSystem.IN_VOICE_COMM_FOCUS_ID, 4918 getContext().getOpPackageName(), 4919 getContext().getAttributionTag(), 4920 AUDIOFOCUS_FLAG_LOCK, 4921 null /* policy token */, 0 /* sdk n/a here*/); 4922 } catch (RemoteException e) { 4923 throw e.rethrowFromSystemServer(); 4924 } 4925 } 4926 4927 /** 4928 * @hide 4929 * Return the volume ramping time for a sound to be played after the given focus request, 4930 * and to play a sound of the given attributes 4931 * @param focusGain 4932 * @param attr 4933 * @return 4934 */ getFocusRampTimeMs(int focusGain, AudioAttributes attr)4935 public int getFocusRampTimeMs(int focusGain, AudioAttributes attr) { 4936 final IAudioService service = getService(); 4937 try { 4938 return service.getFocusRampTimeMs(focusGain, attr); 4939 } catch (RemoteException e) { 4940 throw e.rethrowFromSystemServer(); 4941 } 4942 } 4943 4944 /** 4945 * @hide 4946 * Set the result to the audio focus request received through 4947 * {@link AudioPolicyFocusListener#onAudioFocusRequest(AudioFocusInfo, int)}. 4948 * @param afi the information about the focus requester 4949 * @param requestResult the result to the focus request to be passed to the requester 4950 * @param ap a valid registered {@link AudioPolicy} configured as a focus policy. 4951 */ 4952 @SystemApi 4953 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) setFocusRequestResult(@onNull AudioFocusInfo afi, @FocusRequestResult int requestResult, @NonNull AudioPolicy ap)4954 public void setFocusRequestResult(@NonNull AudioFocusInfo afi, 4955 @FocusRequestResult int requestResult, @NonNull AudioPolicy ap) { 4956 if (afi == null) { 4957 throw new IllegalArgumentException("Illegal null AudioFocusInfo"); 4958 } 4959 if (ap == null) { 4960 throw new IllegalArgumentException("Illegal null AudioPolicy"); 4961 } 4962 final IAudioService service = getService(); 4963 try { 4964 service.setFocusRequestResultFromExtPolicy(afi, requestResult, ap.cb()); 4965 } catch (RemoteException e) { 4966 throw e.rethrowFromSystemServer(); 4967 } 4968 } 4969 4970 /** 4971 * @hide 4972 * Notifies an application with a focus listener of gain or loss of audio focus. 4973 * This method can only be used by owners of an {@link AudioPolicy} configured with 4974 * {@link AudioPolicy.Builder#setIsAudioFocusPolicy(boolean)} set to true. 4975 * @param afi the recipient of the focus change, that has previously requested audio focus, and 4976 * that was received by the {@code AudioPolicy} through 4977 * {@link AudioPolicy.AudioPolicyFocusListener#onAudioFocusRequest(AudioFocusInfo, int)}. 4978 * @param focusChange one of focus gain types ({@link #AUDIOFOCUS_GAIN}, 4979 * {@link #AUDIOFOCUS_GAIN_TRANSIENT}, {@link #AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK} or 4980 * {@link #AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE}) 4981 * or one of the focus loss types ({@link AudioManager#AUDIOFOCUS_LOSS}, 4982 * {@link AudioManager#AUDIOFOCUS_LOSS_TRANSIENT}, 4983 * or {@link AudioManager#AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK}). 4984 * <br>For the focus gain, the change type should be the same as the app requested. 4985 * @param ap a valid registered {@link AudioPolicy} configured as a focus policy. 4986 * @return {@link #AUDIOFOCUS_REQUEST_GRANTED} if the dispatch was successfully sent, or 4987 * {@link #AUDIOFOCUS_REQUEST_FAILED} if the focus client didn't have a listener, or 4988 * if there was an error sending the request. 4989 * @throws NullPointerException if the {@link AudioFocusInfo} or {@link AudioPolicy} are null. 4990 */ 4991 @SystemApi 4992 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) dispatchAudioFocusChange(@onNull AudioFocusInfo afi, int focusChange, @NonNull AudioPolicy ap)4993 public int dispatchAudioFocusChange(@NonNull AudioFocusInfo afi, int focusChange, 4994 @NonNull AudioPolicy ap) { 4995 if (afi == null) { 4996 throw new NullPointerException("Illegal null AudioFocusInfo"); 4997 } 4998 if (ap == null) { 4999 throw new NullPointerException("Illegal null AudioPolicy"); 5000 } 5001 final IAudioService service = getService(); 5002 try { 5003 return service.dispatchFocusChange(afi, focusChange, ap.cb()); 5004 } catch (RemoteException e) { 5005 throw e.rethrowFromSystemServer(); 5006 } 5007 } 5008 5009 /** 5010 * @hide 5011 * Used internally by telephony package to abandon audio focus, typically after a call or 5012 * when ringing ends and the call is rejected or not answered. 5013 * Should match one or more calls to {@link #requestAudioFocusForCall(int, int)}. 5014 */ 5015 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) abandonAudioFocusForCall()5016 public void abandonAudioFocusForCall() { 5017 final IAudioService service = getService(); 5018 try { 5019 service.abandonAudioFocus(null, AudioSystem.IN_VOICE_COMM_FOCUS_ID, 5020 null /*AudioAttributes, legacy behavior*/, getContext().getOpPackageName()); 5021 } catch (RemoteException e) { 5022 throw e.rethrowFromSystemServer(); 5023 } 5024 } 5025 5026 /** 5027 * Abandon audio focus. Causes the previous focus owner, if any, to receive focus. 5028 * @param l the listener with which focus was requested. 5029 * @return {@link #AUDIOFOCUS_REQUEST_FAILED} or {@link #AUDIOFOCUS_REQUEST_GRANTED} 5030 * @deprecated use {@link #abandonAudioFocusRequest(AudioFocusRequest)} 5031 */ abandonAudioFocus(OnAudioFocusChangeListener l)5032 public int abandonAudioFocus(OnAudioFocusChangeListener l) { 5033 return abandonAudioFocus(l, null /*AudioAttributes, legacy behavior*/); 5034 } 5035 5036 /** 5037 * @hide 5038 * Abandon audio focus. Causes the previous focus owner, if any, to receive focus. 5039 * @param l the listener with which focus was requested. 5040 * @param aa the {@link AudioAttributes} with which audio focus was requested 5041 * @return {@link #AUDIOFOCUS_REQUEST_FAILED} or {@link #AUDIOFOCUS_REQUEST_GRANTED} 5042 * @deprecated use {@link #abandonAudioFocusRequest(AudioFocusRequest)} 5043 */ 5044 @SystemApi 5045 @SuppressLint("RequiresPermission") // no permission enforcement, but only "undoes" what would 5046 // have been done by a matching requestAudioFocus abandonAudioFocus(OnAudioFocusChangeListener l, AudioAttributes aa)5047 public int abandonAudioFocus(OnAudioFocusChangeListener l, AudioAttributes aa) { 5048 if (hasCustomPolicyVirtualDeviceContext()) { 5049 // If this AudioManager instance is running within VirtualDevice context configured 5050 // with custom device policy for audio, the audio focus handling is bypassed. 5051 return AUDIOFOCUS_REQUEST_GRANTED; 5052 } 5053 unregisterAudioFocusRequest(l); 5054 final IAudioService service = getService(); 5055 try { 5056 return service.abandonAudioFocus(mAudioFocusDispatcher, 5057 getIdForAudioFocusListener(l), aa, getContext().getOpPackageName()); 5058 } catch (RemoteException e) { 5059 throw e.rethrowFromSystemServer(); 5060 } 5061 } 5062 5063 //==================================================================== 5064 // Remote Control 5065 /** 5066 * Register a component to be the sole receiver of MEDIA_BUTTON intents. 5067 * @param eventReceiver identifier of a {@link android.content.BroadcastReceiver} 5068 * that will receive the media button intent. This broadcast receiver must be declared 5069 * in the application manifest. The package of the component must match that of 5070 * the context you're registering from. 5071 * @deprecated Use {@link MediaSession#setMediaButtonReceiver(PendingIntent)} instead. 5072 */ 5073 @Deprecated registerMediaButtonEventReceiver(ComponentName eventReceiver)5074 public void registerMediaButtonEventReceiver(ComponentName eventReceiver) { 5075 if (eventReceiver == null) { 5076 return; 5077 } 5078 if (!eventReceiver.getPackageName().equals(getContext().getPackageName())) { 5079 Log.e(TAG, "registerMediaButtonEventReceiver() error: " + 5080 "receiver and context package names don't match"); 5081 return; 5082 } 5083 // construct a PendingIntent for the media button and register it 5084 Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON); 5085 // the associated intent will be handled by the component being registered 5086 mediaButtonIntent.setComponent(eventReceiver); 5087 PendingIntent pi = PendingIntent.getBroadcast(getContext(), 5088 0/*requestCode, ignored*/, mediaButtonIntent, 5089 PendingIntent.FLAG_IMMUTABLE); 5090 registerMediaButtonIntent(pi, eventReceiver); 5091 } 5092 5093 /** 5094 * Register a component to be the sole receiver of MEDIA_BUTTON intents. This is like 5095 * {@link #registerMediaButtonEventReceiver(android.content.ComponentName)}, but allows 5096 * the buttons to go to any PendingIntent. Note that you should only use this form if 5097 * you know you will continue running for the full time until unregistering the 5098 * PendingIntent. 5099 * @param eventReceiver target that will receive media button intents. The PendingIntent 5100 * will be sent an {@link Intent#ACTION_MEDIA_BUTTON} event when a media button action 5101 * occurs, with {@link Intent#EXTRA_KEY_EVENT} added and holding the key code of the 5102 * media button that was pressed. 5103 * @deprecated Use {@link MediaSession#setMediaButtonReceiver(PendingIntent)} instead. 5104 */ 5105 @Deprecated registerMediaButtonEventReceiver(PendingIntent eventReceiver)5106 public void registerMediaButtonEventReceiver(PendingIntent eventReceiver) { 5107 if (eventReceiver == null) { 5108 return; 5109 } 5110 registerMediaButtonIntent(eventReceiver, null); 5111 } 5112 5113 /** 5114 * @hide 5115 * no-op if (pi == null) or (eventReceiver == null) 5116 */ registerMediaButtonIntent(PendingIntent pi, ComponentName eventReceiver)5117 public void registerMediaButtonIntent(PendingIntent pi, ComponentName eventReceiver) { 5118 if (pi == null) { 5119 Log.e(TAG, "Cannot call registerMediaButtonIntent() with a null parameter"); 5120 return; 5121 } 5122 MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(getContext()); 5123 helper.addMediaButtonListener(pi, eventReceiver, getContext()); 5124 } 5125 5126 /** 5127 * Unregister the receiver of MEDIA_BUTTON intents. 5128 * @param eventReceiver identifier of a {@link android.content.BroadcastReceiver} 5129 * that was registered with {@link #registerMediaButtonEventReceiver(ComponentName)}. 5130 * @deprecated Use {@link MediaSession} instead. 5131 */ 5132 @Deprecated unregisterMediaButtonEventReceiver(ComponentName eventReceiver)5133 public void unregisterMediaButtonEventReceiver(ComponentName eventReceiver) { 5134 if (eventReceiver == null) { 5135 return; 5136 } 5137 // construct a PendingIntent for the media button and unregister it 5138 Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON); 5139 // the associated intent will be handled by the component being registered 5140 mediaButtonIntent.setComponent(eventReceiver); 5141 PendingIntent pi = PendingIntent.getBroadcast(getContext(), 5142 0/*requestCode, ignored*/, mediaButtonIntent, 5143 PendingIntent.FLAG_IMMUTABLE); 5144 unregisterMediaButtonIntent(pi); 5145 } 5146 5147 /** 5148 * Unregister the receiver of MEDIA_BUTTON intents. 5149 * @param eventReceiver same PendingIntent that was registed with 5150 * {@link #registerMediaButtonEventReceiver(PendingIntent)}. 5151 * @deprecated Use {@link MediaSession} instead. 5152 */ 5153 @Deprecated unregisterMediaButtonEventReceiver(PendingIntent eventReceiver)5154 public void unregisterMediaButtonEventReceiver(PendingIntent eventReceiver) { 5155 if (eventReceiver == null) { 5156 return; 5157 } 5158 unregisterMediaButtonIntent(eventReceiver); 5159 } 5160 5161 /** 5162 * @hide 5163 */ unregisterMediaButtonIntent(PendingIntent pi)5164 public void unregisterMediaButtonIntent(PendingIntent pi) { 5165 MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(getContext()); 5166 helper.removeMediaButtonListener(pi); 5167 } 5168 5169 /** 5170 * Registers the remote control client for providing information to display on the remote 5171 * controls. 5172 * @param rcClient The remote control client from which remote controls will receive 5173 * information to display. 5174 * @see RemoteControlClient 5175 * @deprecated Use {@link MediaSession} instead. 5176 */ 5177 @Deprecated registerRemoteControlClient(RemoteControlClient rcClient)5178 public void registerRemoteControlClient(RemoteControlClient rcClient) { 5179 if ((rcClient == null) || (rcClient.getRcMediaIntent() == null)) { 5180 return; 5181 } 5182 rcClient.registerWithSession(MediaSessionLegacyHelper.getHelper(getContext())); 5183 } 5184 5185 /** 5186 * Unregisters the remote control client that was providing information to display on the 5187 * remote controls. 5188 * @param rcClient The remote control client to unregister. 5189 * @see #registerRemoteControlClient(RemoteControlClient) 5190 * @deprecated Use {@link MediaSession} instead. 5191 */ 5192 @Deprecated unregisterRemoteControlClient(RemoteControlClient rcClient)5193 public void unregisterRemoteControlClient(RemoteControlClient rcClient) { 5194 if ((rcClient == null) || (rcClient.getRcMediaIntent() == null)) { 5195 return; 5196 } 5197 rcClient.unregisterWithSession(MediaSessionLegacyHelper.getHelper(getContext())); 5198 } 5199 5200 /** 5201 * Registers a {@link RemoteController} instance for it to receive media 5202 * metadata updates and playback state information from applications using 5203 * {@link RemoteControlClient}, and control their playback. 5204 * <p> 5205 * Registration requires the {@link RemoteController.OnClientUpdateListener} listener to be 5206 * one of the enabled notification listeners (see 5207 * {@link android.service.notification.NotificationListenerService}). 5208 * 5209 * @param rctlr the object to register. 5210 * @return true if the {@link RemoteController} was successfully registered, 5211 * false if an error occurred, due to an internal system error, or 5212 * insufficient permissions. 5213 * @deprecated Use 5214 * {@link MediaSessionManager#addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, ComponentName)} 5215 * and {@link MediaController} instead. 5216 */ 5217 @Deprecated registerRemoteController(RemoteController rctlr)5218 public boolean registerRemoteController(RemoteController rctlr) { 5219 if (rctlr == null) { 5220 return false; 5221 } 5222 rctlr.startListeningToSessions(); 5223 return true; 5224 } 5225 5226 /** 5227 * Unregisters a {@link RemoteController}, causing it to no longer receive 5228 * media metadata and playback state information, and no longer be capable 5229 * of controlling playback. 5230 * 5231 * @param rctlr the object to unregister. 5232 * @deprecated Use 5233 * {@link MediaSessionManager#removeOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener)} 5234 * instead. 5235 */ 5236 @Deprecated unregisterRemoteController(RemoteController rctlr)5237 public void unregisterRemoteController(RemoteController rctlr) { 5238 if (rctlr == null) { 5239 return; 5240 } 5241 rctlr.stopListeningToSessions(); 5242 } 5243 5244 5245 //==================================================================== 5246 // Audio policy 5247 /** 5248 * @hide 5249 * Register the given {@link AudioPolicy}. 5250 * This call is synchronous and blocks until the registration process successfully completed 5251 * or failed to complete. 5252 * @param policy the non-null {@link AudioPolicy} to register. 5253 * @return {@link #ERROR} if there was an error communicating with the registration service 5254 * or if the user doesn't have the required 5255 * {@link Manifest.permission#MODIFY_AUDIO_ROUTING} permission, 5256 * {@link #SUCCESS} otherwise. 5257 */ 5258 @SystemApi 5259 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) registerAudioPolicy(@onNull AudioPolicy policy)5260 public int registerAudioPolicy(@NonNull AudioPolicy policy) { 5261 return registerAudioPolicyStatic(policy); 5262 } 5263 registerAudioPolicyStatic(@onNull AudioPolicy policy)5264 static int registerAudioPolicyStatic(@NonNull AudioPolicy policy) { 5265 if (policy == null) { 5266 throw new IllegalArgumentException("Illegal null AudioPolicy argument"); 5267 } 5268 final IAudioService service = getService(); 5269 try { 5270 MediaProjection projection = policy.getMediaProjection(); 5271 String regId = service.registerAudioPolicy(policy.getConfig(), policy.cb(), 5272 policy.hasFocusListener(), policy.isFocusPolicy(), policy.isTestFocusPolicy(), 5273 policy.isVolumeController(), 5274 projection == null ? null : projection.getProjection()); 5275 if (regId == null) { 5276 return ERROR; 5277 } else { 5278 policy.setRegistration(regId); 5279 } 5280 // successful registration 5281 } catch (RemoteException e) { 5282 throw e.rethrowFromSystemServer(); 5283 } 5284 return SUCCESS; 5285 } 5286 5287 /** 5288 * @hide 5289 * Unregisters an {@link AudioPolicy} asynchronously. 5290 * @param policy the non-null {@link AudioPolicy} to unregister. 5291 */ 5292 @SystemApi 5293 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) unregisterAudioPolicyAsync(@onNull AudioPolicy policy)5294 public void unregisterAudioPolicyAsync(@NonNull AudioPolicy policy) { 5295 unregisterAudioPolicyAsyncStatic(policy); 5296 } 5297 unregisterAudioPolicyAsyncStatic(@onNull AudioPolicy policy)5298 static void unregisterAudioPolicyAsyncStatic(@NonNull AudioPolicy policy) { 5299 if (policy == null) { 5300 throw new IllegalArgumentException("Illegal null AudioPolicy argument"); 5301 } 5302 final IAudioService service = getService(); 5303 try { 5304 service.unregisterAudioPolicyAsync(policy.cb()); 5305 policy.reset(); 5306 } catch (RemoteException e) { 5307 throw e.rethrowFromSystemServer(); 5308 } 5309 } 5310 5311 /** 5312 * @hide 5313 * Unregisters an {@link AudioPolicy} synchronously. 5314 * This method also invalidates all {@link AudioRecord} and {@link AudioTrack} objects 5315 * associated with mixes of this policy. 5316 * @param policy the non-null {@link AudioPolicy} to unregister. 5317 */ 5318 @SystemApi 5319 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) unregisterAudioPolicy(@onNull AudioPolicy policy)5320 public void unregisterAudioPolicy(@NonNull AudioPolicy policy) { 5321 Preconditions.checkNotNull(policy, "Illegal null AudioPolicy argument"); 5322 final IAudioService service = getService(); 5323 try { 5324 policy.invalidateCaptorsAndInjectors(); 5325 service.unregisterAudioPolicy(policy.cb()); 5326 policy.reset(); 5327 } catch (RemoteException e) { 5328 throw e.rethrowFromSystemServer(); 5329 } 5330 } 5331 5332 /** 5333 * @hide 5334 * @return true if an AudioPolicy was previously registered 5335 */ 5336 @TestApi hasRegisteredDynamicPolicy()5337 public boolean hasRegisteredDynamicPolicy() { 5338 final IAudioService service = getService(); 5339 try { 5340 return service.hasRegisteredDynamicPolicy(); 5341 } catch (RemoteException e) { 5342 throw e.rethrowFromSystemServer(); 5343 } 5344 } 5345 5346 //==================================================================== 5347 // Notification of playback activity & playback configuration 5348 /** 5349 * Interface for receiving update notifications about the playback activity on the system. 5350 * Extend this abstract class and register it with 5351 * {@link AudioManager#registerAudioPlaybackCallback(AudioPlaybackCallback, Handler)} 5352 * to be notified. 5353 * Use {@link AudioManager#getActivePlaybackConfigurations()} to query the current 5354 * configuration. 5355 * @see AudioPlaybackConfiguration 5356 */ 5357 public static abstract class AudioPlaybackCallback { 5358 /** 5359 * Called whenever the playback activity and configuration has changed. 5360 * @param configs list containing the results of 5361 * {@link AudioManager#getActivePlaybackConfigurations()}. 5362 */ onPlaybackConfigChanged(List<AudioPlaybackConfiguration> configs)5363 public void onPlaybackConfigChanged(List<AudioPlaybackConfiguration> configs) {} 5364 } 5365 5366 private static class AudioPlaybackCallbackInfo { 5367 final AudioPlaybackCallback mCb; 5368 final Handler mHandler; AudioPlaybackCallbackInfo(AudioPlaybackCallback cb, Handler handler)5369 AudioPlaybackCallbackInfo(AudioPlaybackCallback cb, Handler handler) { 5370 mCb = cb; 5371 mHandler = handler; 5372 } 5373 } 5374 5375 private final static class PlaybackConfigChangeCallbackData { 5376 final AudioPlaybackCallback mCb; 5377 final List<AudioPlaybackConfiguration> mConfigs; 5378 PlaybackConfigChangeCallbackData(AudioPlaybackCallback cb, List<AudioPlaybackConfiguration> configs)5379 PlaybackConfigChangeCallbackData(AudioPlaybackCallback cb, 5380 List<AudioPlaybackConfiguration> configs) { 5381 mCb = cb; 5382 mConfigs = configs; 5383 } 5384 } 5385 5386 /** 5387 * Register a callback to be notified of audio playback changes through 5388 * {@link AudioPlaybackCallback} 5389 * @param cb non-null callback to register 5390 * @param handler the {@link Handler} object for the thread on which to execute 5391 * the callback. If <code>null</code>, the {@link Handler} associated with the main 5392 * {@link Looper} will be used. 5393 */ registerAudioPlaybackCallback(@onNull AudioPlaybackCallback cb, @Nullable Handler handler)5394 public void registerAudioPlaybackCallback(@NonNull AudioPlaybackCallback cb, 5395 @Nullable Handler handler) 5396 { 5397 if (cb == null) { 5398 throw new IllegalArgumentException("Illegal null AudioPlaybackCallback argument"); 5399 } 5400 5401 synchronized(mPlaybackCallbackLock) { 5402 // lazy initialization of the list of playback callbacks 5403 if (mPlaybackCallbackList == null) { 5404 mPlaybackCallbackList = new ArrayList<AudioPlaybackCallbackInfo>(); 5405 } 5406 final int oldCbCount = mPlaybackCallbackList.size(); 5407 if (!hasPlaybackCallback_sync(cb)) { 5408 mPlaybackCallbackList.add(new AudioPlaybackCallbackInfo(cb, 5409 new ServiceEventHandlerDelegate(handler).getHandler())); 5410 final int newCbCount = mPlaybackCallbackList.size(); 5411 if ((oldCbCount == 0) && (newCbCount > 0)) { 5412 // register binder for callbacks 5413 try { 5414 getService().registerPlaybackCallback(mPlayCb); 5415 } catch (RemoteException e) { 5416 throw e.rethrowFromSystemServer(); 5417 } 5418 } 5419 } else { 5420 Log.w(TAG, "attempt to call registerAudioPlaybackCallback() on a previously" 5421 + "registered callback"); 5422 } 5423 } 5424 } 5425 5426 /** 5427 * Unregister an audio playback callback previously registered with 5428 * {@link #registerAudioPlaybackCallback(AudioPlaybackCallback, Handler)}. 5429 * @param cb non-null callback to unregister 5430 */ unregisterAudioPlaybackCallback(@onNull AudioPlaybackCallback cb)5431 public void unregisterAudioPlaybackCallback(@NonNull AudioPlaybackCallback cb) { 5432 if (cb == null) { 5433 throw new IllegalArgumentException("Illegal null AudioPlaybackCallback argument"); 5434 } 5435 synchronized(mPlaybackCallbackLock) { 5436 if (mPlaybackCallbackList == null) { 5437 Log.w(TAG, "attempt to call unregisterAudioPlaybackCallback() on a callback" 5438 + " that was never registered"); 5439 return; 5440 } 5441 final int oldCbCount = mPlaybackCallbackList.size(); 5442 if (removePlaybackCallback_sync(cb)) { 5443 final int newCbCount = mPlaybackCallbackList.size(); 5444 if ((oldCbCount > 0) && (newCbCount == 0)) { 5445 // unregister binder for callbacks 5446 try { 5447 getService().unregisterPlaybackCallback(mPlayCb); 5448 } catch (RemoteException e) { 5449 throw e.rethrowFromSystemServer(); 5450 } 5451 } 5452 } else { 5453 Log.w(TAG, "attempt to call unregisterAudioPlaybackCallback() on a callback" 5454 + " already unregistered or never registered"); 5455 } 5456 } 5457 } 5458 5459 /** 5460 * Returns the current active audio playback configurations of the device 5461 * @return a non-null list of playback configurations. An empty list indicates there is no 5462 * playback active when queried. 5463 * @see AudioPlaybackConfiguration 5464 */ getActivePlaybackConfigurations()5465 public @NonNull List<AudioPlaybackConfiguration> getActivePlaybackConfigurations() { 5466 final IAudioService service = getService(); 5467 try { 5468 return service.getActivePlaybackConfigurations(); 5469 } catch (RemoteException e) { 5470 throw e.rethrowFromSystemServer(); 5471 } 5472 } 5473 5474 /** 5475 * All operations on this list are sync'd on mPlaybackCallbackLock. 5476 * List is lazy-initialized in 5477 * {@link #registerAudioPlaybackCallback(AudioPlaybackCallback, Handler)}. 5478 * List can be null. 5479 */ 5480 private List<AudioPlaybackCallbackInfo> mPlaybackCallbackList; 5481 private final Object mPlaybackCallbackLock = new Object(); 5482 5483 /** 5484 * Must be called synchronized on mPlaybackCallbackLock 5485 */ hasPlaybackCallback_sync(@onNull AudioPlaybackCallback cb)5486 private boolean hasPlaybackCallback_sync(@NonNull AudioPlaybackCallback cb) { 5487 if (mPlaybackCallbackList != null) { 5488 for (int i=0 ; i < mPlaybackCallbackList.size() ; i++) { 5489 if (cb.equals(mPlaybackCallbackList.get(i).mCb)) { 5490 return true; 5491 } 5492 } 5493 } 5494 return false; 5495 } 5496 5497 /** 5498 * Must be called synchronized on mPlaybackCallbackLock 5499 */ removePlaybackCallback_sync(@onNull AudioPlaybackCallback cb)5500 private boolean removePlaybackCallback_sync(@NonNull AudioPlaybackCallback cb) { 5501 if (mPlaybackCallbackList != null) { 5502 for (int i=0 ; i < mPlaybackCallbackList.size() ; i++) { 5503 if (cb.equals(mPlaybackCallbackList.get(i).mCb)) { 5504 mPlaybackCallbackList.remove(i); 5505 return true; 5506 } 5507 } 5508 } 5509 return false; 5510 } 5511 5512 private final IPlaybackConfigDispatcher mPlayCb = new IPlaybackConfigDispatcher.Stub() { 5513 @Override 5514 public void dispatchPlaybackConfigChange(List<AudioPlaybackConfiguration> configs, 5515 boolean flush) { 5516 if (flush) { 5517 Binder.flushPendingCommands(); 5518 } 5519 synchronized(mPlaybackCallbackLock) { 5520 if (mPlaybackCallbackList != null) { 5521 for (int i=0 ; i < mPlaybackCallbackList.size() ; i++) { 5522 final AudioPlaybackCallbackInfo arci = mPlaybackCallbackList.get(i); 5523 if (arci.mHandler != null) { 5524 final Message m = arci.mHandler.obtainMessage( 5525 MSSG_PLAYBACK_CONFIG_CHANGE/*what*/, 5526 new PlaybackConfigChangeCallbackData(arci.mCb, configs)/*obj*/); 5527 arci.mHandler.sendMessage(m); 5528 } 5529 } 5530 } 5531 } 5532 } 5533 5534 }; 5535 5536 //==================================================================== 5537 // Notification of recording activity & recording configuration 5538 /** 5539 * Interface for receiving update notifications about the recording configuration. Extend 5540 * this abstract class and register it with 5541 * {@link AudioManager#registerAudioRecordingCallback(AudioRecordingCallback, Handler)} 5542 * to be notified. 5543 * Use {@link AudioManager#getActiveRecordingConfigurations()} to query the current 5544 * configuration. 5545 * @see AudioRecordingConfiguration 5546 */ 5547 public static abstract class AudioRecordingCallback { 5548 /** 5549 * Called whenever the device recording configuration has changed. 5550 * @param configs list containing the results of 5551 * {@link AudioManager#getActiveRecordingConfigurations()}. 5552 */ onRecordingConfigChanged(List<AudioRecordingConfiguration> configs)5553 public void onRecordingConfigChanged(List<AudioRecordingConfiguration> configs) {} 5554 } 5555 5556 private static class AudioRecordingCallbackInfo { 5557 final AudioRecordingCallback mCb; 5558 final Handler mHandler; AudioRecordingCallbackInfo(AudioRecordingCallback cb, Handler handler)5559 AudioRecordingCallbackInfo(AudioRecordingCallback cb, Handler handler) { 5560 mCb = cb; 5561 mHandler = handler; 5562 } 5563 } 5564 5565 private final static class RecordConfigChangeCallbackData { 5566 final AudioRecordingCallback mCb; 5567 final List<AudioRecordingConfiguration> mConfigs; 5568 RecordConfigChangeCallbackData(AudioRecordingCallback cb, List<AudioRecordingConfiguration> configs)5569 RecordConfigChangeCallbackData(AudioRecordingCallback cb, 5570 List<AudioRecordingConfiguration> configs) { 5571 mCb = cb; 5572 mConfigs = configs; 5573 } 5574 } 5575 5576 /** 5577 * Register a callback to be notified of audio recording changes through 5578 * {@link AudioRecordingCallback} 5579 * @param cb non-null callback to register 5580 * @param handler the {@link Handler} object for the thread on which to execute 5581 * the callback. If <code>null</code>, the {@link Handler} associated with the main 5582 * {@link Looper} will be used. 5583 */ registerAudioRecordingCallback(@onNull AudioRecordingCallback cb, @Nullable Handler handler)5584 public void registerAudioRecordingCallback(@NonNull AudioRecordingCallback cb, 5585 @Nullable Handler handler) 5586 { 5587 if (cb == null) { 5588 throw new IllegalArgumentException("Illegal null AudioRecordingCallback argument"); 5589 } 5590 5591 synchronized(mRecordCallbackLock) { 5592 // lazy initialization of the list of recording callbacks 5593 if (mRecordCallbackList == null) { 5594 mRecordCallbackList = new ArrayList<AudioRecordingCallbackInfo>(); 5595 } 5596 final int oldCbCount = mRecordCallbackList.size(); 5597 if (!hasRecordCallback_sync(cb)) { 5598 mRecordCallbackList.add(new AudioRecordingCallbackInfo(cb, 5599 new ServiceEventHandlerDelegate(handler).getHandler())); 5600 final int newCbCount = mRecordCallbackList.size(); 5601 if ((oldCbCount == 0) && (newCbCount > 0)) { 5602 // register binder for callbacks 5603 final IAudioService service = getService(); 5604 try { 5605 service.registerRecordingCallback(mRecCb); 5606 } catch (RemoteException e) { 5607 throw e.rethrowFromSystemServer(); 5608 } 5609 } 5610 } else { 5611 Log.w(TAG, "attempt to call registerAudioRecordingCallback() on a previously" 5612 + "registered callback"); 5613 } 5614 } 5615 } 5616 5617 /** 5618 * Unregister an audio recording callback previously registered with 5619 * {@link #registerAudioRecordingCallback(AudioRecordingCallback, Handler)}. 5620 * @param cb non-null callback to unregister 5621 */ unregisterAudioRecordingCallback(@onNull AudioRecordingCallback cb)5622 public void unregisterAudioRecordingCallback(@NonNull AudioRecordingCallback cb) { 5623 if (cb == null) { 5624 throw new IllegalArgumentException("Illegal null AudioRecordingCallback argument"); 5625 } 5626 synchronized(mRecordCallbackLock) { 5627 if (mRecordCallbackList == null) { 5628 return; 5629 } 5630 final int oldCbCount = mRecordCallbackList.size(); 5631 if (removeRecordCallback_sync(cb)) { 5632 final int newCbCount = mRecordCallbackList.size(); 5633 if ((oldCbCount > 0) && (newCbCount == 0)) { 5634 // unregister binder for callbacks 5635 final IAudioService service = getService(); 5636 try { 5637 service.unregisterRecordingCallback(mRecCb); 5638 } catch (RemoteException e) { 5639 throw e.rethrowFromSystemServer(); 5640 } 5641 } 5642 } else { 5643 Log.w(TAG, "attempt to call unregisterAudioRecordingCallback() on a callback" 5644 + " already unregistered or never registered"); 5645 } 5646 } 5647 } 5648 5649 /** 5650 * Returns the current active audio recording configurations of the device. 5651 * @return a non-null list of recording configurations. An empty list indicates there is 5652 * no recording active when queried. 5653 * @see AudioRecordingConfiguration 5654 */ getActiveRecordingConfigurations()5655 public @NonNull List<AudioRecordingConfiguration> getActiveRecordingConfigurations() { 5656 final IAudioService service = getService(); 5657 try { 5658 return service.getActiveRecordingConfigurations(); 5659 } catch (RemoteException e) { 5660 throw e.rethrowFromSystemServer(); 5661 } 5662 } 5663 5664 /** 5665 * constants for the recording events, to keep in sync 5666 * with frameworks/av/include/media/AudioPolicy.h 5667 */ 5668 /** @hide */ 5669 public static final int RECORD_CONFIG_EVENT_NONE = -1; 5670 /** @hide */ 5671 public static final int RECORD_CONFIG_EVENT_START = 0; 5672 /** @hide */ 5673 public static final int RECORD_CONFIG_EVENT_STOP = 1; 5674 /** @hide */ 5675 public static final int RECORD_CONFIG_EVENT_UPDATE = 2; 5676 /** @hide */ 5677 public static final int RECORD_CONFIG_EVENT_RELEASE = 3; 5678 /** 5679 * keep in sync with frameworks/native/include/audiomanager/AudioManager.h 5680 */ 5681 /** @hide */ 5682 public static final int RECORD_RIID_INVALID = -1; 5683 /** @hide */ 5684 public static final int RECORDER_STATE_STARTED = 0; 5685 /** @hide */ 5686 public static final int RECORDER_STATE_STOPPED = 1; 5687 5688 /** 5689 * All operations on this list are sync'd on mRecordCallbackLock. 5690 * List is lazy-initialized in 5691 * {@link #registerAudioRecordingCallback(AudioRecordingCallback, Handler)}. 5692 * List can be null. 5693 */ 5694 private List<AudioRecordingCallbackInfo> mRecordCallbackList; 5695 private final Object mRecordCallbackLock = new Object(); 5696 5697 /** 5698 * Must be called synchronized on mRecordCallbackLock 5699 */ hasRecordCallback_sync(@onNull AudioRecordingCallback cb)5700 private boolean hasRecordCallback_sync(@NonNull AudioRecordingCallback cb) { 5701 if (mRecordCallbackList != null) { 5702 for (int i=0 ; i < mRecordCallbackList.size() ; i++) { 5703 if (cb.equals(mRecordCallbackList.get(i).mCb)) { 5704 return true; 5705 } 5706 } 5707 } 5708 return false; 5709 } 5710 5711 /** 5712 * Must be called synchronized on mRecordCallbackLock 5713 */ removeRecordCallback_sync(@onNull AudioRecordingCallback cb)5714 private boolean removeRecordCallback_sync(@NonNull AudioRecordingCallback cb) { 5715 if (mRecordCallbackList != null) { 5716 for (int i=0 ; i < mRecordCallbackList.size() ; i++) { 5717 if (cb.equals(mRecordCallbackList.get(i).mCb)) { 5718 mRecordCallbackList.remove(i); 5719 return true; 5720 } 5721 } 5722 } 5723 return false; 5724 } 5725 5726 private final IRecordingConfigDispatcher mRecCb = new IRecordingConfigDispatcher.Stub() { 5727 @Override 5728 public void dispatchRecordingConfigChange(List<AudioRecordingConfiguration> configs) { 5729 synchronized(mRecordCallbackLock) { 5730 if (mRecordCallbackList != null) { 5731 for (int i=0 ; i < mRecordCallbackList.size() ; i++) { 5732 final AudioRecordingCallbackInfo arci = mRecordCallbackList.get(i); 5733 if (arci.mHandler != null) { 5734 final Message m = arci.mHandler.obtainMessage( 5735 MSSG_RECORDING_CONFIG_CHANGE/*what*/, 5736 new RecordConfigChangeCallbackData(arci.mCb, configs)/*obj*/); 5737 arci.mHandler.sendMessage(m); 5738 } 5739 } 5740 } 5741 } 5742 } 5743 5744 }; 5745 5746 //===================================================================== 5747 5748 /** 5749 * @hide 5750 * Reload audio settings. This method is called by Settings backup 5751 * agent when audio settings are restored and causes the AudioService 5752 * to read and apply restored settings. 5753 */ 5754 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) reloadAudioSettings()5755 public void reloadAudioSettings() { 5756 final IAudioService service = getService(); 5757 try { 5758 service.reloadAudioSettings(); 5759 } catch (RemoteException e) { 5760 throw e.rethrowFromSystemServer(); 5761 } 5762 } 5763 5764 /** 5765 * {@hide} 5766 */ 5767 private final IBinder mICallBack = new Binder(); 5768 5769 /** 5770 * Checks whether the phone is in silent mode, with or without vibrate. 5771 * 5772 * @return true if phone is in silent mode, with or without vibrate. 5773 * 5774 * @see #getRingerMode() 5775 * 5776 * @hide pending API Council approval 5777 */ 5778 @UnsupportedAppUsage isSilentMode()5779 public boolean isSilentMode() { 5780 int ringerMode = getRingerMode(); 5781 boolean silentMode = 5782 (ringerMode == RINGER_MODE_SILENT) || 5783 (ringerMode == RINGER_MODE_VIBRATE); 5784 return silentMode; 5785 } 5786 5787 // This section re-defines new output device constants from AudioSystem, because the AudioSystem 5788 // class is not used by other parts of the framework, which instead use definitions and methods 5789 // from AudioManager. AudioSystem is an internal class used by AudioManager and AudioService. 5790 5791 /** @hide 5792 * The audio device code for representing "no device." */ 5793 public static final int DEVICE_NONE = AudioSystem.DEVICE_NONE; 5794 /** @hide 5795 * The audio output device code for the small speaker at the front of the device used 5796 * when placing calls. Does not refer to an in-ear headphone without attached microphone, 5797 * such as earbuds, earphones, or in-ear monitors (IEM). Those would be handled as a 5798 * {@link #DEVICE_OUT_WIRED_HEADPHONE}. 5799 */ 5800 @UnsupportedAppUsage 5801 public static final int DEVICE_OUT_EARPIECE = AudioSystem.DEVICE_OUT_EARPIECE; 5802 /** @hide 5803 * The audio output device code for the built-in speaker */ 5804 @UnsupportedAppUsage 5805 public static final int DEVICE_OUT_SPEAKER = AudioSystem.DEVICE_OUT_SPEAKER; 5806 /** @hide 5807 * The audio output device code for a wired headset with attached microphone */ 5808 @UnsupportedAppUsage 5809 public static final int DEVICE_OUT_WIRED_HEADSET = AudioSystem.DEVICE_OUT_WIRED_HEADSET; 5810 /** @hide 5811 * The audio output device code for a wired headphone without attached microphone */ 5812 @UnsupportedAppUsage 5813 public static final int DEVICE_OUT_WIRED_HEADPHONE = AudioSystem.DEVICE_OUT_WIRED_HEADPHONE; 5814 /** @hide 5815 * The audio output device code for a USB headphone with attached microphone */ 5816 public static final int DEVICE_OUT_USB_HEADSET = AudioSystem.DEVICE_OUT_USB_HEADSET; 5817 /** @hide 5818 * The audio output device code for generic Bluetooth SCO, for voice */ 5819 public static final int DEVICE_OUT_BLUETOOTH_SCO = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO; 5820 /** @hide 5821 * The audio output device code for Bluetooth SCO Headset Profile (HSP) and 5822 * Hands-Free Profile (HFP), for voice 5823 */ 5824 @UnsupportedAppUsage 5825 public static final int DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 5826 AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET; 5827 /** @hide 5828 * The audio output device code for Bluetooth SCO car audio, for voice */ 5829 public static final int DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 5830 AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT; 5831 /** @hide 5832 * The audio output device code for generic Bluetooth A2DP, for music */ 5833 @UnsupportedAppUsage 5834 public static final int DEVICE_OUT_BLUETOOTH_A2DP = AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP; 5835 /** @hide 5836 * The audio output device code for Bluetooth A2DP headphones, for music */ 5837 @UnsupportedAppUsage 5838 public static final int DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 5839 AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES; 5840 /** @hide 5841 * The audio output device code for Bluetooth A2DP external speaker, for music */ 5842 @UnsupportedAppUsage 5843 public static final int DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 5844 AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER; 5845 /** @hide 5846 * The audio output device code for S/PDIF (legacy) or HDMI 5847 * Deprecated: replaced by {@link #DEVICE_OUT_HDMI} */ 5848 public static final int DEVICE_OUT_AUX_DIGITAL = AudioSystem.DEVICE_OUT_AUX_DIGITAL; 5849 /** @hide 5850 * The audio output device code for HDMI */ 5851 @UnsupportedAppUsage 5852 public static final int DEVICE_OUT_HDMI = AudioSystem.DEVICE_OUT_HDMI; 5853 /** @hide 5854 * The audio output device code for an analog wired headset attached via a 5855 * docking station 5856 */ 5857 @UnsupportedAppUsage 5858 public static final int DEVICE_OUT_ANLG_DOCK_HEADSET = AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET; 5859 /** @hide 5860 * The audio output device code for a digital wired headset attached via a 5861 * docking station 5862 */ 5863 @UnsupportedAppUsage 5864 public static final int DEVICE_OUT_DGTL_DOCK_HEADSET = AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET; 5865 /** @hide 5866 * The audio output device code for a USB audio accessory. The accessory is in USB host 5867 * mode and the Android device in USB device mode 5868 */ 5869 public static final int DEVICE_OUT_USB_ACCESSORY = AudioSystem.DEVICE_OUT_USB_ACCESSORY; 5870 /** @hide 5871 * The audio output device code for a USB audio device. The device is in USB device 5872 * mode and the Android device in USB host mode 5873 */ 5874 public static final int DEVICE_OUT_USB_DEVICE = AudioSystem.DEVICE_OUT_USB_DEVICE; 5875 /** @hide 5876 * The audio output device code for projection output. 5877 */ 5878 public static final int DEVICE_OUT_REMOTE_SUBMIX = AudioSystem.DEVICE_OUT_REMOTE_SUBMIX; 5879 /** @hide 5880 * The audio output device code the telephony voice TX path. 5881 */ 5882 public static final int DEVICE_OUT_TELEPHONY_TX = AudioSystem.DEVICE_OUT_TELEPHONY_TX; 5883 /** @hide 5884 * The audio output device code for an analog jack with line impedance detected. 5885 */ 5886 public static final int DEVICE_OUT_LINE = AudioSystem.DEVICE_OUT_LINE; 5887 /** @hide 5888 * The audio output device code for HDMI Audio Return Channel. 5889 */ 5890 public static final int DEVICE_OUT_HDMI_ARC = AudioSystem.DEVICE_OUT_HDMI_ARC; 5891 /** @hide 5892 * The audio output device code for HDMI enhanced Audio Return Channel. 5893 */ 5894 public static final int DEVICE_OUT_HDMI_EARC = AudioSystem.DEVICE_OUT_HDMI_EARC; 5895 /** @hide 5896 * The audio output device code for S/PDIF digital connection. 5897 */ 5898 public static final int DEVICE_OUT_SPDIF = AudioSystem.DEVICE_OUT_SPDIF; 5899 /** @hide 5900 * The audio output device code for built-in FM transmitter. 5901 */ 5902 public static final int DEVICE_OUT_FM = AudioSystem.DEVICE_OUT_FM; 5903 /** @hide 5904 * The audio output device code for echo reference injection point. 5905 */ 5906 public static final int DEVICE_OUT_ECHO_CANCELLER = AudioSystem.DEVICE_OUT_ECHO_CANCELLER; 5907 /** @hide 5908 * The audio output device code for a BLE audio headset. 5909 */ 5910 public static final int DEVICE_OUT_BLE_HEADSET = AudioSystem.DEVICE_OUT_BLE_HEADSET; 5911 /** @hide 5912 * The audio output device code for a BLE audio speaker. 5913 */ 5914 public static final int DEVICE_OUT_BLE_SPEAKER = AudioSystem.DEVICE_OUT_BLE_SPEAKER; 5915 /** @hide 5916 * The audio output device code for a BLE audio brodcast group. 5917 */ 5918 public static final int DEVICE_OUT_BLE_BROADCAST = AudioSystem.DEVICE_OUT_BLE_BROADCAST; 5919 /** @hide 5920 * This is not used as a returned value from {@link #getDevicesForStream}, but could be 5921 * used in the future in a set method to select whatever default device is chosen by the 5922 * platform-specific implementation. 5923 */ 5924 public static final int DEVICE_OUT_DEFAULT = AudioSystem.DEVICE_OUT_DEFAULT; 5925 5926 /** @hide 5927 * The audio input device code for default built-in microphone 5928 */ 5929 public static final int DEVICE_IN_BUILTIN_MIC = AudioSystem.DEVICE_IN_BUILTIN_MIC; 5930 /** @hide 5931 * The audio input device code for a Bluetooth SCO headset 5932 */ 5933 public static final int DEVICE_IN_BLUETOOTH_SCO_HEADSET = 5934 AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET; 5935 /** @hide 5936 * The audio input device code for wired headset microphone 5937 */ 5938 public static final int DEVICE_IN_WIRED_HEADSET = 5939 AudioSystem.DEVICE_IN_WIRED_HEADSET; 5940 /** @hide 5941 * The audio input device code for HDMI 5942 */ 5943 public static final int DEVICE_IN_HDMI = 5944 AudioSystem.DEVICE_IN_HDMI; 5945 /** @hide 5946 * The audio input device code for HDMI ARC 5947 */ 5948 public static final int DEVICE_IN_HDMI_ARC = 5949 AudioSystem.DEVICE_IN_HDMI_ARC; 5950 5951 /** @hide 5952 * The audio input device code for HDMI EARC 5953 */ 5954 public static final int DEVICE_IN_HDMI_EARC = 5955 AudioSystem.DEVICE_IN_HDMI_EARC; 5956 5957 /** @hide 5958 * The audio input device code for telephony voice RX path 5959 */ 5960 public static final int DEVICE_IN_TELEPHONY_RX = 5961 AudioSystem.DEVICE_IN_TELEPHONY_RX; 5962 /** @hide 5963 * The audio input device code for built-in microphone pointing to the back 5964 */ 5965 public static final int DEVICE_IN_BACK_MIC = 5966 AudioSystem.DEVICE_IN_BACK_MIC; 5967 /** @hide 5968 * The audio input device code for analog from a docking station 5969 */ 5970 public static final int DEVICE_IN_ANLG_DOCK_HEADSET = 5971 AudioSystem.DEVICE_IN_ANLG_DOCK_HEADSET; 5972 /** @hide 5973 * The audio input device code for digital from a docking station 5974 */ 5975 public static final int DEVICE_IN_DGTL_DOCK_HEADSET = 5976 AudioSystem.DEVICE_IN_DGTL_DOCK_HEADSET; 5977 /** @hide 5978 * The audio input device code for a USB audio accessory. The accessory is in USB host 5979 * mode and the Android device in USB device mode 5980 */ 5981 public static final int DEVICE_IN_USB_ACCESSORY = 5982 AudioSystem.DEVICE_IN_USB_ACCESSORY; 5983 /** @hide 5984 * The audio input device code for a USB audio device. The device is in USB device 5985 * mode and the Android device in USB host mode 5986 */ 5987 public static final int DEVICE_IN_USB_DEVICE = 5988 AudioSystem.DEVICE_IN_USB_DEVICE; 5989 /** @hide 5990 * The audio input device code for a FM radio tuner 5991 */ 5992 public static final int DEVICE_IN_FM_TUNER = AudioSystem.DEVICE_IN_FM_TUNER; 5993 /** @hide 5994 * The audio input device code for a TV tuner 5995 */ 5996 public static final int DEVICE_IN_TV_TUNER = AudioSystem.DEVICE_IN_TV_TUNER; 5997 /** @hide 5998 * The audio input device code for an analog jack with line impedance detected 5999 */ 6000 public static final int DEVICE_IN_LINE = AudioSystem.DEVICE_IN_LINE; 6001 /** @hide 6002 * The audio input device code for a S/PDIF digital connection 6003 */ 6004 public static final int DEVICE_IN_SPDIF = AudioSystem.DEVICE_IN_SPDIF; 6005 /** @hide 6006 * The audio input device code for audio loopback 6007 */ 6008 public static final int DEVICE_IN_LOOPBACK = AudioSystem.DEVICE_IN_LOOPBACK; 6009 /** @hide 6010 * The audio input device code for an echo reference capture point. 6011 */ 6012 public static final int DEVICE_IN_ECHO_REFERENCE = AudioSystem.DEVICE_IN_ECHO_REFERENCE; 6013 /** @hide 6014 * The audio input device code for a BLE audio headset. 6015 */ 6016 public static final int DEVICE_IN_BLE_HEADSET = AudioSystem.DEVICE_IN_BLE_HEADSET; 6017 6018 /** 6019 * Return true if the device code corresponds to an output device. 6020 * @hide 6021 */ isOutputDevice(int device)6022 public static boolean isOutputDevice(int device) 6023 { 6024 return (device & AudioSystem.DEVICE_BIT_IN) == 0; 6025 } 6026 6027 /** 6028 * Return true if the device code corresponds to an input device. 6029 * @hide 6030 */ isInputDevice(int device)6031 public static boolean isInputDevice(int device) 6032 { 6033 return (device & AudioSystem.DEVICE_BIT_IN) == AudioSystem.DEVICE_BIT_IN; 6034 } 6035 6036 6037 /** 6038 * Return the enabled devices for the specified output stream type. 6039 * 6040 * @param streamType The stream type to query. One of 6041 * {@link #STREAM_VOICE_CALL}, 6042 * {@link #STREAM_SYSTEM}, 6043 * {@link #STREAM_RING}, 6044 * {@link #STREAM_MUSIC}, 6045 * {@link #STREAM_ALARM}, 6046 * {@link #STREAM_NOTIFICATION}, 6047 * {@link #STREAM_DTMF}, 6048 * {@link #STREAM_ACCESSIBILITY}. 6049 * 6050 * @return The bit-mask "or" of audio output device codes for all enabled devices on this 6051 * stream. Zero or more of 6052 * {@link #DEVICE_OUT_EARPIECE}, 6053 * {@link #DEVICE_OUT_SPEAKER}, 6054 * {@link #DEVICE_OUT_WIRED_HEADSET}, 6055 * {@link #DEVICE_OUT_WIRED_HEADPHONE}, 6056 * {@link #DEVICE_OUT_BLUETOOTH_SCO}, 6057 * {@link #DEVICE_OUT_BLUETOOTH_SCO_HEADSET}, 6058 * {@link #DEVICE_OUT_BLUETOOTH_SCO_CARKIT}, 6059 * {@link #DEVICE_OUT_BLUETOOTH_A2DP}, 6060 * {@link #DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES}, 6061 * {@link #DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER}, 6062 * {@link #DEVICE_OUT_HDMI}, 6063 * {@link #DEVICE_OUT_ANLG_DOCK_HEADSET}, 6064 * {@link #DEVICE_OUT_DGTL_DOCK_HEADSET}. 6065 * {@link #DEVICE_OUT_USB_ACCESSORY}. 6066 * {@link #DEVICE_OUT_USB_DEVICE}. 6067 * {@link #DEVICE_OUT_REMOTE_SUBMIX}. 6068 * {@link #DEVICE_OUT_TELEPHONY_TX}. 6069 * {@link #DEVICE_OUT_LINE}. 6070 * {@link #DEVICE_OUT_HDMI_ARC}. 6071 * {@link #DEVICE_OUT_HDMI_EARC}. 6072 * {@link #DEVICE_OUT_SPDIF}. 6073 * {@link #DEVICE_OUT_FM}. 6074 * {@link #DEVICE_OUT_DEFAULT} is not used here. 6075 * 6076 * The implementation may support additional device codes beyond those listed, so 6077 * the application should ignore any bits which it does not recognize. 6078 * Note that the information may be imprecise when the implementation 6079 * cannot distinguish whether a particular device is enabled. 6080 * 6081 * @deprecated on {@link android.os.Build.VERSION_CODES#T} as new devices 6082 * will have multi-bit device types. 6083 * Prefer to use {@link #getDevicesForAttributes()} instead, 6084 * noting that getDevicesForStream() has a few small discrepancies 6085 * for better volume handling. 6086 * @hide 6087 */ 6088 @UnsupportedAppUsage 6089 @Deprecated getDevicesForStream(int streamType)6090 public int getDevicesForStream(int streamType) { 6091 switch (streamType) { 6092 case STREAM_VOICE_CALL: 6093 case STREAM_SYSTEM: 6094 case STREAM_RING: 6095 case STREAM_MUSIC: 6096 case STREAM_ALARM: 6097 case STREAM_NOTIFICATION: 6098 case STREAM_DTMF: 6099 case STREAM_ACCESSIBILITY: 6100 final IAudioService service = getService(); 6101 try { 6102 return service.getDeviceMaskForStream(streamType); 6103 } catch (RemoteException e) { 6104 throw e.rethrowFromSystemServer(); 6105 } 6106 default: 6107 return 0; 6108 } 6109 } 6110 6111 /** 6112 * @hide 6113 * Get the audio devices that would be used for the routing of the given audio attributes. 6114 * @param attributes the {@link AudioAttributes} for which the routing is being queried 6115 * @return an empty list if there was an issue with the request, a list of audio devices 6116 * otherwise (typically one device, except for duplicated paths). 6117 */ 6118 @SystemApi 6119 @RequiresPermission(anyOf = { 6120 Manifest.permission.MODIFY_AUDIO_ROUTING, 6121 Manifest.permission.QUERY_AUDIO_STATE 6122 }) getDevicesForAttributes( @onNull AudioAttributes attributes)6123 public @NonNull List<AudioDeviceAttributes> getDevicesForAttributes( 6124 @NonNull AudioAttributes attributes) { 6125 Objects.requireNonNull(attributes); 6126 final IAudioService service = getService(); 6127 try { 6128 return service.getDevicesForAttributes(attributes); 6129 } catch (RemoteException e) { 6130 throw e.rethrowFromSystemServer(); 6131 } 6132 } 6133 6134 // Each listener corresponds to a unique callback stub because each listener can subscribe to 6135 // different AudioAttributes. 6136 private final ConcurrentHashMap<OnDevicesForAttributesChangedListener, 6137 IDevicesForAttributesCallbackStub> mDevicesForAttributesListenerToStub = 6138 new ConcurrentHashMap<>(); 6139 6140 private static final class IDevicesForAttributesCallbackStub 6141 extends IDevicesForAttributesCallback.Stub { 6142 ListenerInfo<OnDevicesForAttributesChangedListener> mInfo; 6143 IDevicesForAttributesCallbackStub(@onNull OnDevicesForAttributesChangedListener listener, @NonNull Executor executor)6144 IDevicesForAttributesCallbackStub(@NonNull OnDevicesForAttributesChangedListener listener, 6145 @NonNull Executor executor) { 6146 mInfo = new ListenerInfo<>(listener, executor); 6147 } 6148 register(boolean register, AudioAttributes attributes)6149 public void register(boolean register, AudioAttributes attributes) { 6150 try { 6151 if (register) { 6152 getService().addOnDevicesForAttributesChangedListener(attributes, this); 6153 } else { 6154 getService().removeOnDevicesForAttributesChangedListener(this); 6155 } 6156 } catch (RemoteException e) { 6157 throw e.rethrowFromSystemServer(); 6158 } 6159 } 6160 6161 @Override onDevicesForAttributesChanged(AudioAttributes attributes, boolean forVolume, List<AudioDeviceAttributes> devices)6162 public void onDevicesForAttributesChanged(AudioAttributes attributes, boolean forVolume, 6163 List<AudioDeviceAttributes> devices) { 6164 // forVolume is ignored. The case where it is `true` is not handled. 6165 mInfo.mExecutor.execute(() -> 6166 mInfo.mListener.onDevicesForAttributesChanged( 6167 attributes, devices)); 6168 } 6169 } 6170 6171 /** 6172 * @hide 6173 * Interface to be notified of when routing changes for the registered audio attributes. 6174 */ 6175 @SystemApi 6176 public interface OnDevicesForAttributesChangedListener { 6177 /** 6178 * Called on the listener to indicate that the audio devices for the given audio 6179 * attributes have changed. 6180 * @param attributes the {@link AudioAttributes} whose routing changed 6181 * @param devices a list of newly routed audio devices 6182 */ onDevicesForAttributesChanged(@onNull AudioAttributes attributes, @NonNull List<AudioDeviceAttributes> devices)6183 void onDevicesForAttributesChanged(@NonNull AudioAttributes attributes, 6184 @NonNull List<AudioDeviceAttributes> devices); 6185 } 6186 6187 /** 6188 * @hide 6189 * Adds a listener for being notified of routing changes for the given {@link AudioAttributes}. 6190 * @param attributes the {@link AudioAttributes} to listen for routing changes 6191 * @param executor 6192 * @param listener 6193 */ 6194 @SystemApi 6195 @RequiresPermission(anyOf = { 6196 Manifest.permission.MODIFY_AUDIO_ROUTING, 6197 Manifest.permission.QUERY_AUDIO_STATE 6198 }) addOnDevicesForAttributesChangedListener(@onNull AudioAttributes attributes, @NonNull @CallbackExecutor Executor executor, @NonNull OnDevicesForAttributesChangedListener listener)6199 public void addOnDevicesForAttributesChangedListener(@NonNull AudioAttributes attributes, 6200 @NonNull @CallbackExecutor Executor executor, 6201 @NonNull OnDevicesForAttributesChangedListener listener) { 6202 Objects.requireNonNull(attributes); 6203 Objects.requireNonNull(executor); 6204 Objects.requireNonNull(listener); 6205 6206 synchronized (mDevicesForAttributesListenerToStub) { 6207 IDevicesForAttributesCallbackStub callbackStub = 6208 mDevicesForAttributesListenerToStub.get(listener); 6209 6210 if (callbackStub == null) { 6211 callbackStub = new IDevicesForAttributesCallbackStub(listener, executor); 6212 mDevicesForAttributesListenerToStub.put(listener, callbackStub); 6213 } 6214 6215 callbackStub.register(true, attributes); 6216 } 6217 } 6218 6219 /** 6220 * @hide 6221 * Removes a previously registered listener for being notified of routing changes for the given 6222 * {@link AudioAttributes}. 6223 * @param listener 6224 */ 6225 @SystemApi 6226 @RequiresPermission(anyOf = { 6227 Manifest.permission.MODIFY_AUDIO_ROUTING, 6228 Manifest.permission.QUERY_AUDIO_STATE 6229 }) removeOnDevicesForAttributesChangedListener( @onNull OnDevicesForAttributesChangedListener listener)6230 public void removeOnDevicesForAttributesChangedListener( 6231 @NonNull OnDevicesForAttributesChangedListener listener) { 6232 Objects.requireNonNull(listener); 6233 6234 synchronized (mDevicesForAttributesListenerToStub) { 6235 IDevicesForAttributesCallbackStub callbackStub = 6236 mDevicesForAttributesListenerToStub.get(listener); 6237 if (callbackStub != null) { 6238 callbackStub.register(false, null /* attributes */); 6239 } 6240 6241 mDevicesForAttributesListenerToStub.remove(listener); 6242 } 6243 } 6244 6245 /** 6246 * Get the audio devices that would be used for the routing of the given audio attributes. 6247 * These are the devices anticipated to play sound from an {@link AudioTrack} created with 6248 * the specified {@link AudioAttributes}. 6249 * The audio routing can change if audio devices are physically connected or disconnected or 6250 * concurrently through {@link AudioRouting} or {@link MediaRouter}. 6251 * @param attributes the {@link AudioAttributes} for which the routing is being queried 6252 * @return an empty list if there was an issue with the request, a list of 6253 * {@link AudioDeviceInfo} otherwise (typically one device, except for duplicated paths). 6254 */ getAudioDevicesForAttributes( @onNull AudioAttributes attributes)6255 public @NonNull List<AudioDeviceInfo> getAudioDevicesForAttributes( 6256 @NonNull AudioAttributes attributes) { 6257 final List<AudioDeviceAttributes> devicesForAttributes; 6258 try { 6259 Objects.requireNonNull(attributes); 6260 final IAudioService service = getService(); 6261 devicesForAttributes = service.getDevicesForAttributesUnprotected(attributes); 6262 } catch (Exception e) { 6263 Log.i(TAG, "No audio devices available for specified attributes."); 6264 return Collections.emptyList(); 6265 } 6266 6267 // Map from AudioDeviceAttributes to AudioDeviceInfo 6268 AudioDeviceInfo[] outputDeviceInfos = getDevicesStatic(GET_DEVICES_OUTPUTS); 6269 List<AudioDeviceInfo> deviceInfosForAttributes = new ArrayList<>(); 6270 for (AudioDeviceAttributes deviceForAttributes : devicesForAttributes) { 6271 for (AudioDeviceInfo deviceInfo : outputDeviceInfos) { 6272 if (deviceForAttributes.getType() == deviceInfo.getType() 6273 && TextUtils.equals(deviceForAttributes.getAddress(), 6274 deviceInfo.getAddress())) { 6275 deviceInfosForAttributes.add(deviceInfo); 6276 } 6277 } 6278 } 6279 return Collections.unmodifiableList(deviceInfosForAttributes); 6280 } 6281 6282 /** 6283 * @hide 6284 * Volume behavior for an audio device that has no particular volume behavior set. Invalid as 6285 * an argument to {@link #setDeviceVolumeBehavior(AudioDeviceAttributes, int)} and should not 6286 * be returned by {@link #getDeviceVolumeBehavior(AudioDeviceAttributes)}. 6287 */ 6288 public static final int DEVICE_VOLUME_BEHAVIOR_UNSET = -1; 6289 /** 6290 * @hide 6291 * Volume behavior for an audio device where a software attenuation is applied 6292 * @see #setDeviceVolumeBehavior(AudioDeviceAttributes, int) 6293 */ 6294 @SystemApi 6295 public static final int DEVICE_VOLUME_BEHAVIOR_VARIABLE = 0; 6296 /** 6297 * @hide 6298 * Volume behavior for an audio device where the volume is always set to provide no attenuation 6299 * nor gain (e.g. unit gain). 6300 * @see #setDeviceVolumeBehavior(AudioDeviceAttributes, int) 6301 */ 6302 @SystemApi 6303 public static final int DEVICE_VOLUME_BEHAVIOR_FULL = 1; 6304 /** 6305 * @hide 6306 * Volume behavior for an audio device where the volume is either set to muted, or to provide 6307 * no attenuation nor gain (e.g. unit gain). 6308 * @see #setDeviceVolumeBehavior(AudioDeviceAttributes, int) 6309 */ 6310 @SystemApi 6311 public static final int DEVICE_VOLUME_BEHAVIOR_FIXED = 2; 6312 /** 6313 * @hide 6314 * Volume behavior for an audio device where no software attenuation is applied, and 6315 * the volume is kept synchronized between the host and the device itself through a 6316 * device-specific protocol such as BT AVRCP. 6317 * @see #setDeviceVolumeBehavior(AudioDeviceAttributes, int) 6318 */ 6319 @SystemApi 6320 public static final int DEVICE_VOLUME_BEHAVIOR_ABSOLUTE = 3; 6321 /** 6322 * @hide 6323 * Volume behavior for an audio device where no software attenuation is applied, and 6324 * the volume is kept synchronized between the host and the device itself through a 6325 * device-specific protocol (such as for hearing aids), based on the audio mode (e.g. 6326 * normal vs in phone call). 6327 * @see #setMode(int) 6328 * @see #setDeviceVolumeBehavior(AudioDeviceAttributes, int) 6329 */ 6330 @SystemApi 6331 public static final int DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE = 4; 6332 6333 /** 6334 * @hide 6335 * A variant of {@link #DEVICE_VOLUME_BEHAVIOR_ABSOLUTE} where the host cannot reliably set 6336 * the volume percentage of the audio device. Specifically, {@link #setStreamVolume} will have 6337 * no effect, or an unreliable effect. 6338 */ 6339 @SystemApi 6340 public static final int DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY = 5; 6341 6342 /** @hide */ 6343 @IntDef({ 6344 DEVICE_VOLUME_BEHAVIOR_VARIABLE, 6345 DEVICE_VOLUME_BEHAVIOR_FULL, 6346 DEVICE_VOLUME_BEHAVIOR_FIXED, 6347 DEVICE_VOLUME_BEHAVIOR_ABSOLUTE, 6348 DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE, 6349 DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY, 6350 }) 6351 @Retention(RetentionPolicy.SOURCE) 6352 public @interface DeviceVolumeBehavior {} 6353 6354 /** @hide */ 6355 @IntDef({ 6356 DEVICE_VOLUME_BEHAVIOR_UNSET, 6357 DEVICE_VOLUME_BEHAVIOR_VARIABLE, 6358 DEVICE_VOLUME_BEHAVIOR_FULL, 6359 DEVICE_VOLUME_BEHAVIOR_FIXED, 6360 DEVICE_VOLUME_BEHAVIOR_ABSOLUTE, 6361 DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE, 6362 DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY, 6363 }) 6364 @Retention(RetentionPolicy.SOURCE) 6365 public @interface DeviceVolumeBehaviorState {} 6366 6367 /** 6368 * Variants of absolute volume behavior that are set in {@link AudioDeviceVolumeManager}. 6369 * @hide 6370 */ 6371 @IntDef({ 6372 DEVICE_VOLUME_BEHAVIOR_ABSOLUTE, 6373 DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY, 6374 }) 6375 @Retention(RetentionPolicy.SOURCE) 6376 public @interface AbsoluteDeviceVolumeBehavior {} 6377 6378 /** 6379 * @hide 6380 * Throws IAE on an invalid volume behavior value 6381 * @param volumeBehavior behavior value to check 6382 */ enforceValidVolumeBehavior(int volumeBehavior)6383 public static void enforceValidVolumeBehavior(int volumeBehavior) { 6384 switch (volumeBehavior) { 6385 case DEVICE_VOLUME_BEHAVIOR_VARIABLE: 6386 case DEVICE_VOLUME_BEHAVIOR_FULL: 6387 case DEVICE_VOLUME_BEHAVIOR_FIXED: 6388 case DEVICE_VOLUME_BEHAVIOR_ABSOLUTE: 6389 case DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE: 6390 case DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY: 6391 return; 6392 default: 6393 throw new IllegalArgumentException("Illegal volume behavior " + volumeBehavior); 6394 } 6395 } 6396 6397 /** 6398 * @hide 6399 * Sets the volume behavior for an audio output device. 6400 * @see #DEVICE_VOLUME_BEHAVIOR_VARIABLE 6401 * @see #DEVICE_VOLUME_BEHAVIOR_FULL 6402 * @see #DEVICE_VOLUME_BEHAVIOR_FIXED 6403 * @see #DEVICE_VOLUME_BEHAVIOR_ABSOLUTE 6404 * @see #DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE 6405 * @param device the device to be affected 6406 * @param deviceVolumeBehavior one of the device behaviors 6407 */ 6408 @SystemApi 6409 @RequiresPermission(anyOf = { 6410 Manifest.permission.MODIFY_AUDIO_ROUTING, 6411 Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED 6412 }) setDeviceVolumeBehavior(@onNull AudioDeviceAttributes device, @DeviceVolumeBehavior int deviceVolumeBehavior)6413 public void setDeviceVolumeBehavior(@NonNull AudioDeviceAttributes device, 6414 @DeviceVolumeBehavior int deviceVolumeBehavior) { 6415 // verify arguments (validity of device type is enforced in server) 6416 Objects.requireNonNull(device); 6417 enforceValidVolumeBehavior(deviceVolumeBehavior); 6418 // communicate with service 6419 final IAudioService service = getService(); 6420 try { 6421 service.setDeviceVolumeBehavior(device, deviceVolumeBehavior, 6422 mApplicationContext.getOpPackageName()); 6423 } catch (RemoteException e) { 6424 throw e.rethrowFromSystemServer(); 6425 } 6426 } 6427 6428 /** 6429 * @hide 6430 * Controls whether DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY may be returned by 6431 * getDeviceVolumeBehavior. If this is disabled, DEVICE_VOLUME_BEHAVIOR_FULL is returned 6432 * in its place. 6433 */ 6434 @ChangeId 6435 @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 6436 @Overridable 6437 public static final long RETURN_DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY = 240663182L; 6438 6439 /** 6440 * @hide 6441 * Returns the volume device behavior for the given audio device 6442 * @param device the audio device 6443 * @return the volume behavior for the device 6444 */ 6445 @SystemApi 6446 @RequiresPermission(anyOf = { 6447 Manifest.permission.MODIFY_AUDIO_ROUTING, 6448 Manifest.permission.QUERY_AUDIO_STATE, 6449 Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED 6450 }) 6451 public @DeviceVolumeBehavior getDeviceVolumeBehavior(@onNull AudioDeviceAttributes device)6452 int getDeviceVolumeBehavior(@NonNull AudioDeviceAttributes device) { 6453 // verify arguments (validity of device type is enforced in server) 6454 Objects.requireNonNull(device); 6455 // communicate with service 6456 final IAudioService service = getService(); 6457 try { 6458 int behavior = service.getDeviceVolumeBehavior(device); 6459 if (!CompatChanges.isChangeEnabled(RETURN_DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY) 6460 && behavior == DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY) { 6461 return AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL; 6462 } 6463 return behavior; 6464 } catch (RemoteException e) { 6465 throw e.rethrowFromSystemServer(); 6466 } 6467 } 6468 6469 /** 6470 * @hide 6471 * Returns {@code true} if the volume device behavior is {@link #DEVICE_VOLUME_BEHAVIOR_FULL}. 6472 */ 6473 @TestApi 6474 @RequiresPermission(anyOf = { 6475 Manifest.permission.MODIFY_AUDIO_ROUTING, 6476 Manifest.permission.QUERY_AUDIO_STATE, 6477 Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED 6478 }) isFullVolumeDevice()6479 public boolean isFullVolumeDevice() { 6480 final AudioAttributes attributes = new AudioAttributes.Builder() 6481 .setUsage(AudioAttributes.USAGE_MEDIA) 6482 .build(); 6483 final List<AudioDeviceAttributes> devices = getDevicesForAttributes(attributes); 6484 for (AudioDeviceAttributes device : devices) { 6485 if (getDeviceVolumeBehavior(device) == DEVICE_VOLUME_BEHAVIOR_FULL) { 6486 return true; 6487 } 6488 } 6489 return false; 6490 } 6491 6492 /** 6493 * Indicate wired accessory connection state change. 6494 * @param device type of device connected/disconnected (AudioManager.DEVICE_OUT_xxx) 6495 * @param state new connection state: 1 connected, 0 disconnected 6496 * @param name device name 6497 * {@hide} 6498 */ 6499 @UnsupportedAppUsage 6500 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) setWiredDeviceConnectionState(int device, int state, String address, String name)6501 public void setWiredDeviceConnectionState(int device, int state, String address, String name) { 6502 AudioDeviceAttributes attributes = new AudioDeviceAttributes(device, address, name); 6503 setWiredDeviceConnectionState(attributes, state); 6504 } 6505 6506 /** 6507 * Indicate wired accessory connection state change and attributes. 6508 * @param state new connection state: 1 connected, 0 disconnected 6509 * @param attributes attributes of the connected device 6510 * {@hide} 6511 */ 6512 @UnsupportedAppUsage 6513 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) setWiredDeviceConnectionState(AudioDeviceAttributes attributes, int state)6514 public void setWiredDeviceConnectionState(AudioDeviceAttributes attributes, int state) { 6515 final IAudioService service = getService(); 6516 try { 6517 service.setWiredDeviceConnectionState(attributes, state, 6518 mApplicationContext.getOpPackageName()); 6519 } catch (RemoteException e) { 6520 throw e.rethrowFromSystemServer(); 6521 } 6522 } 6523 6524 /** 6525 * Indicate wired accessory connection state change. 6526 * @param device {@link AudioDeviceAttributes} of the device to "fake-connect" 6527 * @param connected true for connected, false for disconnected 6528 * {@hide} 6529 */ 6530 @TestApi 6531 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) setTestDeviceConnectionState(@onNull AudioDeviceAttributes device, boolean connected)6532 public void setTestDeviceConnectionState(@NonNull AudioDeviceAttributes device, 6533 boolean connected) { 6534 try { 6535 getService().setTestDeviceConnectionState(device, connected); 6536 } catch (RemoteException e) { 6537 throw e.rethrowFromSystemServer(); 6538 } 6539 } 6540 6541 /** 6542 * Indicate Bluetooth profile connection state change. 6543 * Configuration changes for A2DP are indicated by having the same <code>newDevice</code> and 6544 * <code>previousDevice</code> 6545 * This operation is asynchronous. 6546 * 6547 * @param newDevice Bluetooth device connected or null if there is no new devices 6548 * @param previousDevice Bluetooth device disconnected or null if there is no disconnected 6549 * devices 6550 * @param info contain all info related to the device. {@link BluetoothProfileConnectionInfo} 6551 * {@hide} 6552 */ 6553 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 6554 @RequiresPermission(Manifest.permission.BLUETOOTH_STACK) handleBluetoothActiveDeviceChanged(@ullable BluetoothDevice newDevice, @Nullable BluetoothDevice previousDevice, @NonNull BluetoothProfileConnectionInfo info)6555 public void handleBluetoothActiveDeviceChanged(@Nullable BluetoothDevice newDevice, 6556 @Nullable BluetoothDevice previousDevice, 6557 @NonNull BluetoothProfileConnectionInfo info) { 6558 final IAudioService service = getService(); 6559 try { 6560 service.handleBluetoothActiveDeviceChanged(newDevice, previousDevice, info); 6561 } catch (RemoteException e) { 6562 throw e.rethrowFromSystemServer(); 6563 } 6564 } 6565 6566 /** {@hide} */ getRingtonePlayer()6567 public IRingtonePlayer getRingtonePlayer() { 6568 try { 6569 return getService().getRingtonePlayer(); 6570 } catch (RemoteException e) { 6571 throw e.rethrowFromSystemServer(); 6572 } 6573 } 6574 6575 /** 6576 * Used as a key for {@link #getProperty} to request the native or optimal output sample rate 6577 * for this device's low latency output stream, in decimal Hz. Latency-sensitive apps 6578 * should use this value as a default, and offer the user the option to override it. 6579 * The low latency output stream is typically either the device's primary output stream, 6580 * or another output stream with smaller buffers. 6581 */ 6582 // FIXME Deprecate 6583 public static final String PROPERTY_OUTPUT_SAMPLE_RATE = 6584 "android.media.property.OUTPUT_SAMPLE_RATE"; 6585 6586 /** 6587 * Used as a key for {@link #getProperty} to request the native or optimal output buffer size 6588 * for this device's low latency output stream, in decimal PCM frames. Latency-sensitive apps 6589 * should use this value as a minimum, and offer the user the option to override it. 6590 * The low latency output stream is typically either the device's primary output stream, 6591 * or another output stream with smaller buffers. 6592 */ 6593 // FIXME Deprecate 6594 public static final String PROPERTY_OUTPUT_FRAMES_PER_BUFFER = 6595 "android.media.property.OUTPUT_FRAMES_PER_BUFFER"; 6596 6597 /** 6598 * Used as a key for {@link #getProperty} to determine if the default microphone audio source 6599 * supports near-ultrasound frequencies (range of 18 - 21 kHz). 6600 */ 6601 public static final String PROPERTY_SUPPORT_MIC_NEAR_ULTRASOUND = 6602 "android.media.property.SUPPORT_MIC_NEAR_ULTRASOUND"; 6603 6604 /** 6605 * Used as a key for {@link #getProperty} to determine if the default speaker audio path 6606 * supports near-ultrasound frequencies (range of 18 - 21 kHz). 6607 */ 6608 public static final String PROPERTY_SUPPORT_SPEAKER_NEAR_ULTRASOUND = 6609 "android.media.property.SUPPORT_SPEAKER_NEAR_ULTRASOUND"; 6610 6611 /** 6612 * Used as a key for {@link #getProperty} to determine if the unprocessed audio source is 6613 * available and supported with the expected frequency range and level response. 6614 */ 6615 public static final String PROPERTY_SUPPORT_AUDIO_SOURCE_UNPROCESSED = 6616 "android.media.property.SUPPORT_AUDIO_SOURCE_UNPROCESSED"; 6617 /** 6618 * Returns the value of the property with the specified key. 6619 * @param key One of the strings corresponding to a property key: either 6620 * {@link #PROPERTY_OUTPUT_SAMPLE_RATE}, 6621 * {@link #PROPERTY_OUTPUT_FRAMES_PER_BUFFER}, 6622 * {@link #PROPERTY_SUPPORT_MIC_NEAR_ULTRASOUND}, 6623 * {@link #PROPERTY_SUPPORT_SPEAKER_NEAR_ULTRASOUND}, or 6624 * {@link #PROPERTY_SUPPORT_AUDIO_SOURCE_UNPROCESSED}. 6625 * @return A string representing the associated value for that property key, 6626 * or null if there is no value for that key. 6627 */ getProperty(String key)6628 public String getProperty(String key) { 6629 if (PROPERTY_OUTPUT_SAMPLE_RATE.equals(key)) { 6630 int outputSampleRate = AudioSystem.getPrimaryOutputSamplingRate(); 6631 return outputSampleRate > 0 ? Integer.toString(outputSampleRate) : null; 6632 } else if (PROPERTY_OUTPUT_FRAMES_PER_BUFFER.equals(key)) { 6633 int outputFramesPerBuffer = AudioSystem.getPrimaryOutputFrameCount(); 6634 return outputFramesPerBuffer > 0 ? Integer.toString(outputFramesPerBuffer) : null; 6635 } else if (PROPERTY_SUPPORT_MIC_NEAR_ULTRASOUND.equals(key)) { 6636 // Will throw a RuntimeException Resources.NotFoundException if this config value is 6637 // not found. 6638 return String.valueOf(getContext().getResources().getBoolean( 6639 com.android.internal.R.bool.config_supportMicNearUltrasound)); 6640 } else if (PROPERTY_SUPPORT_SPEAKER_NEAR_ULTRASOUND.equals(key)) { 6641 return String.valueOf(getContext().getResources().getBoolean( 6642 com.android.internal.R.bool.config_supportSpeakerNearUltrasound)); 6643 } else if (PROPERTY_SUPPORT_AUDIO_SOURCE_UNPROCESSED.equals(key)) { 6644 return String.valueOf(getContext().getResources().getBoolean( 6645 com.android.internal.R.bool.config_supportAudioSourceUnprocessed)); 6646 } else { 6647 // null or unknown key 6648 return null; 6649 } 6650 } 6651 6652 /** 6653 * @hide 6654 * Sets an additional audio output device delay in milliseconds. 6655 * 6656 * The additional output delay is a request to the output device to 6657 * delay audio presentation (generally with respect to video presentation for better 6658 * synchronization). 6659 * It may not be supported by all output devices, 6660 * and typically increases the audio latency by the amount of additional 6661 * audio delay requested. 6662 * 6663 * If additional audio delay is supported by an audio output device, 6664 * it is expected to be supported for all output streams (and configurations) 6665 * opened on that device. 6666 * 6667 * @param device an instance of {@link AudioDeviceInfo} returned from {@link getDevices()}. 6668 * @param delayMillis delay in milliseconds desired. This should be in range of {@code 0} 6669 * to the value returned by {@link #getMaxAdditionalOutputDeviceDelay()}. 6670 * @return true if successful, false if the device does not support output device delay 6671 * or the delay is not in range of {@link #getMaxAdditionalOutputDeviceDelay()}. 6672 */ 6673 @SystemApi 6674 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) setAdditionalOutputDeviceDelay( @onNull AudioDeviceInfo device, @IntRange(from = 0) long delayMillis)6675 public boolean setAdditionalOutputDeviceDelay( 6676 @NonNull AudioDeviceInfo device, @IntRange(from = 0) long delayMillis) { 6677 Objects.requireNonNull(device); 6678 try { 6679 return getService().setAdditionalOutputDeviceDelay( 6680 new AudioDeviceAttributes(device), delayMillis); 6681 } catch (RemoteException e) { 6682 throw e.rethrowFromSystemServer(); 6683 } 6684 } 6685 6686 /** 6687 * @hide 6688 * Returns the current additional audio output device delay in milliseconds. 6689 * 6690 * @param device an instance of {@link AudioDeviceInfo} returned from {@link getDevices()}. 6691 * @return the additional output device delay. This is a non-negative number. 6692 * {@code 0} is returned if unsupported. 6693 */ 6694 @SystemApi 6695 @IntRange(from = 0) getAdditionalOutputDeviceDelay(@onNull AudioDeviceInfo device)6696 public long getAdditionalOutputDeviceDelay(@NonNull AudioDeviceInfo device) { 6697 Objects.requireNonNull(device); 6698 try { 6699 return getService().getAdditionalOutputDeviceDelay(new AudioDeviceAttributes(device)); 6700 } catch (RemoteException e) { 6701 throw e.rethrowFromSystemServer(); 6702 } 6703 } 6704 6705 /** 6706 * @hide 6707 * Returns the maximum additional audio output device delay in milliseconds. 6708 * 6709 * @param device an instance of {@link AudioDeviceInfo} returned from {@link getDevices()}. 6710 * @return the maximum output device delay in milliseconds that can be set. 6711 * This is a non-negative number 6712 * representing the additional audio delay supported for the device. 6713 * {@code 0} is returned if unsupported. 6714 */ 6715 @SystemApi 6716 @IntRange(from = 0) getMaxAdditionalOutputDeviceDelay(@onNull AudioDeviceInfo device)6717 public long getMaxAdditionalOutputDeviceDelay(@NonNull AudioDeviceInfo device) { 6718 Objects.requireNonNull(device); 6719 try { 6720 return getService().getMaxAdditionalOutputDeviceDelay( 6721 new AudioDeviceAttributes(device)); 6722 } catch (RemoteException e) { 6723 throw e.rethrowFromSystemServer(); 6724 } 6725 } 6726 6727 /** 6728 * Returns the estimated latency for the given stream type in milliseconds. 6729 * 6730 * DO NOT UNHIDE. The existing approach for doing A/V sync has too many problems. We need 6731 * a better solution. 6732 * @hide 6733 */ 6734 @UnsupportedAppUsage getOutputLatency(int streamType)6735 public int getOutputLatency(int streamType) { 6736 return AudioSystem.getOutputLatency(streamType); 6737 } 6738 6739 /** 6740 * Registers a global volume controller interface. Currently limited to SystemUI. 6741 * 6742 * @hide 6743 */ setVolumeController(IVolumeController controller)6744 public void setVolumeController(IVolumeController controller) { 6745 try { 6746 getService().setVolumeController(controller); 6747 } catch (RemoteException e) { 6748 throw e.rethrowFromSystemServer(); 6749 } 6750 } 6751 6752 /** 6753 * Returns the registered volume controller interface. 6754 * 6755 * @hide 6756 */ 6757 @Nullable getVolumeController()6758 public IVolumeController getVolumeController() { 6759 try { 6760 return getService().getVolumeController(); 6761 } catch (RemoteException e) { 6762 throw e.rethrowFromSystemServer(); 6763 } 6764 } 6765 6766 /** 6767 * Notify audio manager about volume controller visibility changes. 6768 * Currently limited to SystemUI. 6769 * 6770 * @hide 6771 */ notifyVolumeControllerVisible(IVolumeController controller, boolean visible)6772 public void notifyVolumeControllerVisible(IVolumeController controller, boolean visible) { 6773 try { 6774 getService().notifyVolumeControllerVisible(controller, visible); 6775 } catch (RemoteException e) { 6776 throw e.rethrowFromSystemServer(); 6777 } 6778 } 6779 6780 /** 6781 * Only useful for volume controllers. 6782 * @hide 6783 */ isStreamAffectedByRingerMode(int streamType)6784 public boolean isStreamAffectedByRingerMode(int streamType) { 6785 try { 6786 return getService().isStreamAffectedByRingerMode(streamType); 6787 } catch (RemoteException e) { 6788 throw e.rethrowFromSystemServer(); 6789 } 6790 } 6791 6792 /** 6793 * Only useful for volume controllers. 6794 * @hide 6795 */ isStreamAffectedByMute(int streamType)6796 public boolean isStreamAffectedByMute(int streamType) { 6797 try { 6798 return getService().isStreamAffectedByMute(streamType); 6799 } catch (RemoteException e) { 6800 throw e.rethrowFromSystemServer(); 6801 } 6802 } 6803 6804 /** 6805 * Only useful for volume controllers. 6806 * @hide 6807 */ disableSafeMediaVolume()6808 public void disableSafeMediaVolume() { 6809 try { 6810 getService().disableSafeMediaVolume(mApplicationContext.getOpPackageName()); 6811 } catch (RemoteException e) { 6812 throw e.rethrowFromSystemServer(); 6813 } 6814 } 6815 6816 /** 6817 * @hide 6818 * Lower media volume to RS1 interval 6819 */ lowerVolumeToRs1()6820 public void lowerVolumeToRs1() { 6821 try { 6822 getService().lowerVolumeToRs1(mApplicationContext.getOpPackageName()); 6823 } catch (RemoteException e) { 6824 throw e.rethrowFromSystemServer(); 6825 } 6826 } 6827 6828 /** 6829 * @hide 6830 * @return the RS2 upper bound used for momentary exposure warnings 6831 */ 6832 @TestApi 6833 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED) getRs2Value()6834 public float getRs2Value() { 6835 try { 6836 return getService().getOutputRs2UpperBound(); 6837 } catch (RemoteException e) { 6838 throw e.rethrowFromSystemServer(); 6839 } 6840 } 6841 6842 /** 6843 * @hide 6844 * Sets the RS2 upper bound used for momentary exposure warnings 6845 */ 6846 @TestApi 6847 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED) setRs2Value(float rs2Value)6848 public void setRs2Value(float rs2Value) { 6849 try { 6850 getService().setOutputRs2UpperBound(rs2Value); 6851 } catch (RemoteException e) { 6852 throw e.rethrowFromSystemServer(); 6853 } 6854 } 6855 6856 /** 6857 * @hide 6858 * @return the current computed sound dose value 6859 */ 6860 @TestApi 6861 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED) getCsd()6862 public float getCsd() { 6863 try { 6864 return getService().getCsd(); 6865 } catch (RemoteException e) { 6866 throw e.rethrowFromSystemServer(); 6867 } 6868 } 6869 6870 /** 6871 * @hide 6872 * Sets the computed sound dose value to {@code csd}. A negative value will 6873 * reset all the CSD related timeouts: after a momentary exposure warning and 6874 * before the momentary exposure reaches RS2 (see IEC62368-1 10.6.5) 6875 */ 6876 @TestApi 6877 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED) setCsd(float csd)6878 public void setCsd(float csd) { 6879 try { 6880 getService().setCsd(csd); 6881 } catch (RemoteException e) { 6882 throw e.rethrowFromSystemServer(); 6883 } 6884 } 6885 6886 /** 6887 * @hide 6888 * Forces the computation of MEL values (used for CSD) on framework level. This will have the 6889 * result of ignoring the MEL values computed on HAL level. Should only be used in testing 6890 * since this can affect the certification of a device with EN50332-3 regulation. 6891 */ 6892 @TestApi 6893 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED) forceUseFrameworkMel(boolean useFrameworkMel)6894 public void forceUseFrameworkMel(boolean useFrameworkMel) { 6895 try { 6896 getService().forceUseFrameworkMel(useFrameworkMel); 6897 } catch (RemoteException e) { 6898 throw e.rethrowFromSystemServer(); 6899 } 6900 } 6901 6902 /** 6903 * @hide 6904 * Forces the computation of CSD on all output devices. 6905 */ 6906 @TestApi 6907 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED) forceComputeCsdOnAllDevices(boolean computeCsdOnAllDevices)6908 public void forceComputeCsdOnAllDevices(boolean computeCsdOnAllDevices) { 6909 try { 6910 getService().forceComputeCsdOnAllDevices(computeCsdOnAllDevices); 6911 } catch (RemoteException e) { 6912 throw e.rethrowFromSystemServer(); 6913 } 6914 } 6915 6916 /** 6917 * @hide 6918 * Returns whether CSD is enabled and supported by the current active audio module HAL. 6919 * This method will return {@code false) for setups in which CSD as a feature is available 6920 * (see {@link AudioManager#isCsdAsAFeatureAvailable()}) and not enabled (see 6921 * {@link AudioManager#isCsdAsAFeatureEnabled()}). 6922 */ 6923 @TestApi 6924 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED) isCsdEnabled()6925 public boolean isCsdEnabled() { 6926 try { 6927 return getService().isCsdEnabled(); 6928 } catch (RemoteException e) { 6929 throw e.rethrowFromSystemServer(); 6930 } 6931 } 6932 6933 /** 6934 * @hide 6935 * Returns whether CSD as a feature can be manipulated by a client. This method 6936 * returns {@code true} in countries where there isn't a safe hearing regulation 6937 * enforced. 6938 */ 6939 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED) isCsdAsAFeatureAvailable()6940 public boolean isCsdAsAFeatureAvailable() { 6941 try { 6942 return getService().isCsdAsAFeatureAvailable(); 6943 } catch (RemoteException e) { 6944 throw e.rethrowFromSystemServer(); 6945 } 6946 } 6947 6948 /** 6949 * @hide 6950 * Returns {@code true} if the client has enabled CSD. This function should only 6951 * be called if {@link AudioManager#isCsdAsAFeatureAvailable()} returns {@code true}. 6952 */ 6953 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED) isCsdAsAFeatureEnabled()6954 public boolean isCsdAsAFeatureEnabled() { 6955 try { 6956 return getService().isCsdAsAFeatureEnabled(); 6957 } catch (RemoteException e) { 6958 throw e.rethrowFromSystemServer(); 6959 } 6960 } 6961 6962 /** 6963 * @hide 6964 * Enables/disables the CSD feature. This function should only be called if 6965 * {@link AudioManager#isCsdAsAFeatureAvailable()} returns {@code true}. 6966 */ 6967 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED) setCsdAsAFeatureEnabled(boolean csdToggleValue)6968 public void setCsdAsAFeatureEnabled(boolean csdToggleValue) { 6969 try { 6970 getService().setCsdAsAFeatureEnabled(csdToggleValue); 6971 } catch (RemoteException e) { 6972 throw e.rethrowFromSystemServer(); 6973 } 6974 } 6975 6976 /** 6977 * @hide 6978 * Describes an audio device that has not been categorized with a specific 6979 * audio type. 6980 */ 6981 public static final int AUDIO_DEVICE_CATEGORY_UNKNOWN = 0; 6982 6983 /** 6984 * @hide 6985 * Describes an audio device which is categorized as something different. 6986 */ 6987 public static final int AUDIO_DEVICE_CATEGORY_OTHER = 1; 6988 6989 /** 6990 * @hide 6991 * Describes an audio device which was categorized as speakers. 6992 */ 6993 public static final int AUDIO_DEVICE_CATEGORY_SPEAKER = 2; 6994 6995 /** 6996 * @hide 6997 * Describes an audio device which was categorized as headphones. 6998 */ 6999 public static final int AUDIO_DEVICE_CATEGORY_HEADPHONES = 3; 7000 7001 /** 7002 * @hide 7003 * Describes an audio device which was categorized as car-kit. 7004 */ 7005 public static final int AUDIO_DEVICE_CATEGORY_CARKIT = 4; 7006 7007 /** 7008 * @hide 7009 * Describes an audio device which was categorized as watch. 7010 */ 7011 public static final int AUDIO_DEVICE_CATEGORY_WATCH = 5; 7012 7013 /** 7014 * @hide 7015 * Describes an audio device which was categorized as hearing aid. 7016 */ 7017 public static final int AUDIO_DEVICE_CATEGORY_HEARING_AID = 6; 7018 7019 /** 7020 * @hide 7021 * Describes an audio device which was categorized as receiver. 7022 */ 7023 public static final int AUDIO_DEVICE_CATEGORY_RECEIVER = 7; 7024 7025 /** @hide */ 7026 @IntDef(flag = false, prefix = "AUDIO_DEVICE_CATEGORY", value = { 7027 AUDIO_DEVICE_CATEGORY_UNKNOWN, 7028 AUDIO_DEVICE_CATEGORY_OTHER, 7029 AUDIO_DEVICE_CATEGORY_SPEAKER, 7030 AUDIO_DEVICE_CATEGORY_HEADPHONES, 7031 AUDIO_DEVICE_CATEGORY_CARKIT, 7032 AUDIO_DEVICE_CATEGORY_WATCH, 7033 AUDIO_DEVICE_CATEGORY_HEARING_AID, 7034 AUDIO_DEVICE_CATEGORY_RECEIVER } 7035 ) 7036 @Retention(RetentionPolicy.SOURCE) 7037 public @interface AudioDeviceCategory {} 7038 7039 /** @hide */ audioDeviceCategoryToString(int audioDeviceCategory)7040 public static String audioDeviceCategoryToString(int audioDeviceCategory) { 7041 switch (audioDeviceCategory) { 7042 case AUDIO_DEVICE_CATEGORY_UNKNOWN: return "AUDIO_DEVICE_CATEGORY_UNKNOWN"; 7043 case AUDIO_DEVICE_CATEGORY_OTHER: return "AUDIO_DEVICE_CATEGORY_OTHER"; 7044 case AUDIO_DEVICE_CATEGORY_SPEAKER: return "AUDIO_DEVICE_CATEGORY_SPEAKER"; 7045 case AUDIO_DEVICE_CATEGORY_HEADPHONES: return "AUDIO_DEVICE_CATEGORY_HEADPHONES"; 7046 case AUDIO_DEVICE_CATEGORY_CARKIT: return "AUDIO_DEVICE_CATEGORY_CARKIT"; 7047 case AUDIO_DEVICE_CATEGORY_WATCH: return "AUDIO_DEVICE_CATEGORY_WATCH"; 7048 case AUDIO_DEVICE_CATEGORY_HEARING_AID: return "AUDIO_DEVICE_CATEGORY_HEARING_AID"; 7049 case AUDIO_DEVICE_CATEGORY_RECEIVER: return "AUDIO_DEVICE_CATEGORY_RECEIVER"; 7050 default: 7051 return new StringBuilder("unknown AudioDeviceCategory ").append( 7052 audioDeviceCategory).toString(); 7053 } 7054 } 7055 7056 /** 7057 * @hide 7058 * Sets the audio device type of a Bluetooth device given its MAC address 7059 */ 7060 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED) setBluetoothAudioDeviceCategory(@onNull String address, boolean isBle, @AudioDeviceCategory int btAudioDeviceType)7061 public void setBluetoothAudioDeviceCategory(@NonNull String address, boolean isBle, 7062 @AudioDeviceCategory int btAudioDeviceType) { 7063 try { 7064 getService().setBluetoothAudioDeviceCategory(address, isBle, btAudioDeviceType); 7065 } catch (RemoteException e) { 7066 throw e.rethrowFromSystemServer(); 7067 } 7068 } 7069 7070 /** 7071 * @hide 7072 * Gets the audio device type of a Bluetooth device given its MAC address 7073 */ 7074 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED) 7075 @AudioDeviceCategory getBluetoothAudioDeviceCategory(@onNull String address, boolean isBle)7076 public int getBluetoothAudioDeviceCategory(@NonNull String address, boolean isBle) { 7077 try { 7078 return getService().getBluetoothAudioDeviceCategory(address, isBle); 7079 } catch (RemoteException e) { 7080 throw e.rethrowFromSystemServer(); 7081 } 7082 } 7083 7084 /** 7085 * @hide 7086 * Sound dose warning at every 100% of dose during integration window 7087 */ 7088 public static final int CSD_WARNING_DOSE_REACHED_1X = 1; 7089 /** 7090 * @hide 7091 * Sound dose warning when 500% of dose is reached during integration window 7092 */ 7093 public static final int CSD_WARNING_DOSE_REPEATED_5X = 2; 7094 /** 7095 * @hide 7096 * Sound dose warning after a momentary exposure event 7097 */ 7098 public static final int CSD_WARNING_MOMENTARY_EXPOSURE = 3; 7099 /** 7100 * @hide 7101 * Sound dose warning at every 100% of dose during integration window 7102 */ 7103 public static final int CSD_WARNING_ACCUMULATION_START = 4; 7104 7105 /** @hide */ 7106 @IntDef(flag = false, value = { 7107 CSD_WARNING_DOSE_REACHED_1X, 7108 CSD_WARNING_DOSE_REPEATED_5X, 7109 CSD_WARNING_MOMENTARY_EXPOSURE, 7110 CSD_WARNING_ACCUMULATION_START } 7111 ) 7112 @Retention(RetentionPolicy.SOURCE) 7113 public @interface CsdWarning {} 7114 7115 /** 7116 * Only useful for volume controllers. 7117 * @hide 7118 */ 7119 @UnsupportedAppUsage setRingerModeInternal(int ringerMode)7120 public void setRingerModeInternal(int ringerMode) { 7121 try { 7122 getService().setRingerModeInternal(ringerMode, getContext().getOpPackageName()); 7123 } catch (RemoteException e) { 7124 throw e.rethrowFromSystemServer(); 7125 } 7126 } 7127 7128 /** 7129 * Only useful for volume controllers. 7130 * @hide 7131 */ 7132 @UnsupportedAppUsage getRingerModeInternal()7133 public int getRingerModeInternal() { 7134 try { 7135 return getService().getRingerModeInternal(); 7136 } catch (RemoteException e) { 7137 throw e.rethrowFromSystemServer(); 7138 } 7139 } 7140 7141 /** 7142 * Only useful for volume controllers. 7143 * @hide 7144 */ setVolumePolicy(VolumePolicy policy)7145 public void setVolumePolicy(VolumePolicy policy) { 7146 try { 7147 getService().setVolumePolicy(policy); 7148 } catch (RemoteException e) { 7149 throw e.rethrowFromSystemServer(); 7150 } 7151 } 7152 7153 /** 7154 * Set Hdmi Cec system audio mode. 7155 * 7156 * @param on whether to be on system audio mode 7157 * @return output device type. 0 (DEVICE_NONE) if failed to set device. 7158 * @hide 7159 */ setHdmiSystemAudioSupported(boolean on)7160 public int setHdmiSystemAudioSupported(boolean on) { 7161 try { 7162 return getService().setHdmiSystemAudioSupported(on); 7163 } catch (RemoteException e) { 7164 throw e.rethrowFromSystemServer(); 7165 } 7166 } 7167 7168 /** 7169 * Returns true if Hdmi Cec system audio mode is supported. 7170 * 7171 * @hide 7172 */ 7173 @SystemApi 7174 @SuppressLint("RequiresPermission") // FIXME is this still used? isHdmiSystemAudioSupported()7175 public boolean isHdmiSystemAudioSupported() { 7176 try { 7177 return getService().isHdmiSystemAudioSupported(); 7178 } catch (RemoteException e) { 7179 throw e.rethrowFromSystemServer(); 7180 } 7181 } 7182 7183 /** 7184 * Return codes for listAudioPorts(), createAudioPatch() ... 7185 */ 7186 7187 /** @hide */ 7188 @SystemApi 7189 public static final int SUCCESS = AudioSystem.SUCCESS; 7190 /** 7191 * A default error code. 7192 */ 7193 public static final int ERROR = AudioSystem.ERROR; 7194 /** @hide 7195 * CANDIDATE FOR PUBLIC API 7196 */ 7197 public static final int ERROR_BAD_VALUE = AudioSystem.BAD_VALUE; 7198 /** @hide 7199 */ 7200 public static final int ERROR_INVALID_OPERATION = AudioSystem.INVALID_OPERATION; 7201 /** @hide 7202 */ 7203 public static final int ERROR_PERMISSION_DENIED = AudioSystem.PERMISSION_DENIED; 7204 /** @hide 7205 */ 7206 public static final int ERROR_NO_INIT = AudioSystem.NO_INIT; 7207 /** 7208 * An error code indicating that the object reporting it is no longer valid and needs to 7209 * be recreated. 7210 */ 7211 public static final int ERROR_DEAD_OBJECT = AudioSystem.DEAD_OBJECT; 7212 7213 /** 7214 * Returns a list of descriptors for all audio ports managed by the audio framework. 7215 * Audio ports are nodes in the audio framework or audio hardware that can be configured 7216 * or connected and disconnected with createAudioPatch() or releaseAudioPatch(). 7217 * See AudioPort for a list of attributes of each audio port. 7218 * @param ports An AudioPort ArrayList where the list will be returned. 7219 * @hide 7220 */ 7221 @UnsupportedAppUsage listAudioPorts(ArrayList<AudioPort> ports)7222 public static int listAudioPorts(ArrayList<AudioPort> ports) { 7223 return updateAudioPortCache(ports, null, null); 7224 } 7225 7226 /** 7227 * Returns a list of descriptors for all audio ports managed by the audio framework as 7228 * it was before the last update calback. 7229 * @param ports An AudioPort ArrayList where the list will be returned. 7230 * @hide 7231 */ listPreviousAudioPorts(ArrayList<AudioPort> ports)7232 public static int listPreviousAudioPorts(ArrayList<AudioPort> ports) { 7233 return updateAudioPortCache(null, null, ports); 7234 } 7235 7236 /** 7237 * Specialized version of listAudioPorts() listing only audio devices (AudioDevicePort) 7238 * @see listAudioPorts(ArrayList<AudioPort>) 7239 * @hide 7240 */ listAudioDevicePorts(ArrayList<AudioDevicePort> devices)7241 public static int listAudioDevicePorts(ArrayList<AudioDevicePort> devices) { 7242 if (devices == null) { 7243 return ERROR_BAD_VALUE; 7244 } 7245 ArrayList<AudioPort> ports = new ArrayList<AudioPort>(); 7246 int status = updateAudioPortCache(ports, null, null); 7247 if (status == SUCCESS) { 7248 filterDevicePorts(ports, devices); 7249 } 7250 return status; 7251 } 7252 7253 /** 7254 * Specialized version of listPreviousAudioPorts() listing only audio devices (AudioDevicePort) 7255 * @see listPreviousAudioPorts(ArrayList<AudioPort>) 7256 * @hide 7257 */ listPreviousAudioDevicePorts(ArrayList<AudioDevicePort> devices)7258 public static int listPreviousAudioDevicePorts(ArrayList<AudioDevicePort> devices) { 7259 if (devices == null) { 7260 return ERROR_BAD_VALUE; 7261 } 7262 ArrayList<AudioPort> ports = new ArrayList<AudioPort>(); 7263 int status = updateAudioPortCache(null, null, ports); 7264 if (status == SUCCESS) { 7265 filterDevicePorts(ports, devices); 7266 } 7267 return status; 7268 } 7269 filterDevicePorts(ArrayList<AudioPort> ports, ArrayList<AudioDevicePort> devices)7270 private static void filterDevicePorts(ArrayList<AudioPort> ports, 7271 ArrayList<AudioDevicePort> devices) { 7272 devices.clear(); 7273 for (int i = 0; i < ports.size(); i++) { 7274 if (ports.get(i) instanceof AudioDevicePort) { 7275 devices.add((AudioDevicePort)ports.get(i)); 7276 } 7277 } 7278 } 7279 7280 /** 7281 * Create a connection between two or more devices. The framework will reject the request if 7282 * device types are not compatible or the implementation does not support the requested 7283 * configuration. 7284 * NOTE: current implementation is limited to one source and one sink per patch. 7285 * @param patch AudioPatch array where the newly created patch will be returned. 7286 * As input, if patch[0] is not null, the specified patch will be replaced by the 7287 * new patch created. This avoids calling releaseAudioPatch() when modifying a 7288 * patch and allows the implementation to optimize transitions. 7289 * @param sources List of source audio ports. All must be AudioPort.ROLE_SOURCE. 7290 * @param sinks List of sink audio ports. All must be AudioPort.ROLE_SINK. 7291 * 7292 * @return - {@link #SUCCESS} if connection is successful. 7293 * - {@link #ERROR_BAD_VALUE} if incompatible device types are passed. 7294 * - {@link #ERROR_INVALID_OPERATION} if the requested connection is not supported. 7295 * - {@link #ERROR_PERMISSION_DENIED} if the client does not have permission to create 7296 * a patch. 7297 * - {@link #ERROR_DEAD_OBJECT} if the server process is dead 7298 * - {@link #ERROR} if patch cannot be connected for any other reason. 7299 * 7300 * patch[0] contains the newly created patch 7301 * @hide 7302 */ 7303 @UnsupportedAppUsage createAudioPatch(AudioPatch[] patch, AudioPortConfig[] sources, AudioPortConfig[] sinks)7304 public static int createAudioPatch(AudioPatch[] patch, 7305 AudioPortConfig[] sources, 7306 AudioPortConfig[] sinks) { 7307 return AudioSystem.createAudioPatch(patch, sources, sinks); 7308 } 7309 7310 /** 7311 * Releases an existing audio patch connection. 7312 * @param patch The audio patch to disconnect. 7313 * @return - {@link #SUCCESS} if disconnection is successful. 7314 * - {@link #ERROR_BAD_VALUE} if the specified patch does not exist. 7315 * - {@link #ERROR_PERMISSION_DENIED} if the client does not have permission to release 7316 * a patch. 7317 * - {@link #ERROR_DEAD_OBJECT} if the server process is dead 7318 * - {@link #ERROR} if patch cannot be released for any other reason. 7319 * @hide 7320 */ 7321 @UnsupportedAppUsage releaseAudioPatch(AudioPatch patch)7322 public static int releaseAudioPatch(AudioPatch patch) { 7323 return AudioSystem.releaseAudioPatch(patch); 7324 } 7325 7326 /** 7327 * List all existing connections between audio ports. 7328 * @param patches An AudioPatch array where the list will be returned. 7329 * @hide 7330 */ 7331 @UnsupportedAppUsage listAudioPatches(ArrayList<AudioPatch> patches)7332 public static int listAudioPatches(ArrayList<AudioPatch> patches) { 7333 return updateAudioPortCache(null, patches, null); 7334 } 7335 7336 /** 7337 * Set the gain on the specified AudioPort. The AudioGainConfig config is build by 7338 * AudioGain.buildConfig() 7339 * @hide 7340 */ setAudioPortGain(AudioPort port, AudioGainConfig gain)7341 public static int setAudioPortGain(AudioPort port, AudioGainConfig gain) { 7342 if (port == null || gain == null) { 7343 return ERROR_BAD_VALUE; 7344 } 7345 AudioPortConfig activeConfig = port.activeConfig(); 7346 AudioPortConfig config = new AudioPortConfig(port, activeConfig.samplingRate(), 7347 activeConfig.channelMask(), activeConfig.format(), gain); 7348 config.mConfigMask = AudioPortConfig.GAIN; 7349 return AudioSystem.setAudioPortConfig(config); 7350 } 7351 7352 /** 7353 * Listener registered by client to be notified upon new audio port connections, 7354 * disconnections or attributes update. 7355 * @hide 7356 */ 7357 public interface OnAudioPortUpdateListener { 7358 /** 7359 * Callback method called upon audio port list update. 7360 * @param portList the updated list of audio ports 7361 */ onAudioPortListUpdate(AudioPort[] portList)7362 public void onAudioPortListUpdate(AudioPort[] portList); 7363 7364 /** 7365 * Callback method called upon audio patch list update. 7366 * @param patchList the updated list of audio patches 7367 */ onAudioPatchListUpdate(AudioPatch[] patchList)7368 public void onAudioPatchListUpdate(AudioPatch[] patchList); 7369 7370 /** 7371 * Callback method called when the mediaserver dies 7372 */ onServiceDied()7373 public void onServiceDied(); 7374 } 7375 7376 /** 7377 * Register an audio port list update listener. 7378 * @hide 7379 */ 7380 @UnsupportedAppUsage registerAudioPortUpdateListener(OnAudioPortUpdateListener l)7381 public void registerAudioPortUpdateListener(OnAudioPortUpdateListener l) { 7382 sAudioPortEventHandler.init(); 7383 sAudioPortEventHandler.registerListener(l); 7384 } 7385 7386 /** 7387 * Unregister an audio port list update listener. 7388 * @hide 7389 */ 7390 @UnsupportedAppUsage unregisterAudioPortUpdateListener(OnAudioPortUpdateListener l)7391 public void unregisterAudioPortUpdateListener(OnAudioPortUpdateListener l) { 7392 sAudioPortEventHandler.unregisterListener(l); 7393 } 7394 7395 // 7396 // AudioPort implementation 7397 // 7398 7399 private static final int AUDIOPORT_GENERATION_INIT = 0; 7400 private static Object sAudioPortGenerationLock = new Object(); 7401 @GuardedBy("sAudioPortGenerationLock") 7402 private static int sAudioPortGeneration = AUDIOPORT_GENERATION_INIT; 7403 private static ArrayList<AudioPort> sAudioPortsCached = new ArrayList<AudioPort>(); 7404 private static ArrayList<AudioPort> sPreviousAudioPortsCached = new ArrayList<AudioPort>(); 7405 private static ArrayList<AudioPatch> sAudioPatchesCached = new ArrayList<AudioPatch>(); 7406 resetAudioPortGeneration()7407 static int resetAudioPortGeneration() { 7408 int generation; 7409 synchronized (sAudioPortGenerationLock) { 7410 generation = sAudioPortGeneration; 7411 sAudioPortGeneration = AUDIOPORT_GENERATION_INIT; 7412 } 7413 return generation; 7414 } 7415 updateAudioPortCache(ArrayList<AudioPort> ports, ArrayList<AudioPatch> patches, ArrayList<AudioPort> previousPorts)7416 static int updateAudioPortCache(ArrayList<AudioPort> ports, ArrayList<AudioPatch> patches, 7417 ArrayList<AudioPort> previousPorts) { 7418 sAudioPortEventHandler.init(); 7419 synchronized (sAudioPortGenerationLock) { 7420 7421 if (sAudioPortGeneration == AUDIOPORT_GENERATION_INIT) { 7422 int[] patchGeneration = new int[1]; 7423 int[] portGeneration = new int[1]; 7424 int status; 7425 ArrayList<AudioPort> newPorts = new ArrayList<AudioPort>(); 7426 ArrayList<AudioPatch> newPatches = new ArrayList<AudioPatch>(); 7427 7428 do { 7429 newPorts.clear(); 7430 status = AudioSystem.listAudioPorts(newPorts, portGeneration); 7431 if (status != SUCCESS) { 7432 Log.w(TAG, "updateAudioPortCache: listAudioPorts failed"); 7433 return status; 7434 } 7435 newPatches.clear(); 7436 status = AudioSystem.listAudioPatches(newPatches, patchGeneration); 7437 if (status != SUCCESS) { 7438 Log.w(TAG, "updateAudioPortCache: listAudioPatches failed"); 7439 return status; 7440 } 7441 // Loop until patch generation is the same as port generation unless audio ports 7442 // and audio patches are not null. 7443 } while (patchGeneration[0] != portGeneration[0] 7444 && (ports == null || patches == null)); 7445 // If the patch generation doesn't equal port generation, return ERROR here in case 7446 // of mismatch between audio ports and audio patches. 7447 if (patchGeneration[0] != portGeneration[0]) { 7448 return ERROR; 7449 } 7450 7451 for (int i = 0; i < newPatches.size(); i++) { 7452 for (int j = 0; j < newPatches.get(i).sources().length; j++) { 7453 AudioPortConfig portCfg = updatePortConfig(newPatches.get(i).sources()[j], 7454 newPorts); 7455 newPatches.get(i).sources()[j] = portCfg; 7456 } 7457 for (int j = 0; j < newPatches.get(i).sinks().length; j++) { 7458 AudioPortConfig portCfg = updatePortConfig(newPatches.get(i).sinks()[j], 7459 newPorts); 7460 newPatches.get(i).sinks()[j] = portCfg; 7461 } 7462 } 7463 for (Iterator<AudioPatch> i = newPatches.iterator(); i.hasNext(); ) { 7464 AudioPatch newPatch = i.next(); 7465 boolean hasInvalidPort = false; 7466 for (AudioPortConfig portCfg : newPatch.sources()) { 7467 if (portCfg == null) { 7468 hasInvalidPort = true; 7469 break; 7470 } 7471 } 7472 for (AudioPortConfig portCfg : newPatch.sinks()) { 7473 if (portCfg == null) { 7474 hasInvalidPort = true; 7475 break; 7476 } 7477 } 7478 if (hasInvalidPort) { 7479 // Temporarily remove patches with invalid ports. One who created the patch 7480 // is responsible for dealing with the port change. 7481 i.remove(); 7482 } 7483 } 7484 7485 sPreviousAudioPortsCached = sAudioPortsCached; 7486 sAudioPortsCached = newPorts; 7487 sAudioPatchesCached = newPatches; 7488 sAudioPortGeneration = portGeneration[0]; 7489 } 7490 if (ports != null) { 7491 ports.clear(); 7492 ports.addAll(sAudioPortsCached); 7493 } 7494 if (patches != null) { 7495 patches.clear(); 7496 patches.addAll(sAudioPatchesCached); 7497 } 7498 if (previousPorts != null) { 7499 previousPorts.clear(); 7500 previousPorts.addAll(sPreviousAudioPortsCached); 7501 } 7502 } 7503 return SUCCESS; 7504 } 7505 updatePortConfig(AudioPortConfig portCfg, ArrayList<AudioPort> ports)7506 static AudioPortConfig updatePortConfig(AudioPortConfig portCfg, ArrayList<AudioPort> ports) { 7507 AudioPort port = portCfg.port(); 7508 int k; 7509 for (k = 0; k < ports.size(); k++) { 7510 // compare handles because the port returned by JNI is not of the correct 7511 // subclass 7512 if (ports.get(k).handle().equals(port.handle())) { 7513 port = ports.get(k); 7514 break; 7515 } 7516 } 7517 if (k == ports.size()) { 7518 // This can happen in case of stale audio patch referring to a removed device and is 7519 // handled by the caller. 7520 return null; 7521 } 7522 AudioGainConfig gainCfg = portCfg.gain(); 7523 if (gainCfg != null) { 7524 AudioGain gain = port.gain(gainCfg.index()); 7525 gainCfg = gain.buildConfig(gainCfg.mode(), 7526 gainCfg.channelMask(), 7527 gainCfg.values(), 7528 gainCfg.rampDurationMs()); 7529 } 7530 return port.buildConfig(portCfg.samplingRate(), 7531 portCfg.channelMask(), 7532 portCfg.format(), 7533 gainCfg); 7534 } 7535 7536 private OnAmPortUpdateListener mPortListener = null; 7537 7538 /** 7539 * The message sent to apps when the contents of the device list changes if they provide 7540 * a {@link Handler} object to {@link registerAudioDeviceCallback}. 7541 */ 7542 private final static int MSG_DEVICES_CALLBACK_REGISTERED = 0; 7543 private final static int MSG_DEVICES_DEVICES_ADDED = 1; 7544 private final static int MSG_DEVICES_DEVICES_REMOVED = 2; 7545 7546 /** 7547 * The list of {@link AudioDeviceCallback} objects to receive add/remove notifications. 7548 */ 7549 private final ArrayMap<AudioDeviceCallback, NativeEventHandlerDelegate> mDeviceCallbacks = 7550 new ArrayMap<AudioDeviceCallback, NativeEventHandlerDelegate>(); 7551 7552 /** 7553 * The following are flags to allow users of {@link AudioManager#getDevices(int)} to filter 7554 * the results list to only those device types they are interested in. 7555 */ 7556 /** 7557 * Specifies to the {@link AudioManager#getDevices(int)} method to include 7558 * source (i.e. input) audio devices. 7559 */ 7560 public static final int GET_DEVICES_INPUTS = 0x0001; 7561 7562 /** 7563 * Specifies to the {@link AudioManager#getDevices(int)} method to include 7564 * sink (i.e. output) audio devices. 7565 */ 7566 public static final int GET_DEVICES_OUTPUTS = 0x0002; 7567 7568 /** @hide */ 7569 @IntDef(flag = true, prefix = "GET_DEVICES", value = { 7570 GET_DEVICES_INPUTS, 7571 GET_DEVICES_OUTPUTS } 7572 ) 7573 @Retention(RetentionPolicy.SOURCE) 7574 public @interface AudioDeviceRole {} 7575 7576 /** 7577 * Specifies to the {@link AudioManager#getDevices(int)} method to include both 7578 * source and sink devices. 7579 */ 7580 public static final int GET_DEVICES_ALL = GET_DEVICES_OUTPUTS | GET_DEVICES_INPUTS; 7581 7582 /** 7583 * Determines if a given AudioDevicePort meets the specified filter criteria. 7584 * @param port The port to test. 7585 * @param flags A set of bitflags specifying the criteria to test. 7586 * @see {@link GET_DEVICES_OUTPUTS} and {@link GET_DEVICES_INPUTS} 7587 **/ checkFlags(AudioDevicePort port, int flags)7588 private static boolean checkFlags(AudioDevicePort port, int flags) { 7589 return port.role() == AudioPort.ROLE_SINK && (flags & GET_DEVICES_OUTPUTS) != 0 || 7590 port.role() == AudioPort.ROLE_SOURCE && (flags & GET_DEVICES_INPUTS) != 0; 7591 } 7592 checkTypes(AudioDevicePort port)7593 private static boolean checkTypes(AudioDevicePort port) { 7594 return AudioDeviceInfo.convertInternalDeviceToDeviceType(port.type()) != 7595 AudioDeviceInfo.TYPE_UNKNOWN; 7596 } 7597 7598 /** 7599 * Returns an array of {@link AudioDeviceInfo} objects corresponding to the audio devices 7600 * currently connected to the system and meeting the criteria specified in the 7601 * <code>flags</code> parameter. 7602 * Notes that Android audio framework only support one device per device type. In that case, 7603 * if there are multiple audio device with the same device type connected to the Android device, 7604 * only the last reported device will be known by Android audio framework and returned by this 7605 * API. 7606 * @param flags A set of bitflags specifying the criteria to test. 7607 * @see #GET_DEVICES_OUTPUTS 7608 * @see #GET_DEVICES_INPUTS 7609 * @see #GET_DEVICES_ALL 7610 * @return A (possibly zero-length) array of AudioDeviceInfo objects. 7611 */ getDevices(@udioDeviceRole int flags)7612 public AudioDeviceInfo[] getDevices(@AudioDeviceRole int flags) { 7613 return getDevicesStatic(flags); 7614 } 7615 7616 /** 7617 * Does the actual computation to generate an array of (externally-visible) AudioDeviceInfo 7618 * objects from the current (internal) AudioDevicePort list. 7619 */ 7620 private static AudioDeviceInfo[] infoListFromPortList(ArrayList<AudioDevicePort> ports, int flags)7621 infoListFromPortList(ArrayList<AudioDevicePort> ports, int flags) { 7622 7623 // figure out how many AudioDeviceInfo we need space for... 7624 int numRecs = 0; 7625 for (AudioDevicePort port : ports) { 7626 if (checkTypes(port) && checkFlags(port, flags)) { 7627 numRecs++; 7628 } 7629 } 7630 7631 // Now load them up... 7632 AudioDeviceInfo[] deviceList = new AudioDeviceInfo[numRecs]; 7633 int slot = 0; 7634 for (AudioDevicePort port : ports) { 7635 if (checkTypes(port) && checkFlags(port, flags)) { 7636 deviceList[slot++] = new AudioDeviceInfo(port); 7637 } 7638 } 7639 7640 return deviceList; 7641 } 7642 7643 /* 7644 * Calculate the list of ports that are in ports_B, but not in ports_A. This is used by 7645 * the add/remove callback mechanism to provide a list of the newly added or removed devices 7646 * rather than the whole list and make the app figure it out. 7647 * Note that calling this method with: 7648 * ports_A == PREVIOUS_ports and ports_B == CURRENT_ports will calculated ADDED ports. 7649 * ports_A == CURRENT_ports and ports_B == PREVIOUS_ports will calculated REMOVED ports. 7650 */ calcListDeltas( ArrayList<AudioDevicePort> ports_A, ArrayList<AudioDevicePort> ports_B, int flags)7651 private static AudioDeviceInfo[] calcListDeltas( 7652 ArrayList<AudioDevicePort> ports_A, ArrayList<AudioDevicePort> ports_B, int flags) { 7653 7654 ArrayList<AudioDevicePort> delta_ports = new ArrayList<AudioDevicePort>(); 7655 7656 AudioDevicePort cur_port = null; 7657 for (int cur_index = 0; cur_index < ports_B.size(); cur_index++) { 7658 boolean cur_port_found = false; 7659 cur_port = ports_B.get(cur_index); 7660 for (int prev_index = 0; 7661 prev_index < ports_A.size() && !cur_port_found; 7662 prev_index++) { 7663 cur_port_found = (cur_port.id() == ports_A.get(prev_index).id()); 7664 } 7665 7666 if (!cur_port_found) { 7667 delta_ports.add(cur_port); 7668 } 7669 } 7670 7671 return infoListFromPortList(delta_ports, flags); 7672 } 7673 7674 /** 7675 * Generates a list of AudioDeviceInfo objects corresponding to the audio devices currently 7676 * connected to the system and meeting the criteria specified in the <code>flags</code> 7677 * parameter. 7678 * This is an internal function. The public API front is getDevices(int). 7679 * @param flags A set of bitflags specifying the criteria to test. 7680 * @see #GET_DEVICES_OUTPUTS 7681 * @see #GET_DEVICES_INPUTS 7682 * @see #GET_DEVICES_ALL 7683 * @return A (possibly zero-length) array of AudioDeviceInfo objects. 7684 * @hide 7685 */ getDevicesStatic(int flags)7686 public static AudioDeviceInfo[] getDevicesStatic(int flags) { 7687 ArrayList<AudioDevicePort> ports = new ArrayList<AudioDevicePort>(); 7688 int status = AudioManager.listAudioDevicePorts(ports); 7689 if (status != AudioManager.SUCCESS) { 7690 // fail and bail! 7691 return new AudioDeviceInfo[0]; // Always return an array. 7692 } 7693 7694 return infoListFromPortList(ports, flags); 7695 } 7696 7697 /** 7698 * Returns an {@link AudioDeviceInfo} corresponding to the specified {@link AudioPort} ID. 7699 * @param portId The audio port ID to look up for. 7700 * @param flags A set of bitflags specifying the criteria to test. 7701 * @see #GET_DEVICES_OUTPUTS 7702 * @see #GET_DEVICES_INPUTS 7703 * @see #GET_DEVICES_ALL 7704 * @return An AudioDeviceInfo or null if no device with matching port ID is found. 7705 * @hide 7706 */ getDeviceForPortId(int portId, int flags)7707 public static AudioDeviceInfo getDeviceForPortId(int portId, int flags) { 7708 if (portId == 0) { 7709 return null; 7710 } 7711 AudioDeviceInfo[] devices = getDevicesStatic(flags); 7712 for (AudioDeviceInfo device : devices) { 7713 if (device.getId() == portId) { 7714 return device; 7715 } 7716 } 7717 return null; 7718 } 7719 7720 /** 7721 * Registers an {@link AudioDeviceCallback} object to receive notifications of changes 7722 * to the set of connected audio devices. 7723 * @param callback The {@link AudioDeviceCallback} object to receive connect/disconnect 7724 * notifications. 7725 * @param handler Specifies the {@link Handler} object for the thread on which to execute 7726 * the callback. If <code>null</code>, the {@link Handler} associated with the main 7727 * {@link Looper} will be used. 7728 */ registerAudioDeviceCallback(AudioDeviceCallback callback, @Nullable Handler handler)7729 public void registerAudioDeviceCallback(AudioDeviceCallback callback, 7730 @Nullable Handler handler) { 7731 synchronized (mDeviceCallbacks) { 7732 if (callback != null && !mDeviceCallbacks.containsKey(callback)) { 7733 if (mDeviceCallbacks.size() == 0) { 7734 if (mPortListener == null) { 7735 mPortListener = new OnAmPortUpdateListener(); 7736 } 7737 registerAudioPortUpdateListener(mPortListener); 7738 } 7739 NativeEventHandlerDelegate delegate = 7740 new NativeEventHandlerDelegate(callback, handler); 7741 mDeviceCallbacks.put(callback, delegate); 7742 broadcastDeviceListChange_sync(delegate.getHandler()); 7743 } 7744 } 7745 } 7746 7747 /** 7748 * Unregisters an {@link AudioDeviceCallback} object which has been previously registered 7749 * to receive notifications of changes to the set of connected audio devices. 7750 * @param callback The {@link AudioDeviceCallback} object that was previously registered 7751 * with {@link AudioManager#registerAudioDeviceCallback} to be unregistered. 7752 */ unregisterAudioDeviceCallback(AudioDeviceCallback callback)7753 public void unregisterAudioDeviceCallback(AudioDeviceCallback callback) { 7754 synchronized (mDeviceCallbacks) { 7755 if (mDeviceCallbacks.containsKey(callback)) { 7756 mDeviceCallbacks.remove(callback); 7757 if (mDeviceCallbacks.size() == 0) { 7758 unregisterAudioPortUpdateListener(mPortListener); 7759 } 7760 } 7761 } 7762 } 7763 7764 /** 7765 * Set port id for microphones by matching device type and address. 7766 * @hide 7767 */ setPortIdForMicrophones(ArrayList<MicrophoneInfo> microphones)7768 public static void setPortIdForMicrophones(ArrayList<MicrophoneInfo> microphones) { 7769 AudioDeviceInfo[] devices = getDevicesStatic(AudioManager.GET_DEVICES_INPUTS); 7770 for (int i = microphones.size() - 1; i >= 0; i--) { 7771 boolean foundPortId = false; 7772 for (AudioDeviceInfo device : devices) { 7773 if (device.getPort().type() == microphones.get(i).getInternalDeviceType() 7774 && TextUtils.equals(device.getAddress(), microphones.get(i).getAddress())) { 7775 microphones.get(i).setId(device.getId()); 7776 foundPortId = true; 7777 break; 7778 } 7779 } 7780 if (!foundPortId) { 7781 Log.i(TAG, "Failed to find port id for device with type:" 7782 + microphones.get(i).getType() + " address:" 7783 + microphones.get(i).getAddress()); 7784 microphones.remove(i); 7785 } 7786 } 7787 } 7788 7789 /** 7790 * Convert {@link AudioDeviceInfo} to {@link MicrophoneInfo}. 7791 * @hide 7792 */ microphoneInfoFromAudioDeviceInfo(AudioDeviceInfo deviceInfo)7793 public static MicrophoneInfo microphoneInfoFromAudioDeviceInfo(AudioDeviceInfo deviceInfo) { 7794 int deviceType = deviceInfo.getType(); 7795 int micLocation = (deviceType == AudioDeviceInfo.TYPE_BUILTIN_MIC 7796 || deviceType == AudioDeviceInfo.TYPE_TELEPHONY) ? MicrophoneInfo.LOCATION_MAINBODY 7797 : deviceType == AudioDeviceInfo.TYPE_UNKNOWN ? MicrophoneInfo.LOCATION_UNKNOWN 7798 : MicrophoneInfo.LOCATION_PERIPHERAL; 7799 MicrophoneInfo microphone = new MicrophoneInfo( 7800 deviceInfo.getPort().name() + deviceInfo.getId(), 7801 deviceInfo.getPort().type(), deviceInfo.getAddress(), micLocation, 7802 MicrophoneInfo.GROUP_UNKNOWN, MicrophoneInfo.INDEX_IN_THE_GROUP_UNKNOWN, 7803 MicrophoneInfo.POSITION_UNKNOWN, MicrophoneInfo.ORIENTATION_UNKNOWN, 7804 new ArrayList<Pair<Float, Float>>(), new ArrayList<Pair<Integer, Integer>>(), 7805 MicrophoneInfo.SENSITIVITY_UNKNOWN, MicrophoneInfo.SPL_UNKNOWN, 7806 MicrophoneInfo.SPL_UNKNOWN, MicrophoneInfo.DIRECTIONALITY_UNKNOWN); 7807 microphone.setId(deviceInfo.getId()); 7808 return microphone; 7809 } 7810 7811 /** 7812 * Add {@link MicrophoneInfo} by device information while filtering certain types. 7813 */ addMicrophonesFromAudioDeviceInfo(ArrayList<MicrophoneInfo> microphones, HashSet<Integer> filterTypes)7814 private void addMicrophonesFromAudioDeviceInfo(ArrayList<MicrophoneInfo> microphones, 7815 HashSet<Integer> filterTypes) { 7816 AudioDeviceInfo[] devices = getDevicesStatic(GET_DEVICES_INPUTS); 7817 for (AudioDeviceInfo device : devices) { 7818 if (filterTypes.contains(device.getType())) { 7819 continue; 7820 } 7821 MicrophoneInfo microphone = microphoneInfoFromAudioDeviceInfo(device); 7822 microphones.add(microphone); 7823 } 7824 } 7825 7826 /** 7827 * Returns a list of {@link MicrophoneInfo} that corresponds to the characteristics 7828 * of all available microphones. The list is empty when no microphones are available 7829 * on the device. An error during the query will result in an IOException being thrown. 7830 * 7831 * @return a list that contains all microphones' characteristics 7832 * @throws IOException if an error occurs. 7833 */ getMicrophones()7834 public List<MicrophoneInfo> getMicrophones() throws IOException { 7835 ArrayList<MicrophoneInfo> microphones = new ArrayList<MicrophoneInfo>(); 7836 int status = AudioSystem.getMicrophones(microphones); 7837 HashSet<Integer> filterTypes = new HashSet<>(); 7838 filterTypes.add(AudioDeviceInfo.TYPE_TELEPHONY); 7839 if (status != AudioManager.SUCCESS) { 7840 // fail and populate microphones with unknown characteristics by device information. 7841 if (status != AudioManager.ERROR_INVALID_OPERATION) { 7842 Log.e(TAG, "getMicrophones failed:" + status); 7843 } 7844 Log.i(TAG, "fallback on device info"); 7845 addMicrophonesFromAudioDeviceInfo(microphones, filterTypes); 7846 return microphones; 7847 } 7848 setPortIdForMicrophones(microphones); 7849 filterTypes.add(AudioDeviceInfo.TYPE_BUILTIN_MIC); 7850 addMicrophonesFromAudioDeviceInfo(microphones, filterTypes); 7851 return microphones; 7852 } 7853 7854 /** 7855 * Returns a list of audio formats that corresponds to encoding formats 7856 * supported on offload path for A2DP playback. 7857 * 7858 * @return a list of {@link BluetoothCodecConfig} objects containing encoding formats 7859 * supported for offload A2DP playback 7860 * @hide 7861 */ 7862 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) getHwOffloadFormatsSupportedForA2dp()7863 public @NonNull List<BluetoothCodecConfig> getHwOffloadFormatsSupportedForA2dp() { 7864 ArrayList<Integer> formatsList = new ArrayList<>(); 7865 ArrayList<BluetoothCodecConfig> codecConfigList = new ArrayList<>(); 7866 7867 int status = AudioSystem.getHwOffloadFormatsSupportedForBluetoothMedia( 7868 AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, formatsList); 7869 if (status != AudioManager.SUCCESS) { 7870 Log.e(TAG, "getHwOffloadEncodingFormatsSupportedForA2DP failed:" + status); 7871 return codecConfigList; 7872 } 7873 7874 for (Integer format : formatsList) { 7875 int btSourceCodec = AudioSystem.audioFormatToBluetoothSourceCodec(format); 7876 if (btSourceCodec != BluetoothCodecConfig.SOURCE_CODEC_TYPE_INVALID) { 7877 codecConfigList.add( 7878 new BluetoothCodecConfig.Builder().setCodecType(btSourceCodec).build()); 7879 } 7880 } 7881 return codecConfigList; 7882 } 7883 getHwOffloadFormatsSupportedForLeAudio( @udioSystem.BtOffloadDeviceType int deviceType)7884 private List<BluetoothLeAudioCodecConfig> getHwOffloadFormatsSupportedForLeAudio( 7885 @AudioSystem.BtOffloadDeviceType int deviceType) { 7886 ArrayList<Integer> formatsList = new ArrayList<>(); 7887 ArrayList<BluetoothLeAudioCodecConfig> leAudioCodecConfigList = new ArrayList<>(); 7888 7889 int status = AudioSystem.getHwOffloadFormatsSupportedForBluetoothMedia( 7890 deviceType, formatsList); 7891 if (status != AudioManager.SUCCESS) { 7892 Log.e(TAG, "getHwOffloadEncodingFormatsSupportedForLeAudio failed:" + status); 7893 return leAudioCodecConfigList; 7894 } 7895 7896 for (Integer format : formatsList) { 7897 int btLeAudioCodec = AudioSystem.audioFormatToBluetoothLeAudioSourceCodec(format); 7898 if (btLeAudioCodec != BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_INVALID) { 7899 leAudioCodecConfigList.add(new BluetoothLeAudioCodecConfig.Builder() 7900 .setCodecType(btLeAudioCodec) 7901 .build()); 7902 } 7903 } 7904 return leAudioCodecConfigList; 7905 } 7906 7907 /** 7908 * Returns a list of audio formats that corresponds to encoding formats 7909 * supported on offload path for Le audio playback. 7910 * 7911 * @return a list of {@link BluetoothLeAudioCodecConfig} objects containing encoding formats 7912 * supported for offload Le Audio playback 7913 * @hide 7914 */ 7915 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 7916 @NonNull getHwOffloadFormatsSupportedForLeAudio()7917 public List<BluetoothLeAudioCodecConfig> getHwOffloadFormatsSupportedForLeAudio() { 7918 return getHwOffloadFormatsSupportedForLeAudio(AudioSystem.DEVICE_OUT_BLE_HEADSET); 7919 } 7920 7921 /** 7922 * Returns a list of audio formats that corresponds to encoding formats 7923 * supported on offload path for Le Broadcast playback. 7924 * 7925 * @return a list of {@link BluetoothLeAudioCodecConfig} objects containing encoding formats 7926 * supported for offload Le Broadcast playback 7927 * @hide 7928 */ 7929 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 7930 @NonNull getHwOffloadFormatsSupportedForLeBroadcast()7931 public List<BluetoothLeAudioCodecConfig> getHwOffloadFormatsSupportedForLeBroadcast() { 7932 return getHwOffloadFormatsSupportedForLeAudio(AudioSystem.DEVICE_OUT_BLE_BROADCAST); 7933 } 7934 7935 // Since we need to calculate the changes since THE LAST NOTIFICATION, and not since the 7936 // (unpredictable) last time updateAudioPortCache() was called by someone, keep a list 7937 // of the ports that exist at the time of the last notification. 7938 private ArrayList<AudioDevicePort> mPreviousPorts = new ArrayList<AudioDevicePort>(); 7939 7940 /** 7941 * Internal method to compute and generate add/remove messages and then send to any 7942 * registered callbacks. Must be called synchronized on mDeviceCallbacks. 7943 */ broadcastDeviceListChange_sync(Handler handler)7944 private void broadcastDeviceListChange_sync(Handler handler) { 7945 int status; 7946 7947 // Get the new current set of ports 7948 ArrayList<AudioDevicePort> current_ports = new ArrayList<AudioDevicePort>(); 7949 status = AudioManager.listAudioDevicePorts(current_ports); 7950 if (status != AudioManager.SUCCESS) { 7951 return; 7952 } 7953 7954 if (handler != null) { 7955 // This is the callback for the registration, so send the current list 7956 AudioDeviceInfo[] deviceList = 7957 infoListFromPortList(current_ports, GET_DEVICES_ALL); 7958 handler.sendMessage( 7959 Message.obtain(handler, MSG_DEVICES_CALLBACK_REGISTERED, deviceList)); 7960 } else { 7961 AudioDeviceInfo[] added_devices = 7962 calcListDeltas(mPreviousPorts, current_ports, GET_DEVICES_ALL); 7963 AudioDeviceInfo[] removed_devices = 7964 calcListDeltas(current_ports, mPreviousPorts, GET_DEVICES_ALL); 7965 if (added_devices.length != 0 || removed_devices.length != 0) { 7966 for (int i = 0; i < mDeviceCallbacks.size(); i++) { 7967 handler = mDeviceCallbacks.valueAt(i).getHandler(); 7968 if (handler != null) { 7969 if (removed_devices.length != 0) { 7970 handler.sendMessage(Message.obtain(handler, 7971 MSG_DEVICES_DEVICES_REMOVED, 7972 removed_devices)); 7973 } 7974 if (added_devices.length != 0) { 7975 handler.sendMessage(Message.obtain(handler, 7976 MSG_DEVICES_DEVICES_ADDED, 7977 added_devices)); 7978 } 7979 } 7980 } 7981 } 7982 } 7983 7984 mPreviousPorts = current_ports; 7985 } 7986 7987 /** 7988 * Handles Port list update notifications from the AudioManager 7989 */ 7990 private class OnAmPortUpdateListener implements AudioManager.OnAudioPortUpdateListener { 7991 static final String TAG = "OnAmPortUpdateListener"; onAudioPortListUpdate(AudioPort[] portList)7992 public void onAudioPortListUpdate(AudioPort[] portList) { 7993 synchronized (mDeviceCallbacks) { 7994 broadcastDeviceListChange_sync(null); 7995 } 7996 } 7997 7998 /** 7999 * Callback method called upon audio patch list update. 8000 * Note: We don't do anything with Patches at this time, so ignore this notification. 8001 * @param patchList the updated list of audio patches. 8002 */ onAudioPatchListUpdate(AudioPatch[] patchList)8003 public void onAudioPatchListUpdate(AudioPatch[] patchList) {} 8004 8005 /** 8006 * Callback method called when the mediaserver dies 8007 */ onServiceDied()8008 public void onServiceDied() { 8009 synchronized (mDeviceCallbacks) { 8010 broadcastDeviceListChange_sync(null); 8011 } 8012 } 8013 } 8014 8015 8016 /** 8017 * @hide 8018 * Abstract class to receive event notification about audioserver process state. 8019 */ 8020 @SystemApi 8021 public abstract static class AudioServerStateCallback { onAudioServerDown()8022 public void onAudioServerDown() { } onAudioServerUp()8023 public void onAudioServerUp() { } 8024 } 8025 8026 private Executor mAudioServerStateExec; 8027 private AudioServerStateCallback mAudioServerStateCb; 8028 private final Object mAudioServerStateCbLock = new Object(); 8029 8030 private final IAudioServerStateDispatcher mAudioServerStateDispatcher = 8031 new IAudioServerStateDispatcher.Stub() { 8032 @Override 8033 public void dispatchAudioServerStateChange(boolean state) { 8034 Executor exec; 8035 AudioServerStateCallback cb; 8036 8037 synchronized (mAudioServerStateCbLock) { 8038 exec = mAudioServerStateExec; 8039 cb = mAudioServerStateCb; 8040 } 8041 8042 if ((exec == null) || (cb == null)) { 8043 return; 8044 } 8045 if (state) { 8046 exec.execute(() -> cb.onAudioServerUp()); 8047 } else { 8048 exec.execute(() -> cb.onAudioServerDown()); 8049 } 8050 } 8051 }; 8052 8053 /** 8054 * @hide 8055 * Registers a callback for notification of audio server state changes. 8056 * @param executor {@link Executor} to handle the callbacks 8057 * @param stateCallback the callback to receive the audio server state changes 8058 * To remove the callabck, pass a null reference for both executor and stateCallback. 8059 */ 8060 @SystemApi setAudioServerStateCallback(@onNull Executor executor, @NonNull AudioServerStateCallback stateCallback)8061 public void setAudioServerStateCallback(@NonNull Executor executor, 8062 @NonNull AudioServerStateCallback stateCallback) { 8063 if (stateCallback == null) { 8064 throw new IllegalArgumentException("Illegal null AudioServerStateCallback"); 8065 } 8066 if (executor == null) { 8067 throw new IllegalArgumentException( 8068 "Illegal null Executor for the AudioServerStateCallback"); 8069 } 8070 8071 synchronized (mAudioServerStateCbLock) { 8072 if (mAudioServerStateCb != null) { 8073 throw new IllegalStateException( 8074 "setAudioServerStateCallback called with already registered callabck"); 8075 } 8076 final IAudioService service = getService(); 8077 try { 8078 service.registerAudioServerStateDispatcher(mAudioServerStateDispatcher); 8079 } catch (RemoteException e) { 8080 throw e.rethrowFromSystemServer(); 8081 } 8082 mAudioServerStateExec = executor; 8083 mAudioServerStateCb = stateCallback; 8084 } 8085 } 8086 8087 /** 8088 * @hide 8089 * Unregisters the callback for notification of audio server state changes. 8090 */ 8091 @SystemApi clearAudioServerStateCallback()8092 public void clearAudioServerStateCallback() { 8093 synchronized (mAudioServerStateCbLock) { 8094 if (mAudioServerStateCb != null) { 8095 final IAudioService service = getService(); 8096 try { 8097 service.unregisterAudioServerStateDispatcher( 8098 mAudioServerStateDispatcher); 8099 } catch (RemoteException e) { 8100 throw e.rethrowFromSystemServer(); 8101 } 8102 } 8103 mAudioServerStateExec = null; 8104 mAudioServerStateCb = null; 8105 } 8106 } 8107 8108 /** 8109 * @hide 8110 * Checks if native audioservice is running or not. 8111 * @return true if native audioservice runs, false otherwise. 8112 */ 8113 @SystemApi isAudioServerRunning()8114 public boolean isAudioServerRunning() { 8115 final IAudioService service = getService(); 8116 try { 8117 return service.isAudioServerRunning(); 8118 } catch (RemoteException e) { 8119 throw e.rethrowFromSystemServer(); 8120 } 8121 } 8122 8123 /** 8124 * Sets the surround sound mode. 8125 * 8126 * @return true if successful, otherwise false 8127 */ 8128 @RequiresPermission(Manifest.permission.WRITE_SETTINGS) setEncodedSurroundMode(@ncodedSurroundOutputMode int mode)8129 public boolean setEncodedSurroundMode(@EncodedSurroundOutputMode int mode) { 8130 try { 8131 return getService().setEncodedSurroundMode(mode); 8132 } catch (RemoteException e) { 8133 throw e.rethrowFromSystemServer(); 8134 } 8135 } 8136 8137 /** 8138 * Gets the surround sound mode. 8139 * 8140 * @return true if successful, otherwise false 8141 */ getEncodedSurroundMode()8142 public @EncodedSurroundOutputMode int getEncodedSurroundMode() { 8143 try { 8144 return getService().getEncodedSurroundMode( 8145 getContext().getApplicationInfo().targetSdkVersion); 8146 } catch (RemoteException e) { 8147 throw e.rethrowFromSystemServer(); 8148 } 8149 } 8150 8151 /** 8152 * @hide 8153 * Returns all surround formats. 8154 * @return a map where the key is a surround format and 8155 * the value indicates the surround format is enabled or not 8156 */ 8157 @TestApi 8158 @NonNull getSurroundFormats()8159 public Map<Integer, Boolean> getSurroundFormats() { 8160 try { 8161 return getService().getSurroundFormats(); 8162 } catch (RemoteException e) { 8163 throw e.rethrowFromSystemServer(); 8164 } 8165 } 8166 8167 /** 8168 * Sets and persists a certain surround format as enabled or not. 8169 * <p> 8170 * This API is called by TvSettings surround sound menu when user enables or disables a 8171 * surround sound format. This setting is persisted as global user setting. 8172 * Applications should revert their changes to surround sound settings unless they intend to 8173 * modify the global user settings across all apps. The framework does not auto-revert an 8174 * application's settings after a lifecycle event. Audio focus is not required to apply these 8175 * settings. 8176 * 8177 * @param enabled the required surround format state, true for enabled, false for disabled 8178 * @return true if successful, otherwise false 8179 */ 8180 @RequiresPermission(Manifest.permission.WRITE_SETTINGS) setSurroundFormatEnabled( @udioFormat.SurroundSoundEncoding int audioFormat, boolean enabled)8181 public boolean setSurroundFormatEnabled( 8182 @AudioFormat.SurroundSoundEncoding int audioFormat, boolean enabled) { 8183 try { 8184 return getService().setSurroundFormatEnabled(audioFormat, enabled); 8185 } catch (RemoteException e) { 8186 throw e.rethrowFromSystemServer(); 8187 } 8188 } 8189 8190 /** 8191 * Gets whether a certain surround format is enabled or not. 8192 * @param audioFormat a surround format 8193 * 8194 * @return whether the required surround format is enabled 8195 */ isSurroundFormatEnabled(@udioFormat.SurroundSoundEncoding int audioFormat)8196 public boolean isSurroundFormatEnabled(@AudioFormat.SurroundSoundEncoding int audioFormat) { 8197 try { 8198 return getService().isSurroundFormatEnabled(audioFormat); 8199 } catch (RemoteException e) { 8200 throw e.rethrowFromSystemServer(); 8201 } 8202 } 8203 8204 /** 8205 * @hide 8206 * Returns all surround formats that are reported by the connected HDMI device. 8207 * The return values are not affected by calling setSurroundFormatEnabled. 8208 * 8209 * @return a list of surround formats 8210 */ 8211 @TestApi 8212 @NonNull getReportedSurroundFormats()8213 public List<Integer> getReportedSurroundFormats() { 8214 try { 8215 return getService().getReportedSurroundFormats(); 8216 } catch (RemoteException e) { 8217 throw e.rethrowFromSystemServer(); 8218 } 8219 } 8220 8221 /** 8222 * Return if audio haptic coupled playback is supported or not. 8223 * 8224 * @return whether audio haptic playback supported. 8225 */ isHapticPlaybackSupported()8226 public static boolean isHapticPlaybackSupported() { 8227 return AudioSystem.isHapticPlaybackSupported(); 8228 } 8229 8230 /** 8231 * @hide 8232 * Indicates whether a platform supports the Ultrasound feature which covers the playback 8233 * and recording of 20kHz~ sounds. If platform supports Ultrasound, then the 8234 * usage will be 8235 * To start the Ultrasound playback: 8236 * - Create an AudioTrack with {@link AudioAttributes.CONTENT_TYPE_ULTRASOUND}. 8237 * To start the Ultrasound capture: 8238 * - Create an AudioRecord with {@link MediaRecorder.AudioSource.ULTRASOUND}. 8239 * 8240 * @return whether the ultrasound feature is supported, true when platform supports both 8241 * Ultrasound playback and capture, false otherwise. 8242 */ 8243 @SystemApi 8244 @RequiresPermission(Manifest.permission.ACCESS_ULTRASOUND) isUltrasoundSupported()8245 public boolean isUltrasoundSupported() { 8246 try { 8247 return getService().isUltrasoundSupported(); 8248 } catch (RemoteException e) { 8249 throw e.rethrowFromSystemServer(); 8250 } 8251 } 8252 8253 /** 8254 * @hide 8255 * Indicates whether the platform supports capturing content from the hotword recognition 8256 * pipeline. To capture content of this type, create an AudioRecord with 8257 * {@link AudioRecord.Builder.setRequestHotwordStream(boolean, boolean)}. 8258 * @param lookbackAudio Query if the hotword stream additionally supports providing buffered 8259 * audio prior to stream open. 8260 * @return True if the platform supports capturing hotword content, and if lookbackAudio 8261 * is true, if it additionally supports capturing buffered hotword content prior to stream 8262 * open. False otherwise. 8263 */ 8264 @SystemApi 8265 @RequiresPermission(Manifest.permission.CAPTURE_AUDIO_HOTWORD) isHotwordStreamSupported(boolean lookbackAudio)8266 public boolean isHotwordStreamSupported(boolean lookbackAudio) { 8267 try { 8268 return getService().isHotwordStreamSupported(lookbackAudio); 8269 } catch (RemoteException e) { 8270 return false; 8271 } 8272 } 8273 8274 /** 8275 * @hide 8276 * Introspection API to retrieve audio product strategies. 8277 * When implementing {Car|Oem}AudioManager, use this method to retrieve the collection of 8278 * audio product strategies, which is indexed by a weakly typed index in order to be extended 8279 * by OEM without any needs of AOSP patches. 8280 * The {Car|Oem}AudioManager can expose API to build {@link AudioAttributes} for a given product 8281 * strategy refered either by its index or human readable string. It will allow clients 8282 * application to start streaming data using these {@link AudioAttributes} on the selected 8283 * device by Audio Policy Engine. 8284 * @return a (possibly zero-length) array of 8285 * {@see android.media.audiopolicy.AudioProductStrategy} objects. 8286 */ 8287 @SystemApi 8288 @NonNull 8289 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) getAudioProductStrategies()8290 public static List<AudioProductStrategy> getAudioProductStrategies() { 8291 final IAudioService service = getService(); 8292 try { 8293 return service.getAudioProductStrategies(); 8294 } catch (RemoteException e) { 8295 throw e.rethrowFromSystemServer(); 8296 } 8297 } 8298 8299 /** 8300 * @hide 8301 * Introspection API to retrieve audio volume groups. 8302 * When implementing {Car|Oem}AudioManager, use this method to retrieve the collection of 8303 * audio volume groups. 8304 * @return a (possibly zero-length) List of 8305 * {@see android.media.audiopolicy.AudioVolumeGroup} objects. 8306 */ 8307 @SystemApi 8308 @NonNull 8309 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) getAudioVolumeGroups()8310 public static List<AudioVolumeGroup> getAudioVolumeGroups() { 8311 final IAudioService service = getService(); 8312 try { 8313 return service.getAudioVolumeGroups(); 8314 } catch (RemoteException e) { 8315 throw e.rethrowFromSystemServer(); 8316 } 8317 } 8318 8319 /** 8320 * @hide 8321 * Callback registered by client to be notified upon volume group change. 8322 */ 8323 @SystemApi 8324 public abstract static class VolumeGroupCallback { 8325 /** 8326 * Callback method called upon audio volume group change. 8327 * @param group the group for which the volume has changed 8328 */ onAudioVolumeGroupChanged(int group, int flags)8329 public void onAudioVolumeGroupChanged(int group, int flags) {} 8330 } 8331 8332 /** 8333 * @hide 8334 * Register an audio volume group change listener. 8335 * @param callback the {@link VolumeGroupCallback} to register 8336 */ 8337 @SystemApi registerVolumeGroupCallback( @onNull Executor executor, @NonNull VolumeGroupCallback callback)8338 public void registerVolumeGroupCallback( 8339 @NonNull Executor executor, 8340 @NonNull VolumeGroupCallback callback) { 8341 Preconditions.checkNotNull(executor, "executor must not be null"); 8342 Preconditions.checkNotNull(callback, "volume group change cb must not be null"); 8343 sAudioAudioVolumeGroupChangedHandler.init(); 8344 // TODO: make use of executor 8345 sAudioAudioVolumeGroupChangedHandler.registerListener(callback); 8346 } 8347 8348 /** 8349 * @hide 8350 * Unregister an audio volume group change listener. 8351 * @param callback the {@link VolumeGroupCallback} to unregister 8352 */ 8353 @SystemApi unregisterVolumeGroupCallback( @onNull VolumeGroupCallback callback)8354 public void unregisterVolumeGroupCallback( 8355 @NonNull VolumeGroupCallback callback) { 8356 Preconditions.checkNotNull(callback, "volume group change cb must not be null"); 8357 sAudioAudioVolumeGroupChangedHandler.unregisterListener(callback); 8358 } 8359 8360 /** 8361 * Return if an asset contains haptic channels or not. 8362 * 8363 * @param context the {@link Context} to resolve the uri. 8364 * @param uri the {@link Uri} of the asset. 8365 * @return true if the assert contains haptic channels. 8366 * @hide 8367 */ hasHapticChannelsImpl(@onNull Context context, @NonNull Uri uri)8368 public static boolean hasHapticChannelsImpl(@NonNull Context context, @NonNull Uri uri) { 8369 MediaExtractor extractor = new MediaExtractor(); 8370 try { 8371 extractor.setDataSource(context, uri, null); 8372 for (int i = 0; i < extractor.getTrackCount(); i++) { 8373 MediaFormat format = extractor.getTrackFormat(i); 8374 if (format.containsKey(MediaFormat.KEY_HAPTIC_CHANNEL_COUNT) 8375 && format.getInteger(MediaFormat.KEY_HAPTIC_CHANNEL_COUNT) > 0) { 8376 return true; 8377 } 8378 } 8379 } catch (IOException e) { 8380 Log.e(TAG, "hasHapticChannels failure:" + e); 8381 } 8382 return false; 8383 } 8384 8385 /** 8386 * Return if an asset contains haptic channels or not. 8387 * 8388 * @param context the {@link Context} to resolve the uri. 8389 * @param uri the {@link Uri} of the asset. 8390 * @return true if the assert contains haptic channels. 8391 * @hide 8392 */ hasHapticChannels(@ullable Context context, @NonNull Uri uri)8393 public static boolean hasHapticChannels(@Nullable Context context, @NonNull Uri uri) { 8394 Objects.requireNonNull(uri); 8395 8396 if (context != null) { 8397 return hasHapticChannelsImpl(context, uri); 8398 } 8399 8400 Context cachedContext = sContext.get(); 8401 if (cachedContext != null) { 8402 if (DEBUG) { 8403 Log.d(TAG, "Try to use static context to query if having haptic channels"); 8404 } 8405 return hasHapticChannelsImpl(cachedContext, uri); 8406 } 8407 8408 // Try with audio service context, this may fail to get correct result. 8409 if (DEBUG) { 8410 Log.d(TAG, "Try to use audio service context to query if having haptic channels"); 8411 } 8412 try { 8413 return getService().hasHapticChannels(uri); 8414 } catch (RemoteException e) { 8415 throw e.rethrowFromSystemServer(); 8416 } 8417 } 8418 8419 /** 8420 * Set whether or not there is an active RTT call. 8421 * This method should be called by Telecom service. 8422 * @hide 8423 * TODO: make this a @SystemApi 8424 */ setRttEnabled(boolean rttEnabled)8425 public static void setRttEnabled(boolean rttEnabled) { 8426 try { 8427 getService().setRttEnabled(rttEnabled); 8428 } catch (RemoteException e) { 8429 throw e.rethrowFromSystemServer(); 8430 } 8431 } 8432 8433 /** 8434 * Adjusts the volume of the most relevant stream, or the given fallback 8435 * stream. 8436 * <p> 8437 * This method should only be used by applications that replace the 8438 * platform-wide management of audio settings or the main telephony 8439 * application. 8440 * <p> 8441 * This method has no effect if the device implements a fixed volume policy 8442 * as indicated by {@link #isVolumeFixed()}. 8443 * <p>This API checks if the caller has the necessary permissions based on the provided 8444 * component name, uid, and pid values. 8445 * See {@link #adjustSuggestedStreamVolume(int, int, int)}. 8446 * 8447 * @param suggestedStreamType The stream type that will be used if there 8448 * isn't a relevant stream. {@link #USE_DEFAULT_STREAM_TYPE} is 8449 * valid here. 8450 * @param direction The direction to adjust the volume. One of 8451 * {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, 8452 * {@link #ADJUST_SAME}, {@link #ADJUST_MUTE}, 8453 * {@link #ADJUST_UNMUTE}, or {@link #ADJUST_TOGGLE_MUTE}. 8454 * @param flags 8455 * @param packageName the package name of client application 8456 * @param uid the uid of client application 8457 * @param pid the pid of client application 8458 * @param targetSdkVersion the target sdk version of client application 8459 * @see #adjustVolume(int, int) 8460 * @see #adjustStreamVolume(int, int, int) 8461 * @see #setStreamVolume(int, int, int) 8462 * @see #isVolumeFixed() 8463 * 8464 * @hide 8465 */ 8466 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) adjustSuggestedStreamVolumeForUid(int suggestedStreamType, int direction, @SystemVolumeFlags int flags, @NonNull String packageName, int uid, int pid, int targetSdkVersion)8467 public void adjustSuggestedStreamVolumeForUid(int suggestedStreamType, int direction, 8468 @SystemVolumeFlags int flags, 8469 @NonNull String packageName, int uid, int pid, int targetSdkVersion) { 8470 try { 8471 getService().adjustSuggestedStreamVolumeForUid(suggestedStreamType, direction, flags, 8472 packageName, uid, pid, UserHandle.getUserHandleForUid(uid), targetSdkVersion); 8473 } catch (RemoteException e) { 8474 throw e.rethrowFromSystemServer(); 8475 } 8476 } 8477 8478 /** 8479 * Adjusts the volume of a particular stream by one step in a direction. 8480 * <p> 8481 * This method should only be used by applications that replace the platform-wide 8482 * management of audio settings or the main telephony application. 8483 * <p>This method has no effect if the device implements a fixed volume policy 8484 * as indicated by {@link #isVolumeFixed()}. 8485 * <p>From N onward, ringer mode adjustments that would toggle Do Not Disturb are not allowed 8486 * unless the app has been granted Do Not Disturb Access. 8487 * See {@link NotificationManager#isNotificationPolicyAccessGranted()}. 8488 * <p>This API checks if the caller has the necessary permissions based on the provided 8489 * component name, uid, and pid values. 8490 * See {@link #adjustStreamVolume(int, int, int)}. 8491 * 8492 * @param streamType The stream type to adjust. One of {@link #STREAM_VOICE_CALL}, 8493 * {@link #STREAM_SYSTEM}, {@link #STREAM_RING}, {@link #STREAM_MUSIC}, 8494 * {@link #STREAM_ALARM} or {@link #STREAM_ACCESSIBILITY}. 8495 * @param direction The direction to adjust the volume. One of 8496 * {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, or 8497 * {@link #ADJUST_SAME}. 8498 * @param flags 8499 * @param packageName the package name of client application 8500 * @param uid the uid of client application 8501 * @param pid the pid of client application 8502 * @param targetSdkVersion the target sdk version of client application 8503 * @see #adjustVolume(int, int) 8504 * @see #setStreamVolume(int, int, int) 8505 * @throws SecurityException if the adjustment triggers a Do Not Disturb change 8506 * and the caller is not granted notification policy access. 8507 * 8508 * @hide 8509 */ 8510 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) adjustStreamVolumeForUid(int streamType, int direction, @SystemVolumeFlags int flags, @NonNull String packageName, int uid, int pid, int targetSdkVersion)8511 public void adjustStreamVolumeForUid(int streamType, int direction, 8512 @SystemVolumeFlags int flags, 8513 @NonNull String packageName, int uid, int pid, int targetSdkVersion) { 8514 try { 8515 getService().adjustStreamVolumeForUid(streamType, direction, flags, packageName, uid, 8516 pid, UserHandle.getUserHandleForUid(uid), targetSdkVersion); 8517 } catch (RemoteException e) { 8518 throw e.rethrowFromSystemServer(); 8519 } 8520 } 8521 8522 /** 8523 * Sets the volume index for a particular stream. 8524 * <p>This method has no effect if the device implements a fixed volume policy 8525 * as indicated by {@link #isVolumeFixed()}. 8526 * <p>From N onward, volume adjustments that would toggle Do Not Disturb are not allowed unless 8527 * the app has been granted Do Not Disturb Access. 8528 * See {@link NotificationManager#isNotificationPolicyAccessGranted()}. 8529 * <p>This API checks if the caller has the necessary permissions based on the provided 8530 * component name, uid, and pid values. 8531 * See {@link #setStreamVolume(int, int, int)}. 8532 * 8533 * @param streamType The stream whose volume index should be set. 8534 * @param index The volume index to set. See 8535 * {@link #getStreamMaxVolume(int)} for the largest valid value. 8536 * @param flags 8537 * @param packageName the package name of client application 8538 * @param uid the uid of client application 8539 * @param pid the pid of client application 8540 * @param targetSdkVersion the target sdk version of client application 8541 * @see #getStreamMaxVolume(int) 8542 * @see #getStreamVolume(int) 8543 * @see #isVolumeFixed() 8544 * @throws SecurityException if the volume change triggers a Do Not Disturb change 8545 * and the caller is not granted notification policy access. 8546 * 8547 * @hide 8548 */ 8549 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) setStreamVolumeForUid(int streamType, int index, @SystemVolumeFlags int flags, @NonNull String packageName, int uid, int pid, int targetSdkVersion)8550 public void setStreamVolumeForUid(int streamType, int index, 8551 @SystemVolumeFlags int flags, 8552 @NonNull String packageName, int uid, int pid, int targetSdkVersion) { 8553 try { 8554 getService().setStreamVolumeForUid(streamType, index, flags, packageName, uid, pid, 8555 UserHandle.getUserHandleForUid(uid), targetSdkVersion); 8556 } catch (RemoteException e) { 8557 throw e.rethrowFromSystemServer(); 8558 } 8559 } 8560 8561 8562 /** @hide 8563 * TODO: make this a @SystemApi */ 8564 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) setMultiAudioFocusEnabled(boolean enabled)8565 public void setMultiAudioFocusEnabled(boolean enabled) { 8566 try { 8567 getService().setMultiAudioFocusEnabled(enabled); 8568 } catch (RemoteException e) { 8569 throw e.rethrowFromSystemServer(); 8570 } 8571 } 8572 8573 8574 /** 8575 * Retrieves the Hardware A/V synchronization ID corresponding to the given audio session ID. 8576 * For more details on Hardware A/V synchronization please refer to 8577 * <a href="https://source.android.com/devices/tv/multimedia-tunneling/"> 8578 * media tunneling documentation</a>. 8579 * @param sessionId the audio session ID for which the HW A/V sync ID is retrieved. 8580 * @return the HW A/V sync ID for this audio session (an integer different from 0). 8581 * @throws UnsupportedOperationException if HW A/V synchronization is not supported. 8582 */ getAudioHwSyncForSession(int sessionId)8583 public int getAudioHwSyncForSession(int sessionId) { 8584 int hwSyncId = AudioSystem.getAudioHwSyncForSession(sessionId); 8585 if (hwSyncId == AudioSystem.AUDIO_HW_SYNC_INVALID) { 8586 throw new UnsupportedOperationException("HW A/V synchronization is not supported."); 8587 } 8588 return hwSyncId; 8589 } 8590 8591 /** 8592 * Selects the audio device that should be used for communication use cases, for instance voice 8593 * or video calls. This method can be used by voice or video chat applications to select a 8594 * different audio device than the one selected by default by the platform. 8595 * <p>The device selection is expressed as an {@link AudioDeviceInfo} among devices returned by 8596 * {@link #getAvailableCommunicationDevices()}. Note that only devices in a sink role 8597 * (AKA output devices, see {@link AudioDeviceInfo#isSink()}) can be specified. The matching 8598 * source device is selected automatically by the platform. 8599 * <p>The selection is active as long as the requesting application process lives, until 8600 * {@link #clearCommunicationDevice} is called or until the device is disconnected. 8601 * It is therefore important for applications to clear the request when a call ends or the 8602 * the requesting activity or service is stopped or destroyed. 8603 * <p>In case of simultaneous requests by multiple applications the priority is given to the 8604 * application currently controlling the audio mode (see {@link #setMode(int)}). This is the 8605 * latest application having selected mode {@link #MODE_IN_COMMUNICATION} or mode 8606 * {@link #MODE_IN_CALL}. Note that <code>MODE_IN_CALL</code> can only be selected by the main 8607 * telephony application with permission 8608 * {@link Manifest.permission#MODIFY_PHONE_STATE}. 8609 * <p> If the requested devices is not currently available, the request will be rejected and 8610 * the method will return false. 8611 * <p>This API replaces the following deprecated APIs: 8612 * <ul> 8613 * <li> {@link #startBluetoothSco()} 8614 * <li> {@link #stopBluetoothSco()} 8615 * <li> {@link #setSpeakerphoneOn(boolean)} 8616 * </ul> 8617 * <h4>Example</h4> 8618 * <p>The example below shows how to enable and disable speakerphone mode. 8619 * <pre class="prettyprint"> 8620 * // Get an AudioManager instance 8621 * AudioManager audioManager = Context.getSystemService(AudioManager.class); 8622 * AudioDeviceInfo speakerDevice = null; 8623 * List<AudioDeviceInfo> devices = audioManager.getAvailableCommunicationDevices(); 8624 * for (AudioDeviceInfo device : devices) { 8625 * if (device.getType() == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER) { 8626 * speakerDevice = device; 8627 * break; 8628 * } 8629 * } 8630 * if (speakerDevice != null) { 8631 * // Turn speakerphone ON. 8632 * boolean result = audioManager.setCommunicationDevice(speakerDevice); 8633 * if (!result) { 8634 * // Handle error. 8635 * } 8636 * // Turn speakerphone OFF. 8637 * audioManager.clearCommunicationDevice(); 8638 * } 8639 * </pre> 8640 * @param device the requested audio device. 8641 * @return <code>true</code> if the request was accepted, <code>false</code> otherwise. 8642 * @throws IllegalArgumentException If an invalid device is specified. 8643 */ setCommunicationDevice(@onNull AudioDeviceInfo device)8644 public boolean setCommunicationDevice(@NonNull AudioDeviceInfo device) { 8645 Objects.requireNonNull(device); 8646 try { 8647 if (device.getId() == 0) { 8648 Log.w(TAG, "setCommunicationDevice: device not found: " + device); 8649 return false; 8650 } 8651 return getService().setCommunicationDevice(mICallBack, device.getId()); 8652 } catch (RemoteException e) { 8653 throw e.rethrowFromSystemServer(); 8654 } 8655 } 8656 8657 /** 8658 * Cancels previous communication device selection made with 8659 * {@link #setCommunicationDevice(AudioDeviceInfo)}. 8660 */ clearCommunicationDevice()8661 public void clearCommunicationDevice() { 8662 try { 8663 getService().setCommunicationDevice(mICallBack, 0); 8664 } catch (RemoteException e) { 8665 throw e.rethrowFromSystemServer(); 8666 } 8667 } 8668 8669 /** 8670 * Returns currently selected audio device for communication. 8671 * <p>This API replaces the following deprecated APIs: 8672 * <ul> 8673 * <li> {@link #isBluetoothScoOn()} 8674 * <li> {@link #isSpeakerphoneOn()} 8675 * </ul> 8676 * @return an {@link AudioDeviceInfo} indicating which audio device is 8677 * currently selected for communication use cases. Can be null on platforms 8678 * not supporting {@link android.content.pm.PackageManager#FEATURE_TELEPHONY}. 8679 * is used. 8680 */ 8681 @Nullable getCommunicationDevice()8682 public AudioDeviceInfo getCommunicationDevice() { 8683 try { 8684 return getDeviceForPortId( 8685 getService().getCommunicationDevice(), GET_DEVICES_OUTPUTS); 8686 } catch (RemoteException e) { 8687 throw e.rethrowFromSystemServer(); 8688 } 8689 } 8690 8691 /** 8692 * Returns a list of audio devices that can be selected for communication use cases via 8693 * {@link #setCommunicationDevice(AudioDeviceInfo)}. 8694 * @return a list of {@link AudioDeviceInfo} suitable for use with setCommunicationDevice(). 8695 */ 8696 @NonNull getAvailableCommunicationDevices()8697 public List<AudioDeviceInfo> getAvailableCommunicationDevices() { 8698 try { 8699 ArrayList<AudioDeviceInfo> devices = new ArrayList<>(); 8700 int[] portIds = getService().getAvailableCommunicationDeviceIds(); 8701 for (int portId : portIds) { 8702 AudioDeviceInfo device = getDeviceForPortId(portId, GET_DEVICES_OUTPUTS); 8703 if (device == null) { 8704 continue; 8705 } 8706 devices.add(device); 8707 } 8708 return devices; 8709 } catch (RemoteException e) { 8710 throw e.rethrowFromSystemServer(); 8711 } 8712 } 8713 8714 /** 8715 * Returns a list of direct {@link AudioProfile} that are supported for the specified 8716 * {@link AudioAttributes}. This can be empty in case of an error or if no direct playback 8717 * is possible. 8718 * 8719 * <p>Direct playback means that the audio stream is not resampled or downmixed 8720 * by the framework. Checking for direct support can help the app select the representation 8721 * of audio content that most closely matches the capabilities of the device and peripherals 8722 * (e.g. A/V receiver) connected to it. Note that the provided stream can still be re-encoded 8723 * or mixed with other streams, if needed. 8724 * <p>When using this information to inform your application which audio format to play, 8725 * query again whenever audio output devices change (see {@link AudioDeviceCallback}). 8726 * @param attributes a non-null {@link AudioAttributes} instance. 8727 * @return a list of {@link AudioProfile} 8728 */ 8729 @NonNull getDirectProfilesForAttributes(@onNull AudioAttributes attributes)8730 public List<AudioProfile> getDirectProfilesForAttributes(@NonNull AudioAttributes attributes) { 8731 Objects.requireNonNull(attributes); 8732 ArrayList<AudioProfile> audioProfilesList = new ArrayList<>(); 8733 int status = AudioSystem.getDirectProfilesForAttributes(attributes, audioProfilesList); 8734 if (status != SUCCESS) { 8735 Log.w(TAG, "getDirectProfilesForAttributes failed."); 8736 return new ArrayList<>(); 8737 } 8738 return audioProfilesList; 8739 } 8740 8741 /** 8742 * @hide 8743 * Returns an {@link AudioDeviceInfo} corresponding to a connected device of the type provided. 8744 * The type must be a valid output type defined in <code>AudioDeviceInfo</code> class, 8745 * for instance {@link AudioDeviceInfo#TYPE_BUILTIN_SPEAKER}. 8746 * The method will return null if no device of the provided type is connected. 8747 * If more than one device of the provided type is connected, an object corresponding to the 8748 * first device encountered in the enumeration list will be returned. 8749 * @param deviceType The device device for which an <code>AudioDeviceInfo</code> 8750 * object is queried. 8751 * @return An AudioDeviceInfo object or null if no device with the requested type is connected. 8752 * @throws IllegalArgumentException If an invalid device type is specified. 8753 */ 8754 @TestApi 8755 @Nullable getDeviceInfoFromType( @udioDeviceInfo.AudioDeviceTypeOut int deviceType)8756 public static AudioDeviceInfo getDeviceInfoFromType( 8757 @AudioDeviceInfo.AudioDeviceTypeOut int deviceType) { 8758 return getDeviceInfoFromTypeAndAddress(deviceType, null); 8759 } 8760 8761 /** 8762 * @hide 8763 * Returns an {@link AudioDeviceInfo} corresponding to a connected device of the type and 8764 * address provided. 8765 * The type must be a valid output type defined in <code>AudioDeviceInfo</code> class, 8766 * for instance {@link AudioDeviceInfo#TYPE_BUILTIN_SPEAKER}. 8767 * If a null address is provided, the matching will happen on the type only. 8768 * The method will return null if no device of the provided type and address is connected. 8769 * If more than one device of the provided type is connected, an object corresponding to the 8770 * first device encountered in the enumeration list will be returned. 8771 * @param type The device device for which an <code>AudioDeviceInfo</code> 8772 * object is queried. 8773 * @param address The device address for which an <code>AudioDeviceInfo</code> 8774 * object is queried or null if requesting match on type only. 8775 * @return An AudioDeviceInfo object or null if no matching device is connected. 8776 * @throws IllegalArgumentException If an invalid device type is specified. 8777 */ 8778 @Nullable getDeviceInfoFromTypeAndAddress( @udioDeviceInfo.AudioDeviceTypeOut int type, @Nullable String address)8779 public static AudioDeviceInfo getDeviceInfoFromTypeAndAddress( 8780 @AudioDeviceInfo.AudioDeviceTypeOut int type, @Nullable String address) { 8781 AudioDeviceInfo[] devices = getDevicesStatic(GET_DEVICES_OUTPUTS); 8782 AudioDeviceInfo deviceForType = null; 8783 for (AudioDeviceInfo device : devices) { 8784 if (device.getType() == type) { 8785 deviceForType = device; 8786 if (address == null || address.equals(device.getAddress())) { 8787 return device; 8788 } 8789 } 8790 } 8791 return deviceForType; 8792 } 8793 8794 /** 8795 * Listener registered by client to be notified upon communication audio device change. 8796 * See {@link #setCommunicationDevice(AudioDeviceInfo)}. 8797 */ 8798 public interface OnCommunicationDeviceChangedListener { 8799 /** 8800 * Callback method called upon communication audio device change. 8801 * @param device the audio device requested for communication use cases. 8802 * Can be null on platforms not supporting 8803 * {@link android.content.pm.PackageManager#FEATURE_TELEPHONY}. 8804 */ onCommunicationDeviceChanged(@ullable AudioDeviceInfo device)8805 void onCommunicationDeviceChanged(@Nullable AudioDeviceInfo device); 8806 } 8807 8808 /** 8809 * manages the OnCommunicationDeviceChangedListener listeners and the 8810 * CommunicationDeviceDispatcherStub 8811 */ 8812 private final CallbackUtil.LazyListenerManager<OnCommunicationDeviceChangedListener> 8813 mCommDeviceChangedListenerMgr = new CallbackUtil.LazyListenerManager(); 8814 /** 8815 * Adds a listener for being notified of changes to the communication audio device. 8816 * See {@link #setCommunicationDevice(AudioDeviceInfo)}. 8817 * @param executor 8818 * @param listener 8819 */ addOnCommunicationDeviceChangedListener( @onNull @allbackExecutor Executor executor, @NonNull OnCommunicationDeviceChangedListener listener)8820 public void addOnCommunicationDeviceChangedListener( 8821 @NonNull @CallbackExecutor Executor executor, 8822 @NonNull OnCommunicationDeviceChangedListener listener) { 8823 mCommDeviceChangedListenerMgr.addListener( 8824 executor, listener, "addOnCommunicationDeviceChangedListener", 8825 () -> new CommunicationDeviceDispatcherStub()); 8826 } 8827 8828 /** 8829 * Removes a previously added listener of changes to the communication audio device. 8830 * See {@link #setCommunicationDevice(AudioDeviceInfo)}. 8831 * @param listener 8832 */ removeOnCommunicationDeviceChangedListener( @onNull OnCommunicationDeviceChangedListener listener)8833 public void removeOnCommunicationDeviceChangedListener( 8834 @NonNull OnCommunicationDeviceChangedListener listener) { 8835 mCommDeviceChangedListenerMgr.removeListener(listener, 8836 "removeOnCommunicationDeviceChangedListener"); 8837 } 8838 8839 private final class CommunicationDeviceDispatcherStub 8840 extends ICommunicationDeviceDispatcher.Stub implements CallbackUtil.DispatcherStub { 8841 8842 @Override register(boolean register)8843 public void register(boolean register) { 8844 try { 8845 if (register) { 8846 getService().registerCommunicationDeviceDispatcher(this); 8847 } else { 8848 getService().unregisterCommunicationDeviceDispatcher(this); 8849 } 8850 } catch (RemoteException e) { 8851 e.rethrowFromSystemServer(); 8852 } 8853 } 8854 8855 @Override dispatchCommunicationDeviceChanged(int portId)8856 public void dispatchCommunicationDeviceChanged(int portId) { 8857 AudioDeviceInfo device = getDeviceForPortId(portId, GET_DEVICES_OUTPUTS); 8858 mCommDeviceChangedListenerMgr.callListeners( 8859 (listener) -> listener.onCommunicationDeviceChanged(device)); 8860 } 8861 } 8862 8863 8864 /** 8865 * @hide 8866 * Indicates if the platform allows accessing the uplink and downlink audio of an ongoing 8867 * PSTN call. 8868 * When true, {@link getCallUplinkInjectionAudioTrack(AudioFormat)} can be used to obtain 8869 * an AudioTrack for call uplink audio injection and 8870 * {@link getCallDownlinkExtractionAudioRecord(AudioFormat)} can be used to obtain 8871 * an AudioRecord for call downlink audio extraction. 8872 * @return true if PSTN call audio is accessible, false otherwise. 8873 */ 8874 @TestApi 8875 @SystemApi 8876 @RequiresPermission(Manifest.permission.CALL_AUDIO_INTERCEPTION) isPstnCallAudioInterceptable()8877 public boolean isPstnCallAudioInterceptable() { 8878 final IAudioService service = getService(); 8879 try { 8880 return service.isPstnCallAudioInterceptable(); 8881 } catch (RemoteException e) { 8882 throw e.rethrowFromSystemServer(); 8883 } 8884 } 8885 8886 /** @hide */ 8887 @IntDef(flag = false, prefix = "CALL_REDIRECT_", value = { 8888 CALL_REDIRECT_NONE, 8889 CALL_REDIRECT_PSTN, 8890 CALL_REDIRECT_VOIP } 8891 ) 8892 @Retention(RetentionPolicy.SOURCE) 8893 public @interface CallRedirectionMode {} 8894 8895 /** 8896 * Not used for call redirection 8897 * @hide 8898 */ 8899 public static final int CALL_REDIRECT_NONE = 0; 8900 /** 8901 * Used to redirect PSTN call 8902 * @hide 8903 */ 8904 public static final int CALL_REDIRECT_PSTN = 1; 8905 /** 8906 * Used to redirect VoIP call 8907 * @hide 8908 */ 8909 public static final int CALL_REDIRECT_VOIP = 2; 8910 8911 getCallRedirectMode()8912 private @CallRedirectionMode int getCallRedirectMode() { 8913 int mode = getMode(); 8914 if (mode == MODE_IN_CALL || mode == MODE_CALL_SCREENING 8915 || mode == MODE_CALL_REDIRECT) { 8916 return CALL_REDIRECT_PSTN; 8917 } else if (mode == MODE_IN_COMMUNICATION || mode == MODE_COMMUNICATION_REDIRECT) { 8918 return CALL_REDIRECT_VOIP; 8919 } 8920 return CALL_REDIRECT_NONE; 8921 } 8922 checkCallRedirectionFormat(AudioFormat format, boolean isOutput)8923 private void checkCallRedirectionFormat(AudioFormat format, boolean isOutput) { 8924 if (format.getEncoding() != AudioFormat.ENCODING_PCM_16BIT 8925 && format.getEncoding() != AudioFormat.ENCODING_PCM_FLOAT) { 8926 throw new UnsupportedOperationException(" Unsupported encoding "); 8927 } 8928 if (format.getSampleRate() < 8000 8929 || format.getSampleRate() > 48000) { 8930 throw new UnsupportedOperationException(" Unsupported sample rate "); 8931 } 8932 if (isOutput && format.getChannelMask() != AudioFormat.CHANNEL_OUT_MONO 8933 && format.getChannelMask() != AudioFormat.CHANNEL_OUT_STEREO) { 8934 throw new UnsupportedOperationException(" Unsupported output channel mask "); 8935 } 8936 if (!isOutput && format.getChannelMask() != AudioFormat.CHANNEL_IN_MONO 8937 && format.getChannelMask() != AudioFormat.CHANNEL_IN_STEREO) { 8938 throw new UnsupportedOperationException(" Unsupported input channel mask "); 8939 } 8940 } 8941 8942 class CallIRedirectionClientInfo { 8943 public WeakReference trackOrRecord; 8944 public int redirectMode; 8945 } 8946 8947 private Object mCallRedirectionLock = new Object(); 8948 @GuardedBy("mCallRedirectionLock") 8949 private CallInjectionModeChangedListener mCallRedirectionModeListener; 8950 @GuardedBy("mCallRedirectionLock") 8951 private ArrayList<CallIRedirectionClientInfo> mCallIRedirectionClients; 8952 8953 /** 8954 * @hide 8955 * Returns an AudioTrack that can be used to inject audio to an active call uplink. 8956 * This can be used for functions like call screening or call audio redirection and is reserved 8957 * to system apps with privileged permission. 8958 * @param format the desired audio format for audio playback. 8959 * p>Formats accepted are: 8960 * <ul> 8961 * <li><em>Sampling rate</em> - 8kHz to 48kHz. </li> 8962 * <li><em>Channel mask</em> - Mono or Stereo </li> 8963 * <li><em>Sample format</em> - PCM 16 bit or FLOAT 32 bit </li> 8964 * </ul> 8965 * 8966 * @return The AudioTrack used for audio injection 8967 * @throws NullPointerException if AudioFormat argument is null. 8968 * @throws UnsupportedOperationException if on unsupported AudioFormat is specified. 8969 * @throws IllegalArgumentException if an invalid AudioFormat is specified. 8970 * @throws SecurityException if permission CALL_AUDIO_INTERCEPTION is missing . 8971 * @throws IllegalStateException if current audio mode is not MODE_IN_CALL, 8972 * MODE_IN_COMMUNICATION, MODE_CALL_SCREENING, MODE_CALL_REDIRECT 8973 * or MODE_COMMUNICATION_REDIRECT. 8974 */ 8975 @TestApi 8976 @SystemApi 8977 @RequiresPermission(Manifest.permission.CALL_AUDIO_INTERCEPTION) getCallUplinkInjectionAudioTrack(@onNull AudioFormat format)8978 public @NonNull AudioTrack getCallUplinkInjectionAudioTrack(@NonNull AudioFormat format) { 8979 Objects.requireNonNull(format); 8980 checkCallRedirectionFormat(format, true /* isOutput */); 8981 8982 AudioTrack track = null; 8983 int redirectMode = getCallRedirectMode(); 8984 if (redirectMode == CALL_REDIRECT_NONE) { 8985 throw new IllegalStateException( 8986 " not available in mode " + AudioSystem.modeToString(getMode())); 8987 } else if (redirectMode == CALL_REDIRECT_PSTN && !isPstnCallAudioInterceptable()) { 8988 throw new UnsupportedOperationException(" PSTN Call audio not accessible "); 8989 } 8990 8991 track = new AudioTrack.Builder() 8992 .setAudioAttributes(new AudioAttributes.Builder() 8993 .setSystemUsage(AudioAttributes.USAGE_CALL_ASSISTANT) 8994 .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH) 8995 .build()) 8996 .setAudioFormat(format) 8997 .setCallRedirectionMode(redirectMode) 8998 .build(); 8999 9000 if (track != null && track.getState() != AudioTrack.STATE_UNINITIALIZED) { 9001 synchronized (mCallRedirectionLock) { 9002 if (mCallRedirectionModeListener == null) { 9003 mCallRedirectionModeListener = new CallInjectionModeChangedListener(); 9004 try { 9005 addOnModeChangedListener( 9006 Executors.newSingleThreadExecutor(), mCallRedirectionModeListener); 9007 } catch (Exception e) { 9008 Log.e(TAG, "addOnModeChangedListener failed with exception: " + e); 9009 mCallRedirectionModeListener = null; 9010 throw new UnsupportedOperationException(" Cannot register mode listener "); 9011 } 9012 mCallIRedirectionClients = new ArrayList<CallIRedirectionClientInfo>(); 9013 } 9014 CallIRedirectionClientInfo info = new CallIRedirectionClientInfo(); 9015 info.redirectMode = redirectMode; 9016 info.trackOrRecord = new WeakReference<AudioTrack>(track); 9017 mCallIRedirectionClients.add(info); 9018 } 9019 } else { 9020 throw new UnsupportedOperationException(" Cannot create the AudioTrack"); 9021 } 9022 return track; 9023 } 9024 9025 /** 9026 * @hide 9027 * Returns an AudioRecord that can be used to extract audio from an active call downlink. 9028 * This can be used for functions like call screening or call audio redirection and is reserved 9029 * to system apps with privileged permission. 9030 * @param format the desired audio format for audio capture. 9031 *<p>Formats accepted are: 9032 * <ul> 9033 * <li><em>Sampling rate</em> - 8kHz to 48kHz. </li> 9034 * <li><em>Channel mask</em> - Mono or Stereo </li> 9035 * <li><em>Sample format</em> - PCM 16 bit or FLOAT 32 bit </li> 9036 * </ul> 9037 * 9038 * @return The AudioRecord used for audio extraction 9039 * @throws UnsupportedOperationException if on unsupported AudioFormat is specified. 9040 * @throws IllegalArgumentException if an invalid AudioFormat is specified. 9041 * @throws NullPointerException if AudioFormat argument is null. 9042 * @throws SecurityException if permission CALL_AUDIO_INTERCEPTION is missing . 9043 * @throws IllegalStateException if current audio mode is not MODE_IN_CALL, 9044 * MODE_IN_COMMUNICATION, MODE_CALL_SCREENING, MODE_CALL_REDIRECT 9045 * or MODE_COMMUNICATION_REDIRECT. 9046 */ 9047 @TestApi 9048 @SystemApi 9049 @RequiresPermission(Manifest.permission.CALL_AUDIO_INTERCEPTION) getCallDownlinkExtractionAudioRecord(@onNull AudioFormat format)9050 public @NonNull AudioRecord getCallDownlinkExtractionAudioRecord(@NonNull AudioFormat format) { 9051 Objects.requireNonNull(format); 9052 checkCallRedirectionFormat(format, false /* isOutput */); 9053 9054 AudioRecord record = null; 9055 int redirectMode = getCallRedirectMode(); 9056 if (redirectMode == CALL_REDIRECT_NONE) { 9057 throw new IllegalStateException( 9058 " not available in mode " + AudioSystem.modeToString(getMode())); 9059 } else if (redirectMode == CALL_REDIRECT_PSTN && !isPstnCallAudioInterceptable()) { 9060 throw new UnsupportedOperationException(" PSTN Call audio not accessible "); 9061 } 9062 9063 record = new AudioRecord.Builder() 9064 .setAudioAttributes(new AudioAttributes.Builder() 9065 .setInternalCapturePreset(MediaRecorder.AudioSource.VOICE_DOWNLINK) 9066 .build()) 9067 .setAudioFormat(format) 9068 .setCallRedirectionMode(redirectMode) 9069 .build(); 9070 9071 if (record != null && record.getState() != AudioRecord.STATE_UNINITIALIZED) { 9072 synchronized (mCallRedirectionLock) { 9073 if (mCallRedirectionModeListener == null) { 9074 mCallRedirectionModeListener = new CallInjectionModeChangedListener(); 9075 try { 9076 addOnModeChangedListener( 9077 Executors.newSingleThreadExecutor(), mCallRedirectionModeListener); 9078 } catch (Exception e) { 9079 Log.e(TAG, "addOnModeChangedListener failed with exception: " + e); 9080 mCallRedirectionModeListener = null; 9081 throw new UnsupportedOperationException(" Cannot register mode listener "); 9082 } 9083 mCallIRedirectionClients = new ArrayList<CallIRedirectionClientInfo>(); 9084 } 9085 CallIRedirectionClientInfo info = new CallIRedirectionClientInfo(); 9086 info.redirectMode = redirectMode; 9087 info.trackOrRecord = new WeakReference<AudioRecord>(record); 9088 mCallIRedirectionClients.add(info); 9089 } 9090 } else { 9091 throw new UnsupportedOperationException(" Cannot create the AudioRecord"); 9092 } 9093 return record; 9094 } 9095 9096 class CallInjectionModeChangedListener implements OnModeChangedListener { 9097 @Override onModeChanged(@udioMode int mode)9098 public void onModeChanged(@AudioMode int mode) { 9099 synchronized (mCallRedirectionLock) { 9100 final ArrayList<CallIRedirectionClientInfo> clientInfos = 9101 (ArrayList<CallIRedirectionClientInfo>) mCallIRedirectionClients.clone(); 9102 for (CallIRedirectionClientInfo info : clientInfos) { 9103 Object trackOrRecord = info.trackOrRecord.get(); 9104 if (trackOrRecord != null) { 9105 if ((info.redirectMode == CALL_REDIRECT_PSTN 9106 && mode != MODE_IN_CALL && mode != MODE_CALL_SCREENING 9107 && mode != MODE_CALL_REDIRECT) 9108 || (info.redirectMode == CALL_REDIRECT_VOIP 9109 && mode != MODE_IN_COMMUNICATION 9110 && mode != MODE_COMMUNICATION_REDIRECT)) { 9111 if (trackOrRecord instanceof AudioTrack) { 9112 AudioTrack track = (AudioTrack) trackOrRecord; 9113 track.release(); 9114 } else { 9115 AudioRecord record = (AudioRecord) trackOrRecord; 9116 record.release(); 9117 } 9118 mCallIRedirectionClients.remove(info); 9119 } 9120 } 9121 } 9122 if (mCallIRedirectionClients.isEmpty()) { 9123 try { 9124 if (mCallRedirectionModeListener != null) { 9125 removeOnModeChangedListener(mCallRedirectionModeListener); 9126 } 9127 } catch (Exception e) { 9128 Log.e(TAG, "removeOnModeChangedListener failed with exception: " + e); 9129 } finally { 9130 mCallRedirectionModeListener = null; 9131 mCallIRedirectionClients = null; 9132 } 9133 } 9134 } 9135 } 9136 } 9137 9138 //--------------------------------------------------------- 9139 // audio device connection-dependent muting 9140 /** 9141 * @hide 9142 * Mute a set of playback use cases until a given audio device is connected. 9143 * Automatically unmute upon connection of the device, or after the given timeout, whichever 9144 * happens first. 9145 * @param usagesToMute non-empty array of {@link AudioAttributes} usages (for example 9146 * {@link AudioAttributes#USAGE_MEDIA}) to mute until the 9147 * device connects 9148 * @param device the audio device expected to connect within the timeout duration 9149 * @param timeout the maximum amount of time to wait for the device connection 9150 * @param timeUnit the unit for the timeout 9151 * @throws IllegalStateException when trying to issue the command while another is already in 9152 * progress and hasn't been cancelled by 9153 * {@link #cancelMuteAwaitConnection(AudioDeviceAttributes)}. See 9154 * {@link #getMutingExpectedDevice()} to check if a muting command is active. 9155 * @see #registerMuteAwaitConnectionCallback(Executor, AudioManager.MuteAwaitConnectionCallback) 9156 */ 9157 @SystemApi 9158 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) muteAwaitConnection(@onNull int[] usagesToMute, @NonNull AudioDeviceAttributes device, long timeout, @NonNull TimeUnit timeUnit)9159 public void muteAwaitConnection(@NonNull int[] usagesToMute, 9160 @NonNull AudioDeviceAttributes device, 9161 long timeout, @NonNull TimeUnit timeUnit) throws IllegalStateException { 9162 if (timeout <= 0) { 9163 throw new IllegalArgumentException("Timeout must be greater than 0"); 9164 } 9165 Objects.requireNonNull(usagesToMute); 9166 if (usagesToMute.length == 0) { 9167 throw new IllegalArgumentException("Array of usages to mute cannot be empty"); 9168 } 9169 Objects.requireNonNull(device); 9170 Objects.requireNonNull(timeUnit); 9171 try { 9172 getService().muteAwaitConnection(usagesToMute, device, timeUnit.toMillis(timeout)); 9173 } catch (RemoteException e) { 9174 throw e.rethrowFromSystemServer(); 9175 } 9176 } 9177 9178 /** 9179 * @hide 9180 * Query which audio device, if any, is causing some playback use cases to be muted until it 9181 * connects. 9182 * @return the audio device used in 9183 * {@link #muteAwaitConnection(int[], AudioDeviceAttributes, long, TimeUnit)}, or null 9184 * if there is no active muting command (either because the muting command was not issued 9185 * or because it timed out) 9186 */ 9187 @SystemApi 9188 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) getMutingExpectedDevice()9189 public @Nullable AudioDeviceAttributes getMutingExpectedDevice() { 9190 try { 9191 return getService().getMutingExpectedDevice(); 9192 } catch (RemoteException e) { 9193 throw e.rethrowFromSystemServer(); 9194 } 9195 } 9196 9197 /** 9198 * @hide 9199 * Cancel a {@link #muteAwaitConnection(int[], AudioDeviceAttributes, long, TimeUnit)} 9200 * command. 9201 * @param device the device whose connection was expected when the {@code muteAwaitConnection} 9202 * command was issued. 9203 * @throws IllegalStateException when trying to issue the command for a device whose connection 9204 * is not anticipated by a previous call to 9205 * {@link #muteAwaitConnection(int[], AudioDeviceAttributes, long, TimeUnit)} 9206 */ 9207 @SystemApi 9208 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) cancelMuteAwaitConnection(@onNull AudioDeviceAttributes device)9209 public void cancelMuteAwaitConnection(@NonNull AudioDeviceAttributes device) 9210 throws IllegalStateException { 9211 Objects.requireNonNull(device); 9212 try { 9213 getService().cancelMuteAwaitConnection(device); 9214 } catch (RemoteException e) { 9215 throw e.rethrowFromSystemServer(); 9216 } 9217 } 9218 9219 /** 9220 * @hide 9221 * A callback class to receive events about the muting and unmuting of playback use cases 9222 * conditional on the upcoming connection of an audio device. 9223 * @see #registerMuteAwaitConnectionCallback(Executor, AudioManager.MuteAwaitConnectionCallback) 9224 */ 9225 @SystemApi 9226 public abstract static class MuteAwaitConnectionCallback { 9227 9228 /** 9229 * An event where the expected audio device connected 9230 * @see MuteAwaitConnectionCallback#onUnmutedEvent(int, AudioDeviceAttributes, int[]) 9231 */ 9232 public static final int EVENT_CONNECTION = 1; 9233 /** 9234 * An event where the expected audio device failed connect before the timeout happened 9235 * @see MuteAwaitConnectionCallback#onUnmutedEvent(int, AudioDeviceAttributes, int[]) 9236 */ 9237 public static final int EVENT_TIMEOUT = 2; 9238 /** 9239 * An event where the {@code muteAwaitConnection()} command 9240 * was cancelled with {@link #cancelMuteAwaitConnection(AudioDeviceAttributes)} 9241 * @see MuteAwaitConnectionCallback#onUnmutedEvent(int, AudioDeviceAttributes, int[]) 9242 */ 9243 public static final int EVENT_CANCEL = 3; 9244 9245 /** @hide */ 9246 @IntDef(flag = false, prefix = "EVENT_", value = { 9247 EVENT_CONNECTION, 9248 EVENT_TIMEOUT, 9249 EVENT_CANCEL } 9250 ) 9251 @Retention(RetentionPolicy.SOURCE) 9252 public @interface UnmuteEvent {} 9253 9254 /** 9255 * Called when a number of playback use cases are muted in response to a call to 9256 * {@link #muteAwaitConnection(int[], AudioDeviceAttributes, long, TimeUnit)}. 9257 * @param device the audio device whose connection is expected. Playback use cases are 9258 * unmuted when that device connects 9259 * @param mutedUsages an array of {@link AudioAttributes} usages that describe the affected 9260 * playback use cases. 9261 */ onMutedUntilConnection( @onNull AudioDeviceAttributes device, @NonNull int[] mutedUsages)9262 public void onMutedUntilConnection( 9263 @NonNull AudioDeviceAttributes device, 9264 @NonNull int[] mutedUsages) {} 9265 9266 /** 9267 * Called when an event occurred that caused playback uses cases to be unmuted 9268 * @param unmuteEvent the nature of the event 9269 * @param device the device that was expected to connect 9270 * @param mutedUsages the array of {@link AudioAttributes} usages that were muted until 9271 * the event occurred 9272 */ onUnmutedEvent( @nmuteEvent int unmuteEvent, @NonNull AudioDeviceAttributes device, @NonNull int[] mutedUsages)9273 public void onUnmutedEvent( 9274 @UnmuteEvent int unmuteEvent, 9275 @NonNull AudioDeviceAttributes device, @NonNull int[] mutedUsages) {} 9276 } 9277 9278 9279 /** 9280 * @hide 9281 * Register a callback to receive updates on the playback muting conditional on a specific 9282 * audio device connection. 9283 * @param executor the {@link Executor} handling the callback 9284 * @param callback the callback to register 9285 */ 9286 @SystemApi 9287 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) registerMuteAwaitConnectionCallback( @onNull @allbackExecutor Executor executor, @NonNull MuteAwaitConnectionCallback callback)9288 public void registerMuteAwaitConnectionCallback( 9289 @NonNull @CallbackExecutor Executor executor, 9290 @NonNull MuteAwaitConnectionCallback callback) { 9291 synchronized (mMuteAwaitConnectionListenerLock) { 9292 final Pair<ArrayList<ListenerInfo<MuteAwaitConnectionCallback>>, 9293 MuteAwaitConnectionDispatcherStub> res = 9294 CallbackUtil.addListener("registerMuteAwaitConnectionCallback", 9295 executor, callback, mMuteAwaitConnectionListeners, 9296 mMuteAwaitConnDispatcherStub, 9297 () -> new MuteAwaitConnectionDispatcherStub(), 9298 stub -> stub.register(true)); 9299 mMuteAwaitConnectionListeners = res.first; 9300 mMuteAwaitConnDispatcherStub = res.second; 9301 } 9302 } 9303 9304 /** 9305 * @hide 9306 * Unregister a previously registered callback for playback muting conditional on device 9307 * connection. 9308 * @param callback the callback to unregister 9309 */ 9310 @SystemApi 9311 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) unregisterMuteAwaitConnectionCallback( @onNull MuteAwaitConnectionCallback callback)9312 public void unregisterMuteAwaitConnectionCallback( 9313 @NonNull MuteAwaitConnectionCallback callback) { 9314 synchronized (mMuteAwaitConnectionListenerLock) { 9315 final Pair<ArrayList<ListenerInfo<MuteAwaitConnectionCallback>>, 9316 MuteAwaitConnectionDispatcherStub> res = 9317 CallbackUtil.removeListener("unregisterMuteAwaitConnectionCallback", 9318 callback, mMuteAwaitConnectionListeners, mMuteAwaitConnDispatcherStub, 9319 stub -> stub.register(false)); 9320 mMuteAwaitConnectionListeners = res.first; 9321 mMuteAwaitConnDispatcherStub = res.second; 9322 } 9323 } 9324 9325 /** 9326 * Add UIDs that can be considered as assistant. 9327 * 9328 * @param assistantUids UIDs of the services that can be considered as assistant. 9329 * 9330 * @hide 9331 */ 9332 @SystemApi 9333 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) addAssistantServicesUids(@onNull int[] assistantUids)9334 public void addAssistantServicesUids(@NonNull int[] assistantUids) { 9335 try { 9336 getService().addAssistantServicesUids(assistantUids); 9337 } catch (RemoteException e) { 9338 throw e.rethrowFromSystemServer(); 9339 } 9340 } 9341 9342 /** 9343 * Remove UIDs that can be considered as assistant. 9344 * 9345 * @param assistantUids UIDs of the services that should be remove. 9346 * 9347 * @hide 9348 */ 9349 @SystemApi 9350 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) removeAssistantServicesUids(@onNull int[] assistantUids)9351 public void removeAssistantServicesUids(@NonNull int[] assistantUids) { 9352 try { 9353 getService().removeAssistantServicesUids(assistantUids); 9354 } catch (RemoteException e) { 9355 throw e.rethrowFromSystemServer(); 9356 } 9357 } 9358 9359 /** 9360 * Get the assistants UIDs that been added with the 9361 * {@link #addAssistantServicesUids(int[])} and not yet removed with 9362 * {@link #removeAssistantServicesUids(int[])} 9363 * 9364 * <p> Note that during native audioserver crash and after boot up the list of assistant 9365 * UIDs will be reset to an empty list (i.e. no UID will be considered as assistant) 9366 * Just after user switch, the list of assistant will also reset to empty. 9367 * In both cases,The component's UID of the assistiant role or assistant setting will be 9368 * automitically added to the list by the audio service. 9369 * 9370 * @return array of assistants UIDs 9371 * 9372 * @hide 9373 */ 9374 @SystemApi 9375 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) getAssistantServicesUids()9376 public @NonNull int[] getAssistantServicesUids() { 9377 try { 9378 int[] uids = getService().getAssistantServicesUids(); 9379 return Arrays.copyOf(uids, uids.length); 9380 } catch (RemoteException e) { 9381 throw e.rethrowFromSystemServer(); 9382 } 9383 } 9384 9385 /** 9386 * Sets UIDs that can be considered as active assistant. Calling the API with a new array will 9387 * overwrite previous UIDs. If the array of UIDs is empty then no UID will be considered active. 9388 * In this manner calling the API with an empty array will remove all UIDs previously set. 9389 * 9390 * @param assistantUids UIDs of the services that can be considered active assistant. Can be 9391 * an empty array, for this no UID will be considered active. 9392 * 9393 * <p> Note that during audio service crash reset and after boot up the list of active assistant 9394 * UIDs will be reset to an empty list (i.e. no UID will be considered as an active assistant). 9395 * Just after user switch the list of active assistant will also reset to empty. 9396 * 9397 * @hide 9398 */ 9399 @SystemApi 9400 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) setActiveAssistantServiceUids(@onNull int[] assistantUids)9401 public void setActiveAssistantServiceUids(@NonNull int[] assistantUids) { 9402 try { 9403 getService().setActiveAssistantServiceUids(assistantUids); 9404 } catch (RemoteException e) { 9405 throw e.rethrowFromSystemServer(); 9406 } 9407 } 9408 9409 /** 9410 * Get active assistant UIDs last set with the 9411 * {@link #setActiveAssistantServiceUids(int[])} 9412 * 9413 * @return array of active assistants UIDs 9414 * 9415 * @hide 9416 */ 9417 @SystemApi 9418 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) getActiveAssistantServicesUids()9419 public @NonNull int[] getActiveAssistantServicesUids() { 9420 try { 9421 int[] uids = getService().getActiveAssistantServiceUids(); 9422 return Arrays.copyOf(uids, uids.length); 9423 } catch (RemoteException e) { 9424 throw e.rethrowFromSystemServer(); 9425 } 9426 } 9427 9428 /** 9429 * Returns an {@link AudioHalVersionInfo} indicating the Audio Hal Version. If there is no audio 9430 * HAL found, null will be returned. 9431 * 9432 * @return @see @link #AudioHalVersionInfo The version of Audio HAL. 9433 * @hide 9434 */ 9435 @TestApi getHalVersion()9436 public static @Nullable AudioHalVersionInfo getHalVersion() { 9437 try { 9438 return getService().getHalVersion(); 9439 } catch (RemoteException e) { 9440 Log.e(TAG, "Error querying getHalVersion", e); 9441 throw e.rethrowFromSystemServer(); 9442 } 9443 } 9444 9445 //==================================================================== 9446 // Preferred mixer attributes 9447 9448 /** 9449 * Returns the {@link AudioMixerAttributes} that can be used to set as preferred mixer 9450 * attributes via {@link #setPreferredMixerAttributes( 9451 * AudioAttributes, AudioDeviceInfo, AudioMixerAttributes)}. 9452 * <p>Note that only USB devices are guaranteed to expose configurable mixer attributes. An 9453 * empty list may be returned for all other types of devices as they may not allow dynamic 9454 * configuration. 9455 * 9456 * @param device the device to query 9457 * @return a list of {@link AudioMixerAttributes} that can be used as preferred mixer attributes 9458 * for the given device. 9459 * @see #setPreferredMixerAttributes(AudioAttributes, AudioDeviceInfo, AudioMixerAttributes) 9460 */ 9461 @NonNull getSupportedMixerAttributes(@onNull AudioDeviceInfo device)9462 public List<AudioMixerAttributes> getSupportedMixerAttributes(@NonNull AudioDeviceInfo device) { 9463 Objects.requireNonNull(device); 9464 List<AudioMixerAttributes> mixerAttrs = new ArrayList<>(); 9465 return (AudioSystem.getSupportedMixerAttributes(device.getId(), mixerAttrs) 9466 == AudioSystem.SUCCESS) ? mixerAttrs : new ArrayList<>(); 9467 } 9468 9469 /** 9470 * Configures the mixer attributes for a particular {@link AudioAttributes} over a given 9471 * {@link AudioDeviceInfo}. 9472 * <p>Call {@link #getSupportedMixerAttributes(AudioDeviceInfo)} to determine which mixer 9473 * attributes can be used with the given device. 9474 * <p>The ownership of preferred mixer attributes is recognized by uid. When a playback from the 9475 * same uid is routed to the given audio device when calling this API, the output mixer/stream 9476 * will be configured with the values previously set via this API. 9477 * <p>Use {@link #clearPreferredMixerAttributes(AudioAttributes, AudioDeviceInfo)} 9478 * to cancel setting mixer attributes for this {@link AudioAttributes}. 9479 * 9480 * @param attributes the {@link AudioAttributes} whose mixer attributes should be set. 9481 * Currently, only {@link AudioAttributes#USAGE_MEDIA} is supported. When 9482 * playing audio targeted at the given device, use the same attributes for 9483 * playback. 9484 * @param device the device to be routed. Currently, only USB device will be allowed. 9485 * @param mixerAttributes the preferred mixer attributes. When playing audio targeted at the 9486 * given device, use the same {@link AudioFormat} for both playback 9487 * and the mixer attributes. 9488 * @return true only if the preferred mixer attributes are set successfully. 9489 * @see #getPreferredMixerAttributes(AudioAttributes, AudioDeviceInfo) 9490 * @see #clearPreferredMixerAttributes(AudioAttributes, AudioDeviceInfo) 9491 */ 9492 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS) setPreferredMixerAttributes(@onNull AudioAttributes attributes, @NonNull AudioDeviceInfo device, @NonNull AudioMixerAttributes mixerAttributes)9493 public boolean setPreferredMixerAttributes(@NonNull AudioAttributes attributes, 9494 @NonNull AudioDeviceInfo device, 9495 @NonNull AudioMixerAttributes mixerAttributes) { 9496 Objects.requireNonNull(attributes); 9497 Objects.requireNonNull(device); 9498 Objects.requireNonNull(mixerAttributes); 9499 try { 9500 final int status = getService().setPreferredMixerAttributes( 9501 attributes, device.getId(), mixerAttributes); 9502 return status == AudioSystem.SUCCESS; 9503 } catch (RemoteException e) { 9504 throw e.rethrowFromSystemServer(); 9505 } 9506 } 9507 9508 /** 9509 * Returns current preferred mixer attributes that is set via 9510 * {@link #setPreferredMixerAttributes(AudioAttributes, AudioDeviceInfo, AudioMixerAttributes)} 9511 * 9512 * @param attributes the {@link AudioAttributes} whose mixer attributes should be set. 9513 * @param device the expected routing device 9514 * @return the preferred mixer attributes, which will be null when no preferred mixer attributes 9515 * have been set, or when they have been cleared. 9516 * @see #setPreferredMixerAttributes(AudioAttributes, AudioDeviceInfo, AudioMixerAttributes) 9517 * @see #clearPreferredMixerAttributes(AudioAttributes, AudioDeviceInfo) 9518 */ 9519 @Nullable getPreferredMixerAttributes( @onNull AudioAttributes attributes, @NonNull AudioDeviceInfo device)9520 public AudioMixerAttributes getPreferredMixerAttributes( 9521 @NonNull AudioAttributes attributes, 9522 @NonNull AudioDeviceInfo device) { 9523 Objects.requireNonNull(attributes); 9524 Objects.requireNonNull(device); 9525 List<AudioMixerAttributes> mixerAttrList = new ArrayList<>(); 9526 int ret = AudioSystem.getPreferredMixerAttributes( 9527 attributes, device.getId(), mixerAttrList); 9528 if (ret == AudioSystem.SUCCESS) { 9529 return mixerAttrList.isEmpty() ? null : mixerAttrList.get(0); 9530 } else { 9531 Log.e(TAG, "Failed calling getPreferredMixerAttributes, ret=" + ret); 9532 return null; 9533 } 9534 } 9535 9536 /** 9537 * Clears the current preferred mixer attributes that were previously set via 9538 * {@link #setPreferredMixerAttributes(AudioAttributes, AudioDeviceInfo, AudioMixerAttributes)} 9539 * 9540 * @param attributes the {@link AudioAttributes} whose mixer attributes should be cleared. 9541 * @param device the expected routing device 9542 * @return true only if the preferred mixer attributes are removed successfully. 9543 * @see #setPreferredMixerAttributes(AudioAttributes, AudioDeviceInfo, AudioMixerAttributes) 9544 * @see #getPreferredMixerAttributes(AudioAttributes, AudioDeviceInfo) 9545 */ 9546 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS) clearPreferredMixerAttributes( @onNull AudioAttributes attributes, @NonNull AudioDeviceInfo device)9547 public boolean clearPreferredMixerAttributes( 9548 @NonNull AudioAttributes attributes, 9549 @NonNull AudioDeviceInfo device) { 9550 Objects.requireNonNull(attributes); 9551 Objects.requireNonNull(device); 9552 try { 9553 final int status = getService().clearPreferredMixerAttributes( 9554 attributes, device.getId()); 9555 return status == AudioSystem.SUCCESS; 9556 } catch (RemoteException e) { 9557 throw e.rethrowFromSystemServer(); 9558 } 9559 } 9560 9561 /** 9562 * Interface to be notified of changes in the preferred mixer attributes. 9563 * <p>Note that this listener will only be invoked whenever 9564 * {@link #setPreferredMixerAttributes(AudioAttributes, AudioDeviceInfo, AudioMixerAttributes)} 9565 * or {@link #clearPreferredMixerAttributes(AudioAttributes, AudioDeviceInfo)} or device 9566 * disconnection causes a change in preferred mixer attributes. 9567 * @see #setPreferredMixerAttributes(AudioAttributes, AudioDeviceInfo, AudioMixerAttributes) 9568 * @see #clearPreferredMixerAttributes(AudioAttributes, AudioDeviceInfo) 9569 */ 9570 public interface OnPreferredMixerAttributesChangedListener { 9571 /** 9572 * Called on the listener to indicate that the preferred mixer attributes for the audio 9573 * attributes over the given device has changed. 9574 * 9575 * @param attributes the audio attributes for playback 9576 * @param device the targeted device 9577 * @param mixerAttributes the {@link AudioMixerAttributes} that contains information for 9578 * preferred mixer attributes or null if preferred mixer attributes 9579 * is cleared 9580 */ onPreferredMixerAttributesChanged( @onNull AudioAttributes attributes, @NonNull AudioDeviceInfo device, @Nullable AudioMixerAttributes mixerAttributes)9581 void onPreferredMixerAttributesChanged( 9582 @NonNull AudioAttributes attributes, 9583 @NonNull AudioDeviceInfo device, 9584 @Nullable AudioMixerAttributes mixerAttributes); 9585 } 9586 9587 /** 9588 * Manage the {@link OnPreferredMixerAttributesChangedListener} listeners and the 9589 * {@link PreferredMixerAttributesDispatcherStub}. 9590 */ 9591 private final CallbackUtil.LazyListenerManager<OnPreferredMixerAttributesChangedListener> 9592 mPrefMixerAttributesListenerMgr = new CallbackUtil.LazyListenerManager(); 9593 9594 /** 9595 * Adds a listener for being notified of changes to the preferred mixer attributes. 9596 * @param executor the executor to execute the callback 9597 * @param listener the listener to be notified of changes in the preferred mixer attributes. 9598 */ addOnPreferredMixerAttributesChangedListener( @onNull @allbackExecutor Executor executor, @NonNull OnPreferredMixerAttributesChangedListener listener)9599 public void addOnPreferredMixerAttributesChangedListener( 9600 @NonNull @CallbackExecutor Executor executor, 9601 @NonNull OnPreferredMixerAttributesChangedListener listener) { 9602 Objects.requireNonNull(executor); 9603 Objects.requireNonNull(listener); 9604 mPrefMixerAttributesListenerMgr.addListener(executor, listener, 9605 "addOnPreferredMixerAttributesChangedListener", 9606 () -> new PreferredMixerAttributesDispatcherStub()); 9607 } 9608 9609 /** 9610 * Removes a previously added listener of changes to the preferred mixer attributes. 9611 * @param listener the listener to be notified of changes in the preferred mixer attributes, 9612 * which were added via {@link #addOnPreferredMixerAttributesChangedListener( 9613 * Executor, OnPreferredMixerAttributesChangedListener)}. 9614 */ removeOnPreferredMixerAttributesChangedListener( @onNull OnPreferredMixerAttributesChangedListener listener)9615 public void removeOnPreferredMixerAttributesChangedListener( 9616 @NonNull OnPreferredMixerAttributesChangedListener listener) { 9617 Objects.requireNonNull(listener); 9618 mPrefMixerAttributesListenerMgr.removeListener(listener, 9619 "removeOnPreferredMixerAttributesChangedListener"); 9620 } 9621 9622 private final class PreferredMixerAttributesDispatcherStub 9623 extends IPreferredMixerAttributesDispatcher.Stub 9624 implements CallbackUtil.DispatcherStub { 9625 9626 @Override register(boolean register)9627 public void register(boolean register) { 9628 try { 9629 if (register) { 9630 getService().registerPreferredMixerAttributesDispatcher(this); 9631 } else { 9632 getService().unregisterPreferredMixerAttributesDispatcher(this); 9633 } 9634 } catch (RemoteException e) { 9635 e.rethrowFromSystemServer(); 9636 } 9637 } 9638 9639 @Override dispatchPrefMixerAttributesChanged(@onNull AudioAttributes attr, int deviceId, @Nullable AudioMixerAttributes mixerAttr)9640 public void dispatchPrefMixerAttributesChanged(@NonNull AudioAttributes attr, 9641 int deviceId, 9642 @Nullable AudioMixerAttributes mixerAttr) { 9643 // TODO: If the device is disconnected, we may not be able to find the device with 9644 // given device id. We need a better to carry the device information via binder. 9645 AudioDeviceInfo device = getDeviceForPortId(deviceId, GET_DEVICES_OUTPUTS); 9646 if (device == null) { 9647 Log.d(TAG, "Drop preferred mixer attributes changed as the device(" 9648 + deviceId + ") is disconnected"); 9649 return; 9650 } 9651 mPrefMixerAttributesListenerMgr.callListeners( 9652 (listener) -> listener.onPreferredMixerAttributesChanged( 9653 attr, device, mixerAttr)); 9654 } 9655 } 9656 9657 /** 9658 * Requests if the implementation supports controlling the latency modes 9659 * over the Bluetooth A2DP or LE Audio links. 9660 * 9661 * @return true if supported, false otherwise 9662 * 9663 * @hide 9664 */ 9665 @SystemApi 9666 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) supportsBluetoothVariableLatency()9667 public boolean supportsBluetoothVariableLatency() { 9668 try { 9669 return getService().supportsBluetoothVariableLatency(); 9670 } catch (RemoteException e) { 9671 throw e.rethrowFromSystemServer(); 9672 } 9673 } 9674 9675 /** 9676 * Enables or disables the variable Bluetooth latency control mechanism in the 9677 * audio framework and the audio HAL. This does not apply to the latency mode control 9678 * on the spatializer output as this is a built-in feature. 9679 * 9680 * @hide 9681 */ 9682 @SystemApi 9683 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) setBluetoothVariableLatencyEnabled(boolean enabled)9684 public void setBluetoothVariableLatencyEnabled(boolean enabled) { 9685 try { 9686 getService().setBluetoothVariableLatencyEnabled(enabled); 9687 } catch (RemoteException e) { 9688 throw e.rethrowFromSystemServer(); 9689 } 9690 } 9691 9692 /** 9693 * Indicates if the variable Bluetooth latency control mechanism is enabled or disabled. 9694 * @hide 9695 */ 9696 @SystemApi 9697 @RequiresPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) isBluetoothVariableLatencyEnabled()9698 public boolean isBluetoothVariableLatencyEnabled() { 9699 try { 9700 return getService().isBluetoothVariableLatencyEnabled(); 9701 } catch (RemoteException e) { 9702 throw e.rethrowFromSystemServer(); 9703 } 9704 } 9705 9706 //==================================================================== 9707 // Stream aliasing changed listener, getter for stream alias or independent streams 9708 9709 /** 9710 * manages the stream aliasing listeners and StreamAliasingDispatcherStub 9711 */ 9712 private final CallbackUtil.LazyListenerManager<Runnable> mStreamAliasingListenerMgr = 9713 new CallbackUtil.LazyListenerManager(); 9714 9715 9716 final class StreamAliasingDispatcherStub extends IStreamAliasingDispatcher.Stub 9717 implements CallbackUtil.DispatcherStub { 9718 9719 @Override register(boolean register)9720 public void register(boolean register) { 9721 try { 9722 getService().registerStreamAliasingDispatcher(this, register); 9723 } catch (RemoteException e) { 9724 e.rethrowFromSystemServer(); 9725 } 9726 } 9727 9728 @Override dispatchStreamAliasingChanged()9729 public void dispatchStreamAliasingChanged() { 9730 mStreamAliasingListenerMgr.callListeners((listener) -> listener.run()); 9731 } 9732 } 9733 9734 /** 9735 * @hide 9736 * Adds a listener to be notified of changes to volume stream type aliasing. 9737 * See {@link #getIndependentStreamTypes()} and {@link #getStreamTypeAlias(int)} 9738 * @param executor the Executor running the listener 9739 * @param onStreamAliasingChangedListener the listener to add for the aliasing changes 9740 */ 9741 @SystemApi 9742 @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED) addOnStreamAliasingChangedListener( @onNull @allbackExecutor Executor executor, @NonNull Runnable onStreamAliasingChangedListener)9743 public void addOnStreamAliasingChangedListener( 9744 @NonNull @CallbackExecutor Executor executor, 9745 @NonNull Runnable onStreamAliasingChangedListener) { 9746 mStreamAliasingListenerMgr.addListener(executor, onStreamAliasingChangedListener, 9747 "addOnStreamAliasingChangedListener", 9748 () -> new StreamAliasingDispatcherStub()); 9749 } 9750 9751 /** 9752 * @hide 9753 * Removes a previously added listener for changes to stream aliasing. 9754 * See {@link #getIndependentStreamTypes()} and {@link #getStreamTypeAlias(int)} 9755 * @see #addOnStreamAliasingChangedListener(Executor, Runnable) 9756 * @param onStreamAliasingChangedListener the previously added listener of aliasing changes 9757 */ 9758 @SystemApi 9759 @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED) removeOnStreamAliasingChangedListener( @onNull Runnable onStreamAliasingChangedListener)9760 public void removeOnStreamAliasingChangedListener( 9761 @NonNull Runnable onStreamAliasingChangedListener) { 9762 mStreamAliasingListenerMgr.removeListener(onStreamAliasingChangedListener, 9763 "removeOnStreamAliasingChangedListener"); 9764 } 9765 9766 /** 9767 * @hide 9768 * Test method to temporarily override whether STREAM_NOTIFICATION is aliased to STREAM_RING, 9769 * volumes will be updated in case of a change. 9770 * @param isAliased if true, STREAM_NOTIFICATION is aliased to STREAM_RING 9771 */ 9772 @TestApi 9773 @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED) setNotifAliasRingForTest(boolean isAliased)9774 public void setNotifAliasRingForTest(boolean isAliased) { 9775 final IAudioService service = getService(); 9776 try { 9777 service.setNotifAliasRingForTest(isAliased); 9778 } catch (RemoteException e) { 9779 throw e.rethrowFromSystemServer(); 9780 } 9781 } 9782 9783 /** 9784 * @hide 9785 * Return the list of independent stream types for volume control. 9786 * A stream type is considered independent when the volume changes of that type do not 9787 * affect any other independent volume control stream type. 9788 * An independent stream type is its own alias when using {@link #getStreamTypeAlias(int)}. 9789 * @return list of independent stream types, where each value can be one of 9790 * {@link #STREAM_VOICE_CALL}, {@link #STREAM_SYSTEM}, {@link #STREAM_RING}, 9791 * {@link #STREAM_MUSIC}, {@link #STREAM_ALARM}, {@link #STREAM_NOTIFICATION}, 9792 * {@link #STREAM_DTMF} and {@link #STREAM_ACCESSIBILITY}. 9793 */ 9794 @SystemApi 9795 @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED) getIndependentStreamTypes()9796 public @NonNull List<Integer> getIndependentStreamTypes() { 9797 final IAudioService service = getService(); 9798 try { 9799 return service.getIndependentStreamTypes(); 9800 } catch (RemoteException e) { 9801 throw e.rethrowFromSystemServer(); 9802 } 9803 } 9804 9805 /** 9806 * @hide 9807 * Return the stream type that a given stream is aliased to. 9808 * A stream alias means that any change to the source stream will also be applied to the alias, 9809 * and vice-versa. 9810 * If a stream is independent (i.e. part of the stream types returned by 9811 * {@link #getIndependentStreamTypes()}), its alias is itself. 9812 * @param sourceStreamType the stream type to query for the alias. 9813 * @return the stream type the source type is aliased to. 9814 */ 9815 @SystemApi 9816 @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED) getStreamTypeAlias(@ublicStreamTypes int sourceStreamType)9817 public @PublicStreamTypes int getStreamTypeAlias(@PublicStreamTypes int sourceStreamType) { 9818 final IAudioService service = getService(); 9819 try { 9820 return service.getStreamTypeAlias(sourceStreamType); 9821 } catch (RemoteException e) { 9822 throw e.rethrowFromSystemServer(); 9823 } 9824 } 9825 9826 /** 9827 * @hide 9828 * Returns whether the system uses {@link AudioVolumeGroup} for volume control 9829 * @return true when volume control is performed through volume groups, false if it uses 9830 * stream types. 9831 */ 9832 @TestApi 9833 @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED) isVolumeControlUsingVolumeGroups()9834 public boolean isVolumeControlUsingVolumeGroups() { 9835 final IAudioService service = getService(); 9836 try { 9837 return service.isVolumeControlUsingVolumeGroups(); 9838 } catch (RemoteException e) { 9839 throw e.rethrowFromSystemServer(); 9840 } 9841 } 9842 9843 //==================================================================== 9844 // Mute await connection 9845 9846 private final Object mMuteAwaitConnectionListenerLock = new Object(); 9847 9848 @GuardedBy("mMuteAwaitConnectionListenerLock") 9849 private @Nullable ArrayList<ListenerInfo<MuteAwaitConnectionCallback>> 9850 mMuteAwaitConnectionListeners; 9851 9852 @GuardedBy("mMuteAwaitConnectionListenerLock") 9853 private MuteAwaitConnectionDispatcherStub mMuteAwaitConnDispatcherStub; 9854 9855 private final class MuteAwaitConnectionDispatcherStub 9856 extends IMuteAwaitConnectionCallback.Stub { register(boolean register)9857 public void register(boolean register) { 9858 try { 9859 getService().registerMuteAwaitConnectionDispatcher(this, register); 9860 } catch (RemoteException e) { 9861 throw e.rethrowFromSystemServer(); 9862 } 9863 } 9864 9865 @Override 9866 @SuppressLint("GuardedBy") // lock applied inside callListeners method dispatchOnMutedUntilConnection(AudioDeviceAttributes device, int[] mutedUsages)9867 public void dispatchOnMutedUntilConnection(AudioDeviceAttributes device, 9868 int[] mutedUsages) { 9869 CallbackUtil.callListeners(mMuteAwaitConnectionListeners, 9870 mMuteAwaitConnectionListenerLock, 9871 (listener) -> listener.onMutedUntilConnection(device, mutedUsages)); 9872 } 9873 9874 @Override 9875 @SuppressLint("GuardedBy") // lock applied inside callListeners method dispatchOnUnmutedEvent(int event, AudioDeviceAttributes device, int[] mutedUsages)9876 public void dispatchOnUnmutedEvent(int event, AudioDeviceAttributes device, 9877 int[] mutedUsages) { 9878 CallbackUtil.callListeners(mMuteAwaitConnectionListeners, 9879 mMuteAwaitConnectionListenerLock, 9880 (listener) -> listener.onUnmutedEvent(event, device, mutedUsages)); 9881 } 9882 } 9883 9884 //--------------------------------------------------------- 9885 // Inner classes 9886 //-------------------- 9887 /** 9888 * Helper class to handle the forwarding of native events to the appropriate listener 9889 * (potentially) handled in a different thread. 9890 */ 9891 private class NativeEventHandlerDelegate { 9892 private final Handler mHandler; 9893 NativeEventHandlerDelegate(final AudioDeviceCallback callback, Handler handler)9894 NativeEventHandlerDelegate(final AudioDeviceCallback callback, 9895 Handler handler) { 9896 // find the looper for our new event handler 9897 Looper looper; 9898 if (handler != null) { 9899 looper = handler.getLooper(); 9900 } else { 9901 // no given handler, use the looper the addListener call was called in 9902 looper = Looper.getMainLooper(); 9903 } 9904 9905 // construct the event handler with this looper 9906 if (looper != null) { 9907 // implement the event handler delegate 9908 mHandler = new Handler(looper) { 9909 @Override 9910 public void handleMessage(Message msg) { 9911 switch(msg.what) { 9912 case MSG_DEVICES_CALLBACK_REGISTERED: 9913 case MSG_DEVICES_DEVICES_ADDED: 9914 if (callback != null) { 9915 callback.onAudioDevicesAdded((AudioDeviceInfo[])msg.obj); 9916 } 9917 break; 9918 9919 case MSG_DEVICES_DEVICES_REMOVED: 9920 if (callback != null) { 9921 callback.onAudioDevicesRemoved((AudioDeviceInfo[])msg.obj); 9922 } 9923 break; 9924 9925 default: 9926 Log.e(TAG, "Unknown native event type: " + msg.what); 9927 break; 9928 } 9929 } 9930 }; 9931 } else { 9932 mHandler = null; 9933 } 9934 } 9935 getHandler()9936 Handler getHandler() { 9937 return mHandler; 9938 } 9939 } 9940 } 9941