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 android.Manifest; 20 import android.annotation.NonNull; 21 import android.annotation.SdkConstant; 22 import android.annotation.SdkConstant.SdkConstantType; 23 import android.annotation.SystemApi; 24 import android.app.NotificationManager; 25 import android.app.PendingIntent; 26 import android.bluetooth.BluetoothDevice; 27 import android.content.ComponentName; 28 import android.content.Context; 29 import android.content.Intent; 30 import android.media.audiopolicy.AudioPolicy; 31 import android.media.session.MediaController; 32 import android.media.session.MediaSession; 33 import android.media.session.MediaSessionLegacyHelper; 34 import android.media.session.MediaSessionManager; 35 import android.os.Binder; 36 import android.os.Handler; 37 import android.os.IBinder; 38 import android.os.Looper; 39 import android.os.Message; 40 import android.os.Process; 41 import android.os.RemoteException; 42 import android.os.SystemClock; 43 import android.os.ServiceManager; 44 import android.os.UserHandle; 45 import android.provider.Settings; 46 import android.util.ArrayMap; 47 import android.util.Log; 48 import android.util.Pair; 49 import android.view.KeyEvent; 50 51 import java.util.ArrayList; 52 import java.util.Collection; 53 import java.util.HashMap; 54 import java.util.Iterator; 55 import java.util.List; 56 57 /** 58 * AudioManager provides access to volume and ringer mode control. 59 * <p> 60 * Use <code>Context.getSystemService(Context.AUDIO_SERVICE)</code> to get 61 * an instance of this class. 62 */ 63 public class AudioManager { 64 65 private Context mOriginalContext; 66 private Context mApplicationContext; 67 private long mVolumeKeyUpTime; 68 private final boolean mUseVolumeKeySounds; 69 private final boolean mUseFixedVolume; 70 private static String TAG = "AudioManager"; 71 private static final AudioPortEventHandler sAudioPortEventHandler = new AudioPortEventHandler(); 72 73 /** 74 * Broadcast intent, a hint for applications that audio is about to become 75 * 'noisy' due to a change in audio outputs. For example, this intent may 76 * be sent when a wired headset is unplugged, or when an A2DP audio 77 * sink is disconnected, and the audio system is about to automatically 78 * switch audio route to the speaker. Applications that are controlling 79 * audio streams may consider pausing, reducing volume or some other action 80 * on receipt of this intent so as not to surprise the user with audio 81 * from the speaker. 82 */ 83 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 84 public static final String ACTION_AUDIO_BECOMING_NOISY = "android.media.AUDIO_BECOMING_NOISY"; 85 86 /** 87 * Sticky broadcast intent action indicating that the ringer mode has 88 * changed. Includes the new ringer mode. 89 * 90 * @see #EXTRA_RINGER_MODE 91 */ 92 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 93 public static final String RINGER_MODE_CHANGED_ACTION = "android.media.RINGER_MODE_CHANGED"; 94 95 /** 96 * @hide 97 * Sticky broadcast intent action indicating that the internal ringer mode has 98 * changed. Includes the new ringer mode. 99 * 100 * @see #EXTRA_RINGER_MODE 101 */ 102 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 103 public static final String INTERNAL_RINGER_MODE_CHANGED_ACTION = 104 "android.media.INTERNAL_RINGER_MODE_CHANGED_ACTION"; 105 106 /** 107 * The new ringer mode. 108 * 109 * @see #RINGER_MODE_CHANGED_ACTION 110 * @see #RINGER_MODE_NORMAL 111 * @see #RINGER_MODE_SILENT 112 * @see #RINGER_MODE_VIBRATE 113 */ 114 public static final String EXTRA_RINGER_MODE = "android.media.EXTRA_RINGER_MODE"; 115 116 /** 117 * Broadcast intent action indicating that the vibrate setting has 118 * changed. Includes the vibrate type and its new setting. 119 * 120 * @see #EXTRA_VIBRATE_TYPE 121 * @see #EXTRA_VIBRATE_SETTING 122 * @deprecated Applications should maintain their own vibrate policy based on 123 * current ringer mode and listen to {@link #RINGER_MODE_CHANGED_ACTION} instead. 124 */ 125 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 126 public static final String VIBRATE_SETTING_CHANGED_ACTION = 127 "android.media.VIBRATE_SETTING_CHANGED"; 128 129 /** 130 * @hide Broadcast intent when the volume for a particular stream type changes. 131 * Includes the stream, the new volume and previous volumes. 132 * Notes: 133 * - for internal platform use only, do not make public, 134 * - never used for "remote" volume changes 135 * 136 * @see #EXTRA_VOLUME_STREAM_TYPE 137 * @see #EXTRA_VOLUME_STREAM_VALUE 138 * @see #EXTRA_PREV_VOLUME_STREAM_VALUE 139 */ 140 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 141 public static final String VOLUME_CHANGED_ACTION = "android.media.VOLUME_CHANGED_ACTION"; 142 143 /** 144 * @hide Broadcast intent when the devices for a particular stream type changes. 145 * Includes the stream, the new devices and previous devices. 146 * Notes: 147 * - for internal platform use only, do not make public, 148 * - never used for "remote" volume changes 149 * 150 * @see #EXTRA_VOLUME_STREAM_TYPE 151 * @see #EXTRA_VOLUME_STREAM_DEVICES 152 * @see #EXTRA_PREV_VOLUME_STREAM_DEVICES 153 * @see #getDevicesForStream 154 */ 155 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 156 public static final String STREAM_DEVICES_CHANGED_ACTION = 157 "android.media.STREAM_DEVICES_CHANGED_ACTION"; 158 159 /** 160 * @hide Broadcast intent when a stream mute state changes. 161 * Includes the stream that changed and the new mute state 162 * 163 * @see #EXTRA_VOLUME_STREAM_TYPE 164 * @see #EXTRA_STREAM_VOLUME_MUTED 165 */ 166 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 167 public static final String STREAM_MUTE_CHANGED_ACTION = 168 "android.media.STREAM_MUTE_CHANGED_ACTION"; 169 170 /** 171 * @hide Broadcast intent when the master mute state changes. 172 * Includes the the new volume 173 * 174 * @see #EXTRA_MASTER_VOLUME_MUTED 175 */ 176 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 177 public static final String MASTER_MUTE_CHANGED_ACTION = 178 "android.media.MASTER_MUTE_CHANGED_ACTION"; 179 180 /** 181 * The new vibrate setting for a particular type. 182 * 183 * @see #VIBRATE_SETTING_CHANGED_ACTION 184 * @see #EXTRA_VIBRATE_TYPE 185 * @see #VIBRATE_SETTING_ON 186 * @see #VIBRATE_SETTING_OFF 187 * @see #VIBRATE_SETTING_ONLY_SILENT 188 * @deprecated Applications should maintain their own vibrate policy based on 189 * current ringer mode and listen to {@link #RINGER_MODE_CHANGED_ACTION} instead. 190 */ 191 public static final String EXTRA_VIBRATE_SETTING = "android.media.EXTRA_VIBRATE_SETTING"; 192 193 /** 194 * The vibrate type whose setting has changed. 195 * 196 * @see #VIBRATE_SETTING_CHANGED_ACTION 197 * @see #VIBRATE_TYPE_NOTIFICATION 198 * @see #VIBRATE_TYPE_RINGER 199 * @deprecated Applications should maintain their own vibrate policy based on 200 * current ringer mode and listen to {@link #RINGER_MODE_CHANGED_ACTION} instead. 201 */ 202 public static final String EXTRA_VIBRATE_TYPE = "android.media.EXTRA_VIBRATE_TYPE"; 203 204 /** 205 * @hide The stream type for the volume changed intent. 206 */ 207 public static final String EXTRA_VOLUME_STREAM_TYPE = "android.media.EXTRA_VOLUME_STREAM_TYPE"; 208 209 /** 210 * @hide 211 * The stream type alias for the volume changed intent. 212 * For instance the intent may indicate a change of the {@link #STREAM_NOTIFICATION} stream 213 * type (as indicated by the {@link #EXTRA_VOLUME_STREAM_TYPE} extra), but this is also 214 * reflected by a change of the volume of its alias, {@link #STREAM_RING} on some devices, 215 * {@link #STREAM_MUSIC} on others (e.g. a television). 216 */ 217 public static final String EXTRA_VOLUME_STREAM_TYPE_ALIAS = 218 "android.media.EXTRA_VOLUME_STREAM_TYPE_ALIAS"; 219 220 /** 221 * @hide The volume associated with the stream for the volume changed intent. 222 */ 223 public static final String EXTRA_VOLUME_STREAM_VALUE = 224 "android.media.EXTRA_VOLUME_STREAM_VALUE"; 225 226 /** 227 * @hide The previous volume associated with the stream for the volume changed intent. 228 */ 229 public static final String EXTRA_PREV_VOLUME_STREAM_VALUE = 230 "android.media.EXTRA_PREV_VOLUME_STREAM_VALUE"; 231 232 /** 233 * @hide The devices associated with the stream for the stream devices changed intent. 234 */ 235 public static final String EXTRA_VOLUME_STREAM_DEVICES = 236 "android.media.EXTRA_VOLUME_STREAM_DEVICES"; 237 238 /** 239 * @hide The previous devices associated with the stream for the stream devices changed intent. 240 */ 241 public static final String EXTRA_PREV_VOLUME_STREAM_DEVICES = 242 "android.media.EXTRA_PREV_VOLUME_STREAM_DEVICES"; 243 244 /** 245 * @hide The new master volume mute state for the master mute changed intent. 246 * Value is boolean 247 */ 248 public static final String EXTRA_MASTER_VOLUME_MUTED = 249 "android.media.EXTRA_MASTER_VOLUME_MUTED"; 250 251 /** 252 * @hide The new stream volume mute state for the stream mute changed intent. 253 * Value is boolean 254 */ 255 public static final String EXTRA_STREAM_VOLUME_MUTED = 256 "android.media.EXTRA_STREAM_VOLUME_MUTED"; 257 258 /** 259 * Broadcast Action: Wired Headset plugged in or unplugged. 260 * 261 * You <em>cannot</em> receive this through components declared 262 * in manifests, only by explicitly registering for it with 263 * {@link Context#registerReceiver(BroadcastReceiver, IntentFilter) 264 * Context.registerReceiver()}. 265 * 266 * <p>The intent will have the following extra values: 267 * <ul> 268 * <li><em>state</em> - 0 for unplugged, 1 for plugged. </li> 269 * <li><em>name</em> - Headset type, human readable string </li> 270 * <li><em>microphone</em> - 1 if headset has a microphone, 0 otherwise </li> 271 * </ul> 272 * </ul> 273 */ 274 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 275 public static final String ACTION_HEADSET_PLUG = 276 "android.intent.action.HEADSET_PLUG"; 277 278 /** 279 * Broadcast Action: A sticky broadcast indicating an HDMI cable was plugged or unplugged. 280 * 281 * The intent will have the following extra values: {@link #EXTRA_AUDIO_PLUG_STATE}, 282 * {@link #EXTRA_MAX_CHANNEL_COUNT}, {@link #EXTRA_ENCODINGS}. 283 * <p>It can only be received by explicitly registering for it with 284 * {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)}. 285 */ 286 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 287 public static final String ACTION_HDMI_AUDIO_PLUG = 288 "android.media.action.HDMI_AUDIO_PLUG"; 289 290 /** 291 * Extra used in {@link #ACTION_HDMI_AUDIO_PLUG} to communicate whether HDMI is plugged in 292 * or unplugged. 293 * An integer value of 1 indicates a plugged-in state, 0 is unplugged. 294 */ 295 public static final String EXTRA_AUDIO_PLUG_STATE = "android.media.extra.AUDIO_PLUG_STATE"; 296 297 /** 298 * Extra used in {@link #ACTION_HDMI_AUDIO_PLUG} to define the maximum number of channels 299 * supported by the HDMI device. 300 * The corresponding integer value is only available when the device is plugged in (as expressed 301 * by {@link #EXTRA_AUDIO_PLUG_STATE}). 302 */ 303 public static final String EXTRA_MAX_CHANNEL_COUNT = "android.media.extra.MAX_CHANNEL_COUNT"; 304 305 /** 306 * Extra used in {@link #ACTION_HDMI_AUDIO_PLUG} to define the audio encodings supported by 307 * the connected HDMI device. 308 * The corresponding array of encoding values is only available when the device is plugged in 309 * (as expressed by {@link #EXTRA_AUDIO_PLUG_STATE}). Encoding values are defined in 310 * {@link AudioFormat} (for instance see {@link AudioFormat#ENCODING_PCM_16BIT}). Use 311 * {@link android.content.Intent#getIntArrayExtra(String)} to retrieve the encoding values. 312 */ 313 public static final String EXTRA_ENCODINGS = "android.media.extra.ENCODINGS"; 314 315 /** The audio stream for phone calls */ 316 public static final int STREAM_VOICE_CALL = AudioSystem.STREAM_VOICE_CALL; 317 /** The audio stream for system sounds */ 318 public static final int STREAM_SYSTEM = AudioSystem.STREAM_SYSTEM; 319 /** The audio stream for the phone ring */ 320 public static final int STREAM_RING = AudioSystem.STREAM_RING; 321 /** The audio stream for music playback */ 322 public static final int STREAM_MUSIC = AudioSystem.STREAM_MUSIC; 323 /** The audio stream for alarms */ 324 public static final int STREAM_ALARM = AudioSystem.STREAM_ALARM; 325 /** The audio stream for notifications */ 326 public static final int STREAM_NOTIFICATION = AudioSystem.STREAM_NOTIFICATION; 327 /** @hide The audio stream for phone calls when connected to bluetooth */ 328 public static final int STREAM_BLUETOOTH_SCO = AudioSystem.STREAM_BLUETOOTH_SCO; 329 /** @hide The audio stream for enforced system sounds in certain countries (e.g camera in Japan) */ 330 public static final int STREAM_SYSTEM_ENFORCED = AudioSystem.STREAM_SYSTEM_ENFORCED; 331 /** The audio stream for DTMF Tones */ 332 public static final int STREAM_DTMF = AudioSystem.STREAM_DTMF; 333 /** @hide The audio stream for text to speech (TTS) */ 334 public static final int STREAM_TTS = AudioSystem.STREAM_TTS; 335 /** Number of audio streams */ 336 /** 337 * @deprecated Use AudioSystem.getNumStreamTypes() instead 338 */ 339 @Deprecated public static final int NUM_STREAMS = AudioSystem.NUM_STREAMS; 340 341 /** 342 * Increase the ringer volume. 343 * 344 * @see #adjustVolume(int, int) 345 * @see #adjustStreamVolume(int, int, int) 346 */ 347 public static final int ADJUST_RAISE = 1; 348 349 /** 350 * Decrease the ringer volume. 351 * 352 * @see #adjustVolume(int, int) 353 * @see #adjustStreamVolume(int, int, int) 354 */ 355 public static final int ADJUST_LOWER = -1; 356 357 /** 358 * Maintain the previous ringer volume. This may be useful when needing to 359 * show the volume toast without actually modifying the volume. 360 * 361 * @see #adjustVolume(int, int) 362 * @see #adjustStreamVolume(int, int, int) 363 */ 364 public static final int ADJUST_SAME = 0; 365 366 /** 367 * Mute the volume. Has no effect if the stream is already muted. 368 * 369 * @see #adjustVolume(int, int) 370 * @see #adjustStreamVolume(int, int, int) 371 */ 372 public static final int ADJUST_MUTE = -100; 373 374 /** 375 * Unmute the volume. Has no effect if the stream is not muted. 376 * 377 * @see #adjustVolume(int, int) 378 * @see #adjustStreamVolume(int, int, int) 379 */ 380 public static final int ADJUST_UNMUTE = 100; 381 382 /** 383 * Toggle the mute state. If muted the stream will be unmuted. If not muted 384 * the stream will be muted. 385 * 386 * @see #adjustVolume(int, int) 387 * @see #adjustStreamVolume(int, int, int) 388 */ 389 public static final int ADJUST_TOGGLE_MUTE = 101; 390 391 // Flags should be powers of 2! 392 393 /** 394 * Show a toast containing the current volume. 395 * 396 * @see #adjustStreamVolume(int, int, int) 397 * @see #adjustVolume(int, int) 398 * @see #setStreamVolume(int, int, int) 399 * @see #setRingerMode(int) 400 */ 401 public static final int FLAG_SHOW_UI = 1 << 0; 402 403 /** 404 * Whether to include ringer modes as possible options when changing volume. 405 * For example, if true and volume level is 0 and the volume is adjusted 406 * with {@link #ADJUST_LOWER}, then the ringer mode may switch the silent or 407 * vibrate mode. 408 * <p> 409 * By default this is on for the ring stream. If this flag is included, 410 * this behavior will be present regardless of the stream type being 411 * affected by the ringer mode. 412 * 413 * @see #adjustVolume(int, int) 414 * @see #adjustStreamVolume(int, int, int) 415 */ 416 public static final int FLAG_ALLOW_RINGER_MODES = 1 << 1; 417 418 /** 419 * Whether to play a sound when changing the volume. 420 * <p> 421 * If this is given to {@link #adjustVolume(int, int)} or 422 * {@link #adjustSuggestedStreamVolume(int, int, int)}, it may be ignored 423 * in some cases (for example, the decided stream type is not 424 * {@link AudioManager#STREAM_RING}, or the volume is being adjusted 425 * downward). 426 * 427 * @see #adjustStreamVolume(int, int, int) 428 * @see #adjustVolume(int, int) 429 * @see #setStreamVolume(int, int, int) 430 */ 431 public static final int FLAG_PLAY_SOUND = 1 << 2; 432 433 /** 434 * Removes any sounds/vibrate that may be in the queue, or are playing (related to 435 * changing volume). 436 */ 437 public static final int FLAG_REMOVE_SOUND_AND_VIBRATE = 1 << 3; 438 439 /** 440 * Whether to vibrate if going into the vibrate ringer mode. 441 */ 442 public static final int FLAG_VIBRATE = 1 << 4; 443 444 /** 445 * Indicates to VolumePanel that the volume slider should be disabled as user 446 * cannot change the stream volume 447 * @hide 448 */ 449 public static final int FLAG_FIXED_VOLUME = 1 << 5; 450 451 /** 452 * Indicates the volume set/adjust call is for Bluetooth absolute volume 453 * @hide 454 */ 455 public static final int FLAG_BLUETOOTH_ABS_VOLUME = 1 << 6; 456 457 /** 458 * Adjusting the volume was prevented due to silent mode, display a hint in the UI. 459 * @hide 460 */ 461 public static final int FLAG_SHOW_SILENT_HINT = 1 << 7; 462 463 /** 464 * Indicates the volume call is for Hdmi Cec system audio volume 465 * @hide 466 */ 467 public static final int FLAG_HDMI_SYSTEM_AUDIO_VOLUME = 1 << 8; 468 469 /** 470 * Indicates that this should only be handled if media is actively playing. 471 * @hide 472 */ 473 public static final int FLAG_ACTIVE_MEDIA_ONLY = 1 << 9; 474 475 /** 476 * Like FLAG_SHOW_UI, but only dialog warnings and confirmations, no sliders. 477 * @hide 478 */ 479 public static final int FLAG_SHOW_UI_WARNINGS = 1 << 10; 480 481 /** 482 * Adjusting the volume down from vibrated was prevented, display a hint in the UI. 483 * @hide 484 */ 485 public static final int FLAG_SHOW_VIBRATE_HINT = 1 << 11; 486 487 /** 488 * Adjusting the volume due to a hardware key press. 489 * @hide 490 */ 491 public static final int FLAG_FROM_KEY = 1 << 12; 492 493 private static final String[] FLAG_NAMES = { 494 "FLAG_SHOW_UI", 495 "FLAG_ALLOW_RINGER_MODES", 496 "FLAG_PLAY_SOUND", 497 "FLAG_REMOVE_SOUND_AND_VIBRATE", 498 "FLAG_VIBRATE", 499 "FLAG_FIXED_VOLUME", 500 "FLAG_BLUETOOTH_ABS_VOLUME", 501 "FLAG_SHOW_SILENT_HINT", 502 "FLAG_HDMI_SYSTEM_AUDIO_VOLUME", 503 "FLAG_ACTIVE_MEDIA_ONLY", 504 "FLAG_SHOW_UI_WARNINGS", 505 "FLAG_SHOW_VIBRATE_HINT", 506 "FLAG_FROM_KEY", 507 }; 508 509 /** @hide */ flagsToString(int flags)510 public static String flagsToString(int flags) { 511 final StringBuilder sb = new StringBuilder(); 512 for (int i = 0; i < FLAG_NAMES.length; i++) { 513 final int flag = 1 << i; 514 if ((flags & flag) != 0) { 515 if (sb.length() > 0) { 516 sb.append(','); 517 } 518 sb.append(FLAG_NAMES[i]); 519 flags &= ~flag; 520 } 521 } 522 if (flags != 0) { 523 if (sb.length() > 0) { 524 sb.append(','); 525 } 526 sb.append(flags); 527 } 528 return sb.toString(); 529 } 530 531 /** 532 * Ringer mode that will be silent and will not vibrate. (This overrides the 533 * vibrate setting.) 534 * 535 * @see #setRingerMode(int) 536 * @see #getRingerMode() 537 */ 538 public static final int RINGER_MODE_SILENT = 0; 539 540 /** 541 * Ringer mode that will be silent and will vibrate. (This will cause the 542 * phone ringer to always vibrate, but the notification vibrate to only 543 * vibrate if set.) 544 * 545 * @see #setRingerMode(int) 546 * @see #getRingerMode() 547 */ 548 public static final int RINGER_MODE_VIBRATE = 1; 549 550 /** 551 * Ringer mode that may be audible and may vibrate. It will be audible if 552 * the volume before changing out of this mode was audible. It will vibrate 553 * if the vibrate setting is on. 554 * 555 * @see #setRingerMode(int) 556 * @see #getRingerMode() 557 */ 558 public static final int RINGER_MODE_NORMAL = 2; 559 560 /** 561 * Maximum valid ringer mode value. Values must start from 0 and be contiguous. 562 * @hide 563 */ 564 public static final int RINGER_MODE_MAX = RINGER_MODE_NORMAL; 565 566 /** 567 * Vibrate type that corresponds to the ringer. 568 * 569 * @see #setVibrateSetting(int, int) 570 * @see #getVibrateSetting(int) 571 * @see #shouldVibrate(int) 572 * @deprecated Applications should maintain their own vibrate policy based on 573 * current ringer mode that can be queried via {@link #getRingerMode()}. 574 */ 575 public static final int VIBRATE_TYPE_RINGER = 0; 576 577 /** 578 * Vibrate type that corresponds to notifications. 579 * 580 * @see #setVibrateSetting(int, int) 581 * @see #getVibrateSetting(int) 582 * @see #shouldVibrate(int) 583 * @deprecated Applications should maintain their own vibrate policy based on 584 * current ringer mode that can be queried via {@link #getRingerMode()}. 585 */ 586 public static final int VIBRATE_TYPE_NOTIFICATION = 1; 587 588 /** 589 * Vibrate setting that suggests to never vibrate. 590 * 591 * @see #setVibrateSetting(int, int) 592 * @see #getVibrateSetting(int) 593 * @deprecated Applications should maintain their own vibrate policy based on 594 * current ringer mode that can be queried via {@link #getRingerMode()}. 595 */ 596 public static final int VIBRATE_SETTING_OFF = 0; 597 598 /** 599 * Vibrate setting that suggests to vibrate when possible. 600 * 601 * @see #setVibrateSetting(int, int) 602 * @see #getVibrateSetting(int) 603 * @deprecated Applications should maintain their own vibrate policy based on 604 * current ringer mode that can be queried via {@link #getRingerMode()}. 605 */ 606 public static final int VIBRATE_SETTING_ON = 1; 607 608 /** 609 * Vibrate setting that suggests to only vibrate when in the vibrate ringer 610 * mode. 611 * 612 * @see #setVibrateSetting(int, int) 613 * @see #getVibrateSetting(int) 614 * @deprecated Applications should maintain their own vibrate policy based on 615 * current ringer mode that can be queried via {@link #getRingerMode()}. 616 */ 617 public static final int VIBRATE_SETTING_ONLY_SILENT = 2; 618 619 /** 620 * Suggests using the default stream type. This may not be used in all 621 * places a stream type is needed. 622 */ 623 public static final int USE_DEFAULT_STREAM_TYPE = Integer.MIN_VALUE; 624 625 private static IAudioService sService; 626 627 /** 628 * @hide 629 */ AudioManager(Context context)630 public AudioManager(Context context) { 631 setContext(context); 632 mUseVolumeKeySounds = getContext().getResources().getBoolean( 633 com.android.internal.R.bool.config_useVolumeKeySounds); 634 mUseFixedVolume = getContext().getResources().getBoolean( 635 com.android.internal.R.bool.config_useFixedVolume); 636 } 637 getContext()638 private Context getContext() { 639 if (mApplicationContext == null) { 640 setContext(mOriginalContext); 641 } 642 if (mApplicationContext != null) { 643 return mApplicationContext; 644 } 645 return mOriginalContext; 646 } 647 setContext(Context context)648 private void setContext(Context context) { 649 mApplicationContext = context.getApplicationContext(); 650 if (mApplicationContext != null) { 651 mOriginalContext = null; 652 } else { 653 mOriginalContext = context; 654 } 655 } 656 getService()657 private static IAudioService getService() 658 { 659 if (sService != null) { 660 return sService; 661 } 662 IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE); 663 sService = IAudioService.Stub.asInterface(b); 664 return sService; 665 } 666 667 /** 668 * Sends a simulated key event for a media button. 669 * To simulate a key press, you must first send a KeyEvent built with a 670 * {@link KeyEvent#ACTION_DOWN} action, then another event with the {@link KeyEvent#ACTION_UP} 671 * action. 672 * <p>The key event will be sent to the current media key event consumer which registered with 673 * {@link AudioManager#registerMediaButtonEventReceiver(PendingIntent)}. 674 * @param keyEvent a {@link KeyEvent} instance whose key code is one of 675 * {@link KeyEvent#KEYCODE_MUTE}, 676 * {@link KeyEvent#KEYCODE_HEADSETHOOK}, 677 * {@link KeyEvent#KEYCODE_MEDIA_PLAY}, 678 * {@link KeyEvent#KEYCODE_MEDIA_PAUSE}, 679 * {@link KeyEvent#KEYCODE_MEDIA_PLAY_PAUSE}, 680 * {@link KeyEvent#KEYCODE_MEDIA_STOP}, 681 * {@link KeyEvent#KEYCODE_MEDIA_NEXT}, 682 * {@link KeyEvent#KEYCODE_MEDIA_PREVIOUS}, 683 * {@link KeyEvent#KEYCODE_MEDIA_REWIND}, 684 * {@link KeyEvent#KEYCODE_MEDIA_RECORD}, 685 * {@link KeyEvent#KEYCODE_MEDIA_FAST_FORWARD}, 686 * {@link KeyEvent#KEYCODE_MEDIA_CLOSE}, 687 * {@link KeyEvent#KEYCODE_MEDIA_EJECT}, 688 * or {@link KeyEvent#KEYCODE_MEDIA_AUDIO_TRACK}. 689 */ dispatchMediaKeyEvent(KeyEvent keyEvent)690 public void dispatchMediaKeyEvent(KeyEvent keyEvent) { 691 MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(getContext()); 692 helper.sendMediaButtonEvent(keyEvent, false); 693 } 694 695 /** 696 * @hide 697 */ preDispatchKeyEvent(KeyEvent event, int stream)698 public void preDispatchKeyEvent(KeyEvent event, int stream) { 699 /* 700 * If the user hits another key within the play sound delay, then 701 * cancel the sound 702 */ 703 int keyCode = event.getKeyCode(); 704 if (keyCode != KeyEvent.KEYCODE_VOLUME_DOWN && keyCode != KeyEvent.KEYCODE_VOLUME_UP 705 && keyCode != KeyEvent.KEYCODE_VOLUME_MUTE 706 && mVolumeKeyUpTime + AudioSystem.PLAY_SOUND_DELAY > SystemClock.uptimeMillis()) { 707 /* 708 * The user has hit another key during the delay (e.g., 300ms) 709 * since the last volume key up, so cancel any sounds. 710 */ 711 adjustSuggestedStreamVolume(ADJUST_SAME, 712 stream, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE); 713 } 714 } 715 716 /** 717 * @hide 718 */ handleKeyDown(KeyEvent event, int stream)719 public void handleKeyDown(KeyEvent event, int stream) { 720 int keyCode = event.getKeyCode(); 721 switch (keyCode) { 722 case KeyEvent.KEYCODE_VOLUME_UP: 723 case KeyEvent.KEYCODE_VOLUME_DOWN: 724 /* 725 * Adjust the volume in on key down since it is more 726 * responsive to the user. 727 */ 728 adjustSuggestedStreamVolume( 729 keyCode == KeyEvent.KEYCODE_VOLUME_UP 730 ? ADJUST_RAISE 731 : ADJUST_LOWER, 732 stream, 733 FLAG_SHOW_UI | FLAG_VIBRATE); 734 break; 735 case KeyEvent.KEYCODE_VOLUME_MUTE: 736 if (event.getRepeatCount() == 0) { 737 MediaSessionLegacyHelper.getHelper(getContext()) 738 .sendVolumeKeyEvent(event, false); 739 } 740 break; 741 } 742 } 743 744 /** 745 * @hide 746 */ handleKeyUp(KeyEvent event, int stream)747 public void handleKeyUp(KeyEvent event, int stream) { 748 int keyCode = event.getKeyCode(); 749 switch (keyCode) { 750 case KeyEvent.KEYCODE_VOLUME_UP: 751 case KeyEvent.KEYCODE_VOLUME_DOWN: 752 /* 753 * Play a sound. This is done on key up since we don't want the 754 * sound to play when a user holds down volume down to mute. 755 */ 756 if (mUseVolumeKeySounds) { 757 adjustSuggestedStreamVolume( 758 ADJUST_SAME, 759 stream, 760 FLAG_PLAY_SOUND); 761 } 762 mVolumeKeyUpTime = SystemClock.uptimeMillis(); 763 break; 764 case KeyEvent.KEYCODE_VOLUME_MUTE: 765 MediaSessionLegacyHelper.getHelper(getContext()) 766 .sendVolumeKeyEvent(event, false); 767 break; 768 } 769 } 770 771 /** 772 * Indicates if the device implements a fixed volume policy. 773 * <p>Some devices may not have volume control and may operate at a fixed volume, 774 * and may not enable muting or changing the volume of audio streams. 775 * This method will return true on such devices. 776 * <p>The following APIs have no effect when volume is fixed: 777 * <ul> 778 * <li> {@link #adjustVolume(int, int)} 779 * <li> {@link #adjustSuggestedStreamVolume(int, int, int)} 780 * <li> {@link #adjustStreamVolume(int, int, int)} 781 * <li> {@link #setStreamVolume(int, int, int)} 782 * <li> {@link #setRingerMode(int)} 783 * <li> {@link #setStreamSolo(int, boolean)} 784 * <li> {@link #setStreamMute(int, boolean)} 785 * </ul> 786 */ isVolumeFixed()787 public boolean isVolumeFixed() { 788 return mUseFixedVolume; 789 } 790 791 /** 792 * Adjusts the volume of a particular stream by one step in a direction. 793 * <p> 794 * This method should only be used by applications that replace the platform-wide 795 * management of audio settings or the main telephony application. 796 * 797 * @param streamType The stream type to adjust. One of {@link #STREAM_VOICE_CALL}, 798 * {@link #STREAM_SYSTEM}, {@link #STREAM_RING}, {@link #STREAM_MUSIC} or 799 * {@link #STREAM_ALARM} 800 * @param direction The direction to adjust the volume. One of 801 * {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, or 802 * {@link #ADJUST_SAME}. 803 * @param flags One or more flags. 804 * @see #adjustVolume(int, int) 805 * @see #setStreamVolume(int, int, int) 806 */ adjustStreamVolume(int streamType, int direction, int flags)807 public void adjustStreamVolume(int streamType, int direction, int flags) { 808 IAudioService service = getService(); 809 try { 810 service.adjustStreamVolume(streamType, direction, flags, 811 getContext().getOpPackageName()); 812 } catch (RemoteException e) { 813 throw e.rethrowFromSystemServer(); 814 } 815 } 816 817 /** 818 * Adjusts the volume of the most relevant stream. For example, if a call is 819 * active, it will have the highest priority regardless of if the in-call 820 * screen is showing. Another example, if music is playing in the background 821 * and a call is not active, the music stream will be adjusted. 822 * <p> 823 * This method should only be used by applications that replace the 824 * platform-wide management of audio settings or the main telephony 825 * application. 826 * <p> 827 * This method has no effect if the device implements a fixed volume policy 828 * as indicated by {@link #isVolumeFixed()}. 829 * 830 * @param direction The direction to adjust the volume. One of 831 * {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, 832 * {@link #ADJUST_SAME}, {@link #ADJUST_MUTE}, 833 * {@link #ADJUST_UNMUTE}, or {@link #ADJUST_TOGGLE_MUTE}. 834 * @param flags One or more flags. 835 * @see #adjustSuggestedStreamVolume(int, int, int) 836 * @see #adjustStreamVolume(int, int, int) 837 * @see #setStreamVolume(int, int, int) 838 * @see #isVolumeFixed() 839 */ adjustVolume(int direction, int flags)840 public void adjustVolume(int direction, int flags) { 841 MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(getContext()); 842 helper.sendAdjustVolumeBy(USE_DEFAULT_STREAM_TYPE, direction, flags); 843 } 844 845 /** 846 * Adjusts the volume of the most relevant stream, or the given fallback 847 * stream. 848 * <p> 849 * This method should only be used by applications that replace the 850 * platform-wide management of audio settings or the main telephony 851 * application. 852 * <p> 853 * This method has no effect if the device implements a fixed volume policy 854 * as indicated by {@link #isVolumeFixed()}. 855 * 856 * @param direction The direction to adjust the volume. One of 857 * {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, 858 * {@link #ADJUST_SAME}, {@link #ADJUST_MUTE}, 859 * {@link #ADJUST_UNMUTE}, or {@link #ADJUST_TOGGLE_MUTE}. 860 * @param suggestedStreamType The stream type that will be used if there 861 * isn't a relevant stream. {@link #USE_DEFAULT_STREAM_TYPE} is 862 * valid here. 863 * @param flags One or more flags. 864 * @see #adjustVolume(int, int) 865 * @see #adjustStreamVolume(int, int, int) 866 * @see #setStreamVolume(int, int, int) 867 * @see #isVolumeFixed() 868 */ adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags)869 public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags) { 870 MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(getContext()); 871 helper.sendAdjustVolumeBy(suggestedStreamType, direction, flags); 872 } 873 874 /** @hide */ setMasterMute(boolean mute, int flags)875 public void setMasterMute(boolean mute, int flags) { 876 IAudioService service = getService(); 877 try { 878 service.setMasterMute(mute, flags, getContext().getOpPackageName(), 879 UserHandle.getCallingUserId()); 880 } catch (RemoteException e) { 881 throw e.rethrowFromSystemServer(); 882 } 883 } 884 885 /** 886 * Returns the current ringtone mode. 887 * 888 * @return The current ringtone mode, one of {@link #RINGER_MODE_NORMAL}, 889 * {@link #RINGER_MODE_SILENT}, or {@link #RINGER_MODE_VIBRATE}. 890 * @see #setRingerMode(int) 891 */ getRingerMode()892 public int getRingerMode() { 893 IAudioService service = getService(); 894 try { 895 return service.getRingerModeExternal(); 896 } catch (RemoteException e) { 897 throw e.rethrowFromSystemServer(); 898 } 899 } 900 901 /** 902 * Checks valid ringer mode values. 903 * 904 * @return true if the ringer mode indicated is valid, false otherwise. 905 * 906 * @see #setRingerMode(int) 907 * @hide 908 */ isValidRingerMode(int ringerMode)909 public static boolean isValidRingerMode(int ringerMode) { 910 if (ringerMode < 0 || ringerMode > RINGER_MODE_MAX) { 911 return false; 912 } 913 IAudioService service = getService(); 914 try { 915 return service.isValidRingerMode(ringerMode); 916 } catch (RemoteException e) { 917 throw e.rethrowFromSystemServer(); 918 } 919 } 920 921 /** 922 * Returns the maximum volume index for a particular stream. 923 * 924 * @param streamType The stream type whose maximum volume index is returned. 925 * @return The maximum valid volume index for the stream. 926 * @see #getStreamVolume(int) 927 */ getStreamMaxVolume(int streamType)928 public int getStreamMaxVolume(int streamType) { 929 IAudioService service = getService(); 930 try { 931 return service.getStreamMaxVolume(streamType); 932 } catch (RemoteException e) { 933 throw e.rethrowFromSystemServer(); 934 } 935 } 936 937 /** 938 * Returns the minimum volume index for a particular stream. 939 * 940 * @param streamType The stream type whose minimum volume index is returned. 941 * @return The minimum valid volume index for the stream. 942 * @see #getStreamVolume(int) 943 * @hide 944 */ getStreamMinVolume(int streamType)945 public int getStreamMinVolume(int streamType) { 946 IAudioService service = getService(); 947 try { 948 return service.getStreamMinVolume(streamType); 949 } catch (RemoteException e) { 950 throw e.rethrowFromSystemServer(); 951 } 952 } 953 954 /** 955 * Returns the current volume index for a particular stream. 956 * 957 * @param streamType The stream type whose volume index is returned. 958 * @return The current volume index for the stream. 959 * @see #getStreamMaxVolume(int) 960 * @see #setStreamVolume(int, int, int) 961 */ getStreamVolume(int streamType)962 public int getStreamVolume(int streamType) { 963 IAudioService service = getService(); 964 try { 965 return service.getStreamVolume(streamType); 966 } catch (RemoteException e) { 967 throw e.rethrowFromSystemServer(); 968 } 969 } 970 971 /** 972 * Get last audible volume before stream was muted. 973 * 974 * @hide 975 */ getLastAudibleStreamVolume(int streamType)976 public int getLastAudibleStreamVolume(int streamType) { 977 IAudioService service = getService(); 978 try { 979 return service.getLastAudibleStreamVolume(streamType); 980 } catch (RemoteException e) { 981 throw e.rethrowFromSystemServer(); 982 } 983 } 984 985 /** 986 * Get the stream type whose volume is driving the UI sounds volume. 987 * UI sounds are screen lock/unlock, camera shutter, key clicks... 988 * It is assumed that this stream type is also tied to ringer mode changes. 989 * @hide 990 */ getUiSoundsStreamType()991 public int getUiSoundsStreamType() { 992 IAudioService service = getService(); 993 try { 994 return service.getUiSoundsStreamType(); 995 } catch (RemoteException e) { 996 throw e.rethrowFromSystemServer(); 997 } 998 } 999 1000 /** 1001 * Sets the ringer mode. 1002 * <p> 1003 * Silent mode will mute the volume and will not vibrate. Vibrate mode will 1004 * mute the volume and vibrate. Normal mode will be audible and may vibrate 1005 * according to user settings. 1006 * <p>This method has no effect if the device implements a fixed volume policy 1007 * as indicated by {@link #isVolumeFixed()}. 1008 * * <p>From N onward, ringer mode adjustments that would toggle Do Not Disturb are not allowed 1009 * unless the app has been granted Do Not Disturb Access. 1010 * See {@link NotificationManager#isNotificationPolicyAccessGranted()}. 1011 * @param ringerMode The ringer mode, one of {@link #RINGER_MODE_NORMAL}, 1012 * {@link #RINGER_MODE_SILENT}, or {@link #RINGER_MODE_VIBRATE}. 1013 * @see #getRingerMode() 1014 * @see #isVolumeFixed() 1015 */ setRingerMode(int ringerMode)1016 public void setRingerMode(int ringerMode) { 1017 if (!isValidRingerMode(ringerMode)) { 1018 return; 1019 } 1020 IAudioService service = getService(); 1021 try { 1022 service.setRingerModeExternal(ringerMode, getContext().getOpPackageName()); 1023 } catch (RemoteException e) { 1024 throw e.rethrowFromSystemServer(); 1025 } 1026 } 1027 1028 /** 1029 * Sets the volume index for a particular stream. 1030 * <p>This method has no effect if the device implements a fixed volume policy 1031 * as indicated by {@link #isVolumeFixed()}. 1032 * <p>From N onward, volume adjustments that would toggle Do Not Disturb are not allowed unless 1033 * the app has been granted Do Not Disturb Access. 1034 * See {@link NotificationManager#isNotificationPolicyAccessGranted()}. 1035 * @param streamType The stream whose volume index should be set. 1036 * @param index The volume index to set. See 1037 * {@link #getStreamMaxVolume(int)} for the largest valid value. 1038 * @param flags One or more flags. 1039 * @see #getStreamMaxVolume(int) 1040 * @see #getStreamVolume(int) 1041 * @see #isVolumeFixed() 1042 */ setStreamVolume(int streamType, int index, int flags)1043 public void setStreamVolume(int streamType, int index, int flags) { 1044 IAudioService service = getService(); 1045 try { 1046 service.setStreamVolume(streamType, index, flags, getContext().getOpPackageName()); 1047 } catch (RemoteException e) { 1048 throw e.rethrowFromSystemServer(); 1049 } 1050 } 1051 1052 /** 1053 * Solo or unsolo a particular stream. 1054 * <p> 1055 * Do not use. This method has been deprecated and is now a no-op. 1056 * {@link #requestAudioFocus} should be used for exclusive audio playback. 1057 * 1058 * @param streamType The stream to be soloed/unsoloed. 1059 * @param state The required solo state: true for solo ON, false for solo 1060 * OFF 1061 * @see #isVolumeFixed() 1062 * @deprecated Do not use. If you need exclusive audio playback use 1063 * {@link #requestAudioFocus}. 1064 */ 1065 @Deprecated setStreamSolo(int streamType, boolean state)1066 public void setStreamSolo(int streamType, boolean state) { 1067 Log.w(TAG, "setStreamSolo has been deprecated. Do not use."); 1068 } 1069 1070 /** 1071 * Mute or unmute an audio stream. 1072 * <p> 1073 * This method should only be used by applications that replace the 1074 * platform-wide management of audio settings or the main telephony 1075 * application. 1076 * <p> 1077 * This method has no effect if the device implements a fixed volume policy 1078 * as indicated by {@link #isVolumeFixed()}. 1079 * <p> 1080 * This method was deprecated in API level 22. Prior to API level 22 this 1081 * method had significantly different behavior and should be used carefully. 1082 * The following applies only to pre-22 platforms: 1083 * <ul> 1084 * <li>The mute command is protected against client process death: if a 1085 * process with an active mute request on a stream dies, this stream will be 1086 * unmuted automatically.</li> 1087 * <li>The mute requests for a given stream are cumulative: the AudioManager 1088 * can receive several mute requests from one or more clients and the stream 1089 * will be unmuted only when the same number of unmute requests are 1090 * received.</li> 1091 * <li>For a better user experience, applications MUST unmute a muted stream 1092 * in onPause() and mute is again in onResume() if appropriate.</li> 1093 * </ul> 1094 * 1095 * @param streamType The stream to be muted/unmuted. 1096 * @param state The required mute state: true for mute ON, false for mute 1097 * OFF 1098 * @see #isVolumeFixed() 1099 * @deprecated Use {@link #adjustStreamVolume(int, int, int)} with 1100 * {@link #ADJUST_MUTE} or {@link #ADJUST_UNMUTE} instead. 1101 */ 1102 @Deprecated setStreamMute(int streamType, boolean state)1103 public void setStreamMute(int streamType, boolean state) { 1104 Log.w(TAG, "setStreamMute is deprecated. adjustStreamVolume should be used instead."); 1105 int direction = state ? ADJUST_MUTE : ADJUST_UNMUTE; 1106 if (streamType == AudioManager.USE_DEFAULT_STREAM_TYPE) { 1107 adjustSuggestedStreamVolume(direction, streamType, 0); 1108 } else { 1109 adjustStreamVolume(streamType, direction, 0); 1110 } 1111 } 1112 1113 /** 1114 * Returns the current mute state for a particular stream. 1115 * 1116 * @param streamType The stream to get mute state for. 1117 * @return The mute state for the given stream. 1118 * @see #adjustStreamVolume(int, int, int) 1119 */ isStreamMute(int streamType)1120 public boolean isStreamMute(int streamType) { 1121 IAudioService service = getService(); 1122 try { 1123 return service.isStreamMute(streamType); 1124 } catch (RemoteException e) { 1125 throw e.rethrowFromSystemServer(); 1126 } 1127 } 1128 1129 /** 1130 * get master mute state. 1131 * 1132 * @hide 1133 */ isMasterMute()1134 public boolean isMasterMute() { 1135 IAudioService service = getService(); 1136 try { 1137 return service.isMasterMute(); 1138 } catch (RemoteException e) { 1139 throw e.rethrowFromSystemServer(); 1140 } 1141 } 1142 1143 /** 1144 * forces the stream controlled by hard volume keys 1145 * specifying streamType == -1 releases control to the 1146 * logic. 1147 * 1148 * @hide 1149 */ forceVolumeControlStream(int streamType)1150 public void forceVolumeControlStream(int streamType) { 1151 IAudioService service = getService(); 1152 try { 1153 service.forceVolumeControlStream(streamType, mICallBack); 1154 } catch (RemoteException e) { 1155 throw e.rethrowFromSystemServer(); 1156 } 1157 } 1158 1159 /** 1160 * Returns whether a particular type should vibrate according to user 1161 * settings and the current ringer mode. 1162 * <p> 1163 * This shouldn't be needed by most clients that use notifications to 1164 * vibrate. The notification manager will not vibrate if the policy doesn't 1165 * allow it, so the client should always set a vibrate pattern and let the 1166 * notification manager control whether or not to actually vibrate. 1167 * 1168 * @param vibrateType The type of vibrate. One of 1169 * {@link #VIBRATE_TYPE_NOTIFICATION} or 1170 * {@link #VIBRATE_TYPE_RINGER}. 1171 * @return Whether the type should vibrate at the instant this method is 1172 * called. 1173 * @see #setVibrateSetting(int, int) 1174 * @see #getVibrateSetting(int) 1175 * @deprecated Applications should maintain their own vibrate policy based on 1176 * current ringer mode that can be queried via {@link #getRingerMode()}. 1177 */ shouldVibrate(int vibrateType)1178 public boolean shouldVibrate(int vibrateType) { 1179 IAudioService service = getService(); 1180 try { 1181 return service.shouldVibrate(vibrateType); 1182 } catch (RemoteException e) { 1183 throw e.rethrowFromSystemServer(); 1184 } 1185 } 1186 1187 /** 1188 * Returns whether the user's vibrate setting for a vibrate type. 1189 * <p> 1190 * This shouldn't be needed by most clients that want to vibrate, instead 1191 * see {@link #shouldVibrate(int)}. 1192 * 1193 * @param vibrateType The type of vibrate. One of 1194 * {@link #VIBRATE_TYPE_NOTIFICATION} or 1195 * {@link #VIBRATE_TYPE_RINGER}. 1196 * @return The vibrate setting, one of {@link #VIBRATE_SETTING_ON}, 1197 * {@link #VIBRATE_SETTING_OFF}, or 1198 * {@link #VIBRATE_SETTING_ONLY_SILENT}. 1199 * @see #setVibrateSetting(int, int) 1200 * @see #shouldVibrate(int) 1201 * @deprecated Applications should maintain their own vibrate policy based on 1202 * current ringer mode that can be queried via {@link #getRingerMode()}. 1203 */ getVibrateSetting(int vibrateType)1204 public int getVibrateSetting(int vibrateType) { 1205 IAudioService service = getService(); 1206 try { 1207 return service.getVibrateSetting(vibrateType); 1208 } catch (RemoteException e) { 1209 throw e.rethrowFromSystemServer(); 1210 } 1211 } 1212 1213 /** 1214 * Sets the setting for when the vibrate type should vibrate. 1215 * <p> 1216 * This method should only be used by applications that replace the platform-wide 1217 * management of audio settings or the main telephony application. 1218 * 1219 * @param vibrateType The type of vibrate. One of 1220 * {@link #VIBRATE_TYPE_NOTIFICATION} or 1221 * {@link #VIBRATE_TYPE_RINGER}. 1222 * @param vibrateSetting The vibrate setting, one of 1223 * {@link #VIBRATE_SETTING_ON}, 1224 * {@link #VIBRATE_SETTING_OFF}, or 1225 * {@link #VIBRATE_SETTING_ONLY_SILENT}. 1226 * @see #getVibrateSetting(int) 1227 * @see #shouldVibrate(int) 1228 * @deprecated Applications should maintain their own vibrate policy based on 1229 * current ringer mode that can be queried via {@link #getRingerMode()}. 1230 */ setVibrateSetting(int vibrateType, int vibrateSetting)1231 public void setVibrateSetting(int vibrateType, int vibrateSetting) { 1232 IAudioService service = getService(); 1233 try { 1234 service.setVibrateSetting(vibrateType, vibrateSetting); 1235 } catch (RemoteException e) { 1236 throw e.rethrowFromSystemServer(); 1237 } 1238 } 1239 1240 /** 1241 * Sets the speakerphone on or off. 1242 * <p> 1243 * This method should only be used by applications that replace the platform-wide 1244 * management of audio settings or the main telephony application. 1245 * 1246 * @param on set <var>true</var> to turn on speakerphone; 1247 * <var>false</var> to turn it off 1248 */ setSpeakerphoneOn(boolean on)1249 public void setSpeakerphoneOn(boolean on){ 1250 IAudioService service = getService(); 1251 try { 1252 service.setSpeakerphoneOn(on); 1253 } catch (RemoteException e) { 1254 throw e.rethrowFromSystemServer(); 1255 } 1256 } 1257 1258 /** 1259 * Checks whether the speakerphone is on or off. 1260 * 1261 * @return true if speakerphone is on, false if it's off 1262 */ isSpeakerphoneOn()1263 public boolean isSpeakerphoneOn() { 1264 IAudioService service = getService(); 1265 try { 1266 return service.isSpeakerphoneOn(); 1267 } catch (RemoteException e) { 1268 throw e.rethrowFromSystemServer(); 1269 } 1270 } 1271 1272 //==================================================================== 1273 // Bluetooth SCO control 1274 /** 1275 * Sticky broadcast intent action indicating that the bluetoooth SCO audio 1276 * connection state has changed. The intent contains on extra {@link #EXTRA_SCO_AUDIO_STATE} 1277 * indicating the new state which is either {@link #SCO_AUDIO_STATE_DISCONNECTED} 1278 * or {@link #SCO_AUDIO_STATE_CONNECTED} 1279 * 1280 * @see #startBluetoothSco() 1281 * @deprecated Use {@link #ACTION_SCO_AUDIO_STATE_UPDATED} instead 1282 */ 1283 @Deprecated 1284 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1285 public static final String ACTION_SCO_AUDIO_STATE_CHANGED = 1286 "android.media.SCO_AUDIO_STATE_CHANGED"; 1287 1288 /** 1289 * Sticky broadcast intent action indicating that the bluetoooth SCO audio 1290 * connection state has been updated. 1291 * <p>This intent has two extras: 1292 * <ul> 1293 * <li> {@link #EXTRA_SCO_AUDIO_STATE} - The new SCO audio state. </li> 1294 * <li> {@link #EXTRA_SCO_AUDIO_PREVIOUS_STATE}- The previous SCO audio state. </li> 1295 * </ul> 1296 * <p> EXTRA_SCO_AUDIO_STATE or EXTRA_SCO_AUDIO_PREVIOUS_STATE can be any of: 1297 * <ul> 1298 * <li> {@link #SCO_AUDIO_STATE_DISCONNECTED}, </li> 1299 * <li> {@link #SCO_AUDIO_STATE_CONNECTING} or </li> 1300 * <li> {@link #SCO_AUDIO_STATE_CONNECTED}, </li> 1301 * </ul> 1302 * @see #startBluetoothSco() 1303 */ 1304 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1305 public static final String ACTION_SCO_AUDIO_STATE_UPDATED = 1306 "android.media.ACTION_SCO_AUDIO_STATE_UPDATED"; 1307 1308 /** 1309 * Extra for intent {@link #ACTION_SCO_AUDIO_STATE_CHANGED} or 1310 * {@link #ACTION_SCO_AUDIO_STATE_UPDATED} containing the new bluetooth SCO connection state. 1311 */ 1312 public static final String EXTRA_SCO_AUDIO_STATE = 1313 "android.media.extra.SCO_AUDIO_STATE"; 1314 1315 /** 1316 * Extra for intent {@link #ACTION_SCO_AUDIO_STATE_UPDATED} containing the previous 1317 * bluetooth SCO connection state. 1318 */ 1319 public static final String EXTRA_SCO_AUDIO_PREVIOUS_STATE = 1320 "android.media.extra.SCO_AUDIO_PREVIOUS_STATE"; 1321 1322 /** 1323 * Value for extra EXTRA_SCO_AUDIO_STATE or EXTRA_SCO_AUDIO_PREVIOUS_STATE 1324 * indicating that the SCO audio channel is not established 1325 */ 1326 public static final int SCO_AUDIO_STATE_DISCONNECTED = 0; 1327 /** 1328 * Value for extra {@link #EXTRA_SCO_AUDIO_STATE} or {@link #EXTRA_SCO_AUDIO_PREVIOUS_STATE} 1329 * indicating that the SCO audio channel is established 1330 */ 1331 public static final int SCO_AUDIO_STATE_CONNECTED = 1; 1332 /** 1333 * Value for extra EXTRA_SCO_AUDIO_STATE or EXTRA_SCO_AUDIO_PREVIOUS_STATE 1334 * indicating that the SCO audio channel is being established 1335 */ 1336 public static final int SCO_AUDIO_STATE_CONNECTING = 2; 1337 /** 1338 * Value for extra EXTRA_SCO_AUDIO_STATE indicating that 1339 * there was an error trying to obtain the state 1340 */ 1341 public static final int SCO_AUDIO_STATE_ERROR = -1; 1342 1343 1344 /** 1345 * Indicates if current platform supports use of SCO for off call use cases. 1346 * Application wanted to use bluetooth SCO audio when the phone is not in call 1347 * must first call this method to make sure that the platform supports this 1348 * feature. 1349 * @return true if bluetooth SCO can be used for audio when not in call 1350 * false otherwise 1351 * @see #startBluetoothSco() 1352 */ isBluetoothScoAvailableOffCall()1353 public boolean isBluetoothScoAvailableOffCall() { 1354 return getContext().getResources().getBoolean( 1355 com.android.internal.R.bool.config_bluetooth_sco_off_call); 1356 } 1357 1358 /** 1359 * Start bluetooth SCO audio connection. 1360 * <p>Requires Permission: 1361 * {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}. 1362 * <p>This method can be used by applications wanting to send and received audio 1363 * to/from a bluetooth SCO headset while the phone is not in call. 1364 * <p>As the SCO connection establishment can take several seconds, 1365 * applications should not rely on the connection to be available when the method 1366 * returns but instead register to receive the intent {@link #ACTION_SCO_AUDIO_STATE_UPDATED} 1367 * and wait for the state to be {@link #SCO_AUDIO_STATE_CONNECTED}. 1368 * <p>As the ACTION_SCO_AUDIO_STATE_UPDATED intent is sticky, the application can check the SCO 1369 * audio state before calling startBluetoothSco() by reading the intent returned by the receiver 1370 * registration. If the state is already CONNECTED, no state change will be received via the 1371 * intent after calling startBluetoothSco(). It is however useful to call startBluetoothSco() 1372 * so that the connection stays active in case the current initiator stops the connection. 1373 * <p>Unless the connection is already active as described above, the state will always 1374 * transition from DISCONNECTED to CONNECTING and then either to CONNECTED if the connection 1375 * succeeds or back to DISCONNECTED if the connection fails (e.g no headset is connected). 1376 * <p>When finished with the SCO connection or if the establishment fails, the application must 1377 * call {@link #stopBluetoothSco()} to clear the request and turn down the bluetooth connection. 1378 * <p>Even if a SCO connection is established, the following restrictions apply on audio 1379 * output streams so that they can be routed to SCO headset: 1380 * <ul> 1381 * <li> the stream type must be {@link #STREAM_VOICE_CALL} </li> 1382 * <li> the format must be mono </li> 1383 * <li> the sampling must be 16kHz or 8kHz </li> 1384 * </ul> 1385 * <p>The following restrictions apply on input streams: 1386 * <ul> 1387 * <li> the format must be mono </li> 1388 * <li> the sampling must be 8kHz </li> 1389 * </ul> 1390 * <p>Note that the phone application always has the priority on the usage of the SCO 1391 * connection for telephony. If this method is called while the phone is in call 1392 * it will be ignored. Similarly, if a call is received or sent while an application 1393 * is using the SCO connection, the connection will be lost for the application and NOT 1394 * returned automatically when the call ends. 1395 * <p>NOTE: up to and including API version 1396 * {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}, this method initiates a virtual 1397 * voice call to the bluetooth headset. 1398 * After API version {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2} only a raw SCO audio 1399 * connection is established. 1400 * @see #stopBluetoothSco() 1401 * @see #ACTION_SCO_AUDIO_STATE_UPDATED 1402 */ startBluetoothSco()1403 public void startBluetoothSco(){ 1404 IAudioService service = getService(); 1405 try { 1406 service.startBluetoothSco(mICallBack, 1407 getContext().getApplicationInfo().targetSdkVersion); 1408 } catch (RemoteException e) { 1409 throw e.rethrowFromSystemServer(); 1410 } 1411 } 1412 1413 /** 1414 * @hide 1415 * Start bluetooth SCO audio connection in virtual call mode. 1416 * <p>Requires Permission: 1417 * {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}. 1418 * <p>Similar to {@link #startBluetoothSco()} with explicit selection of virtual call mode. 1419 * Telephony and communication applications (VoIP, Video Chat) should preferably select 1420 * virtual call mode. 1421 * Applications using voice input for search or commands should first try raw audio connection 1422 * with {@link #startBluetoothSco()} and fall back to startBluetoothScoVirtualCall() in case of 1423 * failure. 1424 * @see #startBluetoothSco() 1425 * @see #stopBluetoothSco() 1426 * @see #ACTION_SCO_AUDIO_STATE_UPDATED 1427 */ startBluetoothScoVirtualCall()1428 public void startBluetoothScoVirtualCall() { 1429 IAudioService service = getService(); 1430 try { 1431 service.startBluetoothScoVirtualCall(mICallBack); 1432 } catch (RemoteException e) { 1433 throw e.rethrowFromSystemServer(); 1434 } 1435 } 1436 1437 /** 1438 * Stop bluetooth SCO audio connection. 1439 * <p>Requires Permission: 1440 * {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}. 1441 * <p>This method must be called by applications having requested the use of 1442 * bluetooth SCO audio with {@link #startBluetoothSco()} when finished with the SCO 1443 * connection or if connection fails. 1444 * @see #startBluetoothSco() 1445 */ 1446 // Also used for connections started with {@link #startBluetoothScoVirtualCall()} stopBluetoothSco()1447 public void stopBluetoothSco(){ 1448 IAudioService service = getService(); 1449 try { 1450 service.stopBluetoothSco(mICallBack); 1451 } catch (RemoteException e) { 1452 throw e.rethrowFromSystemServer(); 1453 } 1454 } 1455 1456 /** 1457 * Request use of Bluetooth SCO headset for communications. 1458 * <p> 1459 * This method should only be used by applications that replace the platform-wide 1460 * management of audio settings or the main telephony application. 1461 * 1462 * @param on set <var>true</var> to use bluetooth SCO for communications; 1463 * <var>false</var> to not use bluetooth SCO for communications 1464 */ setBluetoothScoOn(boolean on)1465 public void setBluetoothScoOn(boolean on){ 1466 IAudioService service = getService(); 1467 try { 1468 service.setBluetoothScoOn(on); 1469 } catch (RemoteException e) { 1470 throw e.rethrowFromSystemServer(); 1471 } 1472 } 1473 1474 /** 1475 * Checks whether communications use Bluetooth SCO. 1476 * 1477 * @return true if SCO is used for communications; 1478 * false if otherwise 1479 */ isBluetoothScoOn()1480 public boolean isBluetoothScoOn() { 1481 IAudioService service = getService(); 1482 try { 1483 return service.isBluetoothScoOn(); 1484 } catch (RemoteException e) { 1485 throw e.rethrowFromSystemServer(); 1486 } 1487 } 1488 1489 /** 1490 * @param on set <var>true</var> to route A2DP audio to/from Bluetooth 1491 * headset; <var>false</var> disable A2DP audio 1492 * @deprecated Do not use. 1493 */ setBluetoothA2dpOn(boolean on)1494 @Deprecated public void setBluetoothA2dpOn(boolean on){ 1495 } 1496 1497 /** 1498 * Checks whether A2DP audio routing to the Bluetooth headset is on or off. 1499 * 1500 * @return true if A2DP audio is being routed to/from Bluetooth headset; 1501 * false if otherwise 1502 */ isBluetoothA2dpOn()1503 public boolean isBluetoothA2dpOn() { 1504 if (AudioSystem.getDeviceConnectionState(DEVICE_OUT_BLUETOOTH_A2DP,"") 1505 == AudioSystem.DEVICE_STATE_AVAILABLE) { 1506 return true; 1507 } else if (AudioSystem.getDeviceConnectionState(DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES,"") 1508 == AudioSystem.DEVICE_STATE_AVAILABLE) { 1509 return true; 1510 } else if (AudioSystem.getDeviceConnectionState(DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER,"") 1511 == AudioSystem.DEVICE_STATE_AVAILABLE) { 1512 return true; 1513 } 1514 return false; 1515 } 1516 1517 /** 1518 * Sets audio routing to the wired headset on or off. 1519 * 1520 * @param on set <var>true</var> to route audio to/from wired 1521 * headset; <var>false</var> disable wired headset audio 1522 * @deprecated Do not use. 1523 */ setWiredHeadsetOn(boolean on)1524 @Deprecated public void setWiredHeadsetOn(boolean on){ 1525 } 1526 1527 /** 1528 * Checks whether a wired headset is connected or not. 1529 * <p>This is not a valid indication that audio playback is 1530 * actually over the wired headset as audio routing depends on other conditions. 1531 * 1532 * @return true if a wired headset is connected. 1533 * false if otherwise 1534 * @deprecated Use only to check is a headset is connected or not. 1535 */ isWiredHeadsetOn()1536 public boolean isWiredHeadsetOn() { 1537 if (AudioSystem.getDeviceConnectionState(DEVICE_OUT_WIRED_HEADSET,"") 1538 == AudioSystem.DEVICE_STATE_UNAVAILABLE && 1539 AudioSystem.getDeviceConnectionState(DEVICE_OUT_WIRED_HEADPHONE,"") 1540 == AudioSystem.DEVICE_STATE_UNAVAILABLE) { 1541 return false; 1542 } else { 1543 return true; 1544 } 1545 } 1546 1547 /** 1548 * Sets the microphone mute on or off. 1549 * <p> 1550 * This method should only be used by applications that replace the platform-wide 1551 * management of audio settings or the main telephony application. 1552 * 1553 * @param on set <var>true</var> to mute the microphone; 1554 * <var>false</var> to turn mute off 1555 */ setMicrophoneMute(boolean on)1556 public void setMicrophoneMute(boolean on) { 1557 IAudioService service = getService(); 1558 try { 1559 service.setMicrophoneMute(on, getContext().getOpPackageName(), 1560 UserHandle.getCallingUserId()); 1561 } catch (RemoteException e) { 1562 throw e.rethrowFromSystemServer(); 1563 } 1564 } 1565 1566 /** 1567 * Checks whether the microphone mute is on or off. 1568 * 1569 * @return true if microphone is muted, false if it's not 1570 */ isMicrophoneMute()1571 public boolean isMicrophoneMute() { 1572 return AudioSystem.isMicrophoneMuted(); 1573 } 1574 1575 /** 1576 * Sets the audio mode. 1577 * <p> 1578 * The audio mode encompasses audio routing AND the behavior of 1579 * the telephony layer. Therefore this method should only be used by applications that 1580 * replace the platform-wide management of audio settings or the main telephony application. 1581 * In particular, the {@link #MODE_IN_CALL} mode should only be used by the telephony 1582 * application when it places a phone call, as it will cause signals from the radio layer 1583 * to feed the platform mixer. 1584 * 1585 * @param mode the requested audio mode ({@link #MODE_NORMAL}, {@link #MODE_RINGTONE}, 1586 * {@link #MODE_IN_CALL} or {@link #MODE_IN_COMMUNICATION}). 1587 * Informs the HAL about the current audio state so that 1588 * it can route the audio appropriately. 1589 */ setMode(int mode)1590 public void setMode(int mode) { 1591 IAudioService service = getService(); 1592 try { 1593 service.setMode(mode, mICallBack, mApplicationContext.getOpPackageName()); 1594 } catch (RemoteException e) { 1595 throw e.rethrowFromSystemServer(); 1596 } 1597 } 1598 1599 /** 1600 * Returns the current audio mode. 1601 * 1602 * @return the current audio mode ({@link #MODE_NORMAL}, {@link #MODE_RINGTONE}, 1603 * {@link #MODE_IN_CALL} or {@link #MODE_IN_COMMUNICATION}). 1604 * Returns the current current audio state from the HAL. 1605 */ getMode()1606 public int getMode() { 1607 IAudioService service = getService(); 1608 try { 1609 return service.getMode(); 1610 } catch (RemoteException e) { 1611 throw e.rethrowFromSystemServer(); 1612 } 1613 } 1614 1615 /* modes for setMode/getMode/setRoute/getRoute */ 1616 /** 1617 * Audio harware modes. 1618 */ 1619 /** 1620 * Invalid audio mode. 1621 */ 1622 public static final int MODE_INVALID = AudioSystem.MODE_INVALID; 1623 /** 1624 * Current audio mode. Used to apply audio routing to current mode. 1625 */ 1626 public static final int MODE_CURRENT = AudioSystem.MODE_CURRENT; 1627 /** 1628 * Normal audio mode: not ringing and no call established. 1629 */ 1630 public static final int MODE_NORMAL = AudioSystem.MODE_NORMAL; 1631 /** 1632 * Ringing audio mode. An incoming is being signaled. 1633 */ 1634 public static final int MODE_RINGTONE = AudioSystem.MODE_RINGTONE; 1635 /** 1636 * In call audio mode. A telephony call is established. 1637 */ 1638 public static final int MODE_IN_CALL = AudioSystem.MODE_IN_CALL; 1639 /** 1640 * In communication audio mode. An audio/video chat or VoIP call is established. 1641 */ 1642 public static final int MODE_IN_COMMUNICATION = AudioSystem.MODE_IN_COMMUNICATION; 1643 1644 /* Routing bits for setRouting/getRouting API */ 1645 /** 1646 * Routing audio output to earpiece 1647 * @deprecated Do not set audio routing directly, use setSpeakerphoneOn(), 1648 * setBluetoothScoOn() methods instead. 1649 */ 1650 @Deprecated public static final int ROUTE_EARPIECE = AudioSystem.ROUTE_EARPIECE; 1651 /** 1652 * Routing audio output to speaker 1653 * @deprecated Do not set audio routing directly, use setSpeakerphoneOn(), 1654 * setBluetoothScoOn() methods instead. 1655 */ 1656 @Deprecated public static final int ROUTE_SPEAKER = AudioSystem.ROUTE_SPEAKER; 1657 /** 1658 * @deprecated use {@link #ROUTE_BLUETOOTH_SCO} 1659 * @deprecated Do not set audio routing directly, use setSpeakerphoneOn(), 1660 * setBluetoothScoOn() methods instead. 1661 */ 1662 @Deprecated public static final int ROUTE_BLUETOOTH = AudioSystem.ROUTE_BLUETOOTH_SCO; 1663 /** 1664 * Routing audio output to bluetooth SCO 1665 * @deprecated Do not set audio routing directly, use setSpeakerphoneOn(), 1666 * setBluetoothScoOn() methods instead. 1667 */ 1668 @Deprecated public static final int ROUTE_BLUETOOTH_SCO = AudioSystem.ROUTE_BLUETOOTH_SCO; 1669 /** 1670 * Routing audio output to headset 1671 * @deprecated Do not set audio routing directly, use setSpeakerphoneOn(), 1672 * setBluetoothScoOn() methods instead. 1673 */ 1674 @Deprecated public static final int ROUTE_HEADSET = AudioSystem.ROUTE_HEADSET; 1675 /** 1676 * Routing audio output to bluetooth A2DP 1677 * @deprecated Do not set audio routing directly, use setSpeakerphoneOn(), 1678 * setBluetoothScoOn() methods instead. 1679 */ 1680 @Deprecated public static final int ROUTE_BLUETOOTH_A2DP = AudioSystem.ROUTE_BLUETOOTH_A2DP; 1681 /** 1682 * Used for mask parameter of {@link #setRouting(int,int,int)}. 1683 * @deprecated Do not set audio routing directly, use setSpeakerphoneOn(), 1684 * setBluetoothScoOn() methods instead. 1685 */ 1686 @Deprecated public static final int ROUTE_ALL = AudioSystem.ROUTE_ALL; 1687 1688 /** 1689 * Sets the audio routing for a specified mode 1690 * 1691 * @param mode audio mode to change route. E.g., MODE_RINGTONE. 1692 * @param routes bit vector of routes requested, created from one or 1693 * more of ROUTE_xxx types. Set bits indicate that route should be on 1694 * @param mask bit vector of routes to change, created from one or more of 1695 * ROUTE_xxx types. Unset bits indicate the route should be left unchanged 1696 * 1697 * @deprecated Do not set audio routing directly, use setSpeakerphoneOn(), 1698 * setBluetoothScoOn() methods instead. 1699 */ 1700 @Deprecated setRouting(int mode, int routes, int mask)1701 public void setRouting(int mode, int routes, int mask) { 1702 } 1703 1704 /** 1705 * Returns the current audio routing bit vector for a specified mode. 1706 * 1707 * @param mode audio mode to get route (e.g., MODE_RINGTONE) 1708 * @return an audio route bit vector that can be compared with ROUTE_xxx 1709 * bits 1710 * @deprecated Do not query audio routing directly, use isSpeakerphoneOn(), 1711 * isBluetoothScoOn(), isBluetoothA2dpOn() and isWiredHeadsetOn() methods instead. 1712 */ 1713 @Deprecated getRouting(int mode)1714 public int getRouting(int mode) { 1715 return -1; 1716 } 1717 1718 /** 1719 * Checks whether any music is active. 1720 * 1721 * @return true if any music tracks are active. 1722 */ isMusicActive()1723 public boolean isMusicActive() { 1724 return AudioSystem.isStreamActive(STREAM_MUSIC, 0); 1725 } 1726 1727 /** 1728 * @hide 1729 * Checks whether any music or media is actively playing on a remote device (e.g. wireless 1730 * display). Note that BT audio sinks are not considered remote devices. 1731 * @return true if {@link AudioManager#STREAM_MUSIC} is active on a remote device 1732 */ isMusicActiveRemotely()1733 public boolean isMusicActiveRemotely() { 1734 return AudioSystem.isStreamActiveRemotely(STREAM_MUSIC, 0); 1735 } 1736 1737 /** 1738 * @hide 1739 * Checks whether the current audio focus is exclusive. 1740 * @return true if the top of the audio focus stack requested focus 1741 * with {@link #AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE} 1742 */ isAudioFocusExclusive()1743 public boolean isAudioFocusExclusive() { 1744 IAudioService service = getService(); 1745 try { 1746 return service.getCurrentAudioFocus() == AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE; 1747 } catch (RemoteException e) { 1748 throw e.rethrowFromSystemServer(); 1749 } 1750 } 1751 1752 /** 1753 * Return a new audio session identifier not associated with any player or effect. 1754 * An audio session identifier is a system wide unique identifier for a set of audio streams 1755 * (one or more mixed together). 1756 * <p>The primary use of the audio session ID is to associate audio effects to audio players, 1757 * such as {@link MediaPlayer} or {@link AudioTrack}: all audio effects sharing the same audio 1758 * session ID will be applied to the mixed audio content of the players that share the same 1759 * audio session. 1760 * <p>This method can for instance be used when creating one of the 1761 * {@link android.media.audiofx.AudioEffect} objects to define the audio session of the effect, 1762 * or to specify a session for a speech synthesis utterance 1763 * in {@link android.speech.tts.TextToSpeech.Engine}. 1764 * @return a new unclaimed and unused audio session identifier, or {@link #ERROR} when the 1765 * system failed to generate a new session, a condition in which audio playback or recording 1766 * will subsequently fail as well. 1767 */ generateAudioSessionId()1768 public int generateAudioSessionId() { 1769 int session = AudioSystem.newAudioSessionId(); 1770 if (session > 0) { 1771 return session; 1772 } else { 1773 Log.e(TAG, "Failure to generate a new audio session ID"); 1774 return ERROR; 1775 } 1776 } 1777 1778 /** 1779 * A special audio session ID to indicate that the audio session ID isn't known and the 1780 * framework should generate a new value. This can be used when building a new 1781 * {@link AudioTrack} instance with 1782 * {@link AudioTrack#AudioTrack(AudioAttributes, AudioFormat, int, int, int)}. 1783 */ 1784 public static final int AUDIO_SESSION_ID_GENERATE = AudioSystem.AUDIO_SESSION_ALLOCATE; 1785 1786 1787 /* 1788 * Sets a generic audio configuration parameter. The use of these parameters 1789 * are platform dependant, see libaudio 1790 * 1791 * ** Temporary interface - DO NOT USE 1792 * 1793 * TODO: Replace with a more generic key:value get/set mechanism 1794 * 1795 * param key name of parameter to set. Must not be null. 1796 * param value value of parameter. Must not be null. 1797 */ 1798 /** 1799 * @hide 1800 * @deprecated Use {@link #setParameters(String)} instead 1801 */ setParameter(String key, String value)1802 @Deprecated public void setParameter(String key, String value) { 1803 setParameters(key+"="+value); 1804 } 1805 1806 /** 1807 * Sets a variable number of parameter values to audio hardware. 1808 * 1809 * @param keyValuePairs list of parameters key value pairs in the form: 1810 * key1=value1;key2=value2;... 1811 * 1812 */ setParameters(String keyValuePairs)1813 public void setParameters(String keyValuePairs) { 1814 AudioSystem.setParameters(keyValuePairs); 1815 } 1816 1817 /** 1818 * Gets a variable number of parameter values from audio hardware. 1819 * 1820 * @param keys list of parameters 1821 * @return list of parameters key value pairs in the form: 1822 * key1=value1;key2=value2;... 1823 */ getParameters(String keys)1824 public String getParameters(String keys) { 1825 return AudioSystem.getParameters(keys); 1826 } 1827 1828 /* Sound effect identifiers */ 1829 /** 1830 * Keyboard and direction pad click sound 1831 * @see #playSoundEffect(int) 1832 */ 1833 public static final int FX_KEY_CLICK = 0; 1834 /** 1835 * Focus has moved up 1836 * @see #playSoundEffect(int) 1837 */ 1838 public static final int FX_FOCUS_NAVIGATION_UP = 1; 1839 /** 1840 * Focus has moved down 1841 * @see #playSoundEffect(int) 1842 */ 1843 public static final int FX_FOCUS_NAVIGATION_DOWN = 2; 1844 /** 1845 * Focus has moved left 1846 * @see #playSoundEffect(int) 1847 */ 1848 public static final int FX_FOCUS_NAVIGATION_LEFT = 3; 1849 /** 1850 * Focus has moved right 1851 * @see #playSoundEffect(int) 1852 */ 1853 public static final int FX_FOCUS_NAVIGATION_RIGHT = 4; 1854 /** 1855 * IME standard keypress sound 1856 * @see #playSoundEffect(int) 1857 */ 1858 public static final int FX_KEYPRESS_STANDARD = 5; 1859 /** 1860 * IME spacebar keypress sound 1861 * @see #playSoundEffect(int) 1862 */ 1863 public static final int FX_KEYPRESS_SPACEBAR = 6; 1864 /** 1865 * IME delete keypress sound 1866 * @see #playSoundEffect(int) 1867 */ 1868 public static final int FX_KEYPRESS_DELETE = 7; 1869 /** 1870 * IME return_keypress sound 1871 * @see #playSoundEffect(int) 1872 */ 1873 public static final int FX_KEYPRESS_RETURN = 8; 1874 1875 /** 1876 * Invalid keypress sound 1877 * @see #playSoundEffect(int) 1878 */ 1879 public static final int FX_KEYPRESS_INVALID = 9; 1880 /** 1881 * @hide Number of sound effects 1882 */ 1883 public static final int NUM_SOUND_EFFECTS = 10; 1884 1885 /** 1886 * Plays a sound effect (Key clicks, lid open/close...) 1887 * @param effectType The type of sound effect. One of 1888 * {@link #FX_KEY_CLICK}, 1889 * {@link #FX_FOCUS_NAVIGATION_UP}, 1890 * {@link #FX_FOCUS_NAVIGATION_DOWN}, 1891 * {@link #FX_FOCUS_NAVIGATION_LEFT}, 1892 * {@link #FX_FOCUS_NAVIGATION_RIGHT}, 1893 * {@link #FX_KEYPRESS_STANDARD}, 1894 * {@link #FX_KEYPRESS_SPACEBAR}, 1895 * {@link #FX_KEYPRESS_DELETE}, 1896 * {@link #FX_KEYPRESS_RETURN}, 1897 * {@link #FX_KEYPRESS_INVALID}, 1898 * NOTE: This version uses the UI settings to determine 1899 * whether sounds are heard or not. 1900 */ playSoundEffect(int effectType)1901 public void playSoundEffect(int effectType) { 1902 if (effectType < 0 || effectType >= NUM_SOUND_EFFECTS) { 1903 return; 1904 } 1905 1906 if (!querySoundEffectsEnabled(Process.myUserHandle().getIdentifier())) { 1907 return; 1908 } 1909 1910 IAudioService service = getService(); 1911 try { 1912 service.playSoundEffect(effectType); 1913 } catch (RemoteException e) { 1914 throw e.rethrowFromSystemServer(); 1915 } 1916 } 1917 1918 /** 1919 * Plays a sound effect (Key clicks, lid open/close...) 1920 * @param effectType The type of sound effect. One of 1921 * {@link #FX_KEY_CLICK}, 1922 * {@link #FX_FOCUS_NAVIGATION_UP}, 1923 * {@link #FX_FOCUS_NAVIGATION_DOWN}, 1924 * {@link #FX_FOCUS_NAVIGATION_LEFT}, 1925 * {@link #FX_FOCUS_NAVIGATION_RIGHT}, 1926 * {@link #FX_KEYPRESS_STANDARD}, 1927 * {@link #FX_KEYPRESS_SPACEBAR}, 1928 * {@link #FX_KEYPRESS_DELETE}, 1929 * {@link #FX_KEYPRESS_RETURN}, 1930 * {@link #FX_KEYPRESS_INVALID}, 1931 * @param userId The current user to pull sound settings from 1932 * NOTE: This version uses the UI settings to determine 1933 * whether sounds are heard or not. 1934 * @hide 1935 */ playSoundEffect(int effectType, int userId)1936 public void playSoundEffect(int effectType, int userId) { 1937 if (effectType < 0 || effectType >= NUM_SOUND_EFFECTS) { 1938 return; 1939 } 1940 1941 if (!querySoundEffectsEnabled(userId)) { 1942 return; 1943 } 1944 1945 IAudioService service = getService(); 1946 try { 1947 service.playSoundEffect(effectType); 1948 } catch (RemoteException e) { 1949 throw e.rethrowFromSystemServer(); 1950 } 1951 } 1952 1953 /** 1954 * Plays a sound effect (Key clicks, lid open/close...) 1955 * @param effectType The type of sound effect. One of 1956 * {@link #FX_KEY_CLICK}, 1957 * {@link #FX_FOCUS_NAVIGATION_UP}, 1958 * {@link #FX_FOCUS_NAVIGATION_DOWN}, 1959 * {@link #FX_FOCUS_NAVIGATION_LEFT}, 1960 * {@link #FX_FOCUS_NAVIGATION_RIGHT}, 1961 * {@link #FX_KEYPRESS_STANDARD}, 1962 * {@link #FX_KEYPRESS_SPACEBAR}, 1963 * {@link #FX_KEYPRESS_DELETE}, 1964 * {@link #FX_KEYPRESS_RETURN}, 1965 * {@link #FX_KEYPRESS_INVALID}, 1966 * @param volume Sound effect volume. 1967 * The volume value is a raw scalar so UI controls should be scaled logarithmically. 1968 * If a volume of -1 is specified, the AudioManager.STREAM_MUSIC stream volume minus 3dB will be used. 1969 * NOTE: This version is for applications that have their own 1970 * settings panel for enabling and controlling volume. 1971 */ playSoundEffect(int effectType, float volume)1972 public void playSoundEffect(int effectType, float volume) { 1973 if (effectType < 0 || effectType >= NUM_SOUND_EFFECTS) { 1974 return; 1975 } 1976 1977 IAudioService service = getService(); 1978 try { 1979 service.playSoundEffectVolume(effectType, volume); 1980 } catch (RemoteException e) { 1981 throw e.rethrowFromSystemServer(); 1982 } 1983 } 1984 1985 /** 1986 * Settings has an in memory cache, so this is fast. 1987 */ querySoundEffectsEnabled(int user)1988 private boolean querySoundEffectsEnabled(int user) { 1989 return Settings.System.getIntForUser(getContext().getContentResolver(), 1990 Settings.System.SOUND_EFFECTS_ENABLED, 0, user) != 0; 1991 } 1992 1993 1994 /** 1995 * Load Sound effects. 1996 * This method must be called when sound effects are enabled. 1997 */ loadSoundEffects()1998 public void loadSoundEffects() { 1999 IAudioService service = getService(); 2000 try { 2001 service.loadSoundEffects(); 2002 } catch (RemoteException e) { 2003 throw e.rethrowFromSystemServer(); 2004 } 2005 } 2006 2007 /** 2008 * Unload Sound effects. 2009 * This method can be called to free some memory when 2010 * sound effects are disabled. 2011 */ unloadSoundEffects()2012 public void unloadSoundEffects() { 2013 IAudioService service = getService(); 2014 try { 2015 service.unloadSoundEffects(); 2016 } catch (RemoteException e) { 2017 throw e.rethrowFromSystemServer(); 2018 } 2019 } 2020 2021 /** 2022 * @hide 2023 * Used to indicate no audio focus has been gained or lost. 2024 */ 2025 public static final int AUDIOFOCUS_NONE = 0; 2026 2027 /** 2028 * Used to indicate a gain of audio focus, or a request of audio focus, of unknown duration. 2029 * @see OnAudioFocusChangeListener#onAudioFocusChange(int) 2030 * @see #requestAudioFocus(OnAudioFocusChangeListener, int, int) 2031 */ 2032 public static final int AUDIOFOCUS_GAIN = 1; 2033 /** 2034 * Used to indicate a temporary gain or request of audio focus, anticipated to last a short 2035 * amount of time. Examples of temporary changes are the playback of driving directions, or an 2036 * event notification. 2037 * @see OnAudioFocusChangeListener#onAudioFocusChange(int) 2038 * @see #requestAudioFocus(OnAudioFocusChangeListener, int, int) 2039 */ 2040 public static final int AUDIOFOCUS_GAIN_TRANSIENT = 2; 2041 /** 2042 * Used to indicate a temporary request of audio focus, anticipated to last a short 2043 * amount of time, and where it is acceptable for other audio applications to keep playing 2044 * after having lowered their output level (also referred to as "ducking"). 2045 * Examples of temporary changes are the playback of driving directions where playback of music 2046 * in the background is acceptable. 2047 * @see OnAudioFocusChangeListener#onAudioFocusChange(int) 2048 * @see #requestAudioFocus(OnAudioFocusChangeListener, int, int) 2049 */ 2050 public static final int AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK = 3; 2051 /** 2052 * Used to indicate a temporary request of audio focus, anticipated to last a short 2053 * amount of time, during which no other applications, or system components, should play 2054 * anything. Examples of exclusive and transient audio focus requests are voice 2055 * memo recording and speech recognition, during which the system shouldn't play any 2056 * notifications, and media playback should have paused. 2057 * @see #requestAudioFocus(OnAudioFocusChangeListener, int, int) 2058 */ 2059 public static final int AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE = 4; 2060 /** 2061 * Used to indicate a loss of audio focus of unknown duration. 2062 * @see OnAudioFocusChangeListener#onAudioFocusChange(int) 2063 */ 2064 public static final int AUDIOFOCUS_LOSS = -1 * AUDIOFOCUS_GAIN; 2065 /** 2066 * Used to indicate a transient loss of audio focus. 2067 * @see OnAudioFocusChangeListener#onAudioFocusChange(int) 2068 */ 2069 public static final int AUDIOFOCUS_LOSS_TRANSIENT = -1 * AUDIOFOCUS_GAIN_TRANSIENT; 2070 /** 2071 * Used to indicate a transient loss of audio focus where the loser of the audio focus can 2072 * lower its output volume if it wants to continue playing (also referred to as "ducking"), as 2073 * the new focus owner doesn't require others to be silent. 2074 * @see OnAudioFocusChangeListener#onAudioFocusChange(int) 2075 */ 2076 public static final int AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK = 2077 -1 * AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK; 2078 2079 /** 2080 * Interface definition for a callback to be invoked when the audio focus of the system is 2081 * updated. 2082 */ 2083 public interface OnAudioFocusChangeListener { 2084 /** 2085 * Called on the listener to notify it the audio focus for this listener has been changed. 2086 * The focusChange value indicates whether the focus was gained, 2087 * whether the focus was lost, and whether that loss is transient, or whether the new focus 2088 * holder will hold it for an unknown amount of time. 2089 * When losing focus, listeners can use the focus change information to decide what 2090 * behavior to adopt when losing focus. A music player could for instance elect to lower 2091 * the volume of its music stream (duck) for transient focus losses, and pause otherwise. 2092 * @param focusChange the type of focus change, one of {@link AudioManager#AUDIOFOCUS_GAIN}, 2093 * {@link AudioManager#AUDIOFOCUS_LOSS}, {@link AudioManager#AUDIOFOCUS_LOSS_TRANSIENT} 2094 * and {@link AudioManager#AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK}. 2095 */ onAudioFocusChange(int focusChange)2096 public void onAudioFocusChange(int focusChange); 2097 } 2098 2099 /** 2100 * Map to convert focus event listener IDs, as used in the AudioService audio focus stack, 2101 * to actual listener objects. 2102 */ 2103 private final HashMap<String, OnAudioFocusChangeListener> mAudioFocusIdListenerMap = 2104 new HashMap<String, OnAudioFocusChangeListener>(); 2105 /** 2106 * Lock to prevent concurrent changes to the list of focus listeners for this AudioManager 2107 * instance. 2108 */ 2109 private final Object mFocusListenerLock = new Object(); 2110 findFocusListener(String id)2111 private OnAudioFocusChangeListener findFocusListener(String id) { 2112 return mAudioFocusIdListenerMap.get(id); 2113 } 2114 2115 /** 2116 * Handler for events (audio focus change, recording config change) coming from the 2117 * audio service. 2118 */ 2119 private final ServiceEventHandlerDelegate mServiceEventHandlerDelegate = 2120 new ServiceEventHandlerDelegate(null); 2121 2122 /** 2123 * Event types 2124 */ 2125 private final static int MSSG_FOCUS_CHANGE = 0; 2126 private final static int MSSG_RECORDING_CONFIG_CHANGE = 1; 2127 2128 /** 2129 * Helper class to handle the forwarding of audio service events to the appropriate listener 2130 */ 2131 private class ServiceEventHandlerDelegate { 2132 private final Handler mHandler; 2133 ServiceEventHandlerDelegate(Handler handler)2134 ServiceEventHandlerDelegate(Handler handler) { 2135 Looper looper; 2136 if (handler == null) { 2137 if ((looper = Looper.myLooper()) == null) { 2138 looper = Looper.getMainLooper(); 2139 } 2140 } else { 2141 looper = handler.getLooper(); 2142 } 2143 2144 if (looper != null) { 2145 // implement the event handler delegate to receive events from audio service 2146 mHandler = new Handler(looper) { 2147 @Override 2148 public void handleMessage(Message msg) { 2149 switch (msg.what) { 2150 case MSSG_FOCUS_CHANGE: 2151 OnAudioFocusChangeListener listener = null; 2152 synchronized(mFocusListenerLock) { 2153 listener = findFocusListener((String)msg.obj); 2154 } 2155 if (listener != null) { 2156 Log.d(TAG, "AudioManager dispatching onAudioFocusChange(" 2157 + msg.arg1 + ") for " + msg.obj); 2158 listener.onAudioFocusChange(msg.arg1); 2159 } 2160 break; 2161 case MSSG_RECORDING_CONFIG_CHANGE: 2162 final RecordConfigChangeCallbackData cbData = 2163 (RecordConfigChangeCallbackData) msg.obj; 2164 if (cbData.mCb != null) { 2165 cbData.mCb.onRecordingConfigChanged(cbData.mConfigs); 2166 } 2167 break; 2168 default: 2169 Log.e(TAG, "Unknown event " + msg.what); 2170 } 2171 } 2172 }; 2173 } else { 2174 mHandler = null; 2175 } 2176 } 2177 getHandler()2178 Handler getHandler() { 2179 return mHandler; 2180 } 2181 } 2182 2183 private final IAudioFocusDispatcher mAudioFocusDispatcher = new IAudioFocusDispatcher.Stub() { 2184 2185 public void dispatchAudioFocusChange(int focusChange, String id) { 2186 final Message m = mServiceEventHandlerDelegate.getHandler().obtainMessage( 2187 MSSG_FOCUS_CHANGE/*what*/, focusChange/*arg1*/, 0/*arg2 ignored*/, id/*obj*/); 2188 mServiceEventHandlerDelegate.getHandler().sendMessage(m); 2189 } 2190 2191 }; 2192 getIdForAudioFocusListener(OnAudioFocusChangeListener l)2193 private String getIdForAudioFocusListener(OnAudioFocusChangeListener l) { 2194 if (l == null) { 2195 return new String(this.toString()); 2196 } else { 2197 return new String(this.toString() + l.toString()); 2198 } 2199 } 2200 2201 /** 2202 * @hide 2203 * Registers a listener to be called when audio focus changes. Calling this method is optional 2204 * before calling {@link #requestAudioFocus(OnAudioFocusChangeListener, int, int)}, as it 2205 * will register the listener as well if it wasn't registered already. 2206 * @param l the listener to be notified of audio focus changes. 2207 */ registerAudioFocusListener(OnAudioFocusChangeListener l)2208 public void registerAudioFocusListener(OnAudioFocusChangeListener l) { 2209 synchronized(mFocusListenerLock) { 2210 if (mAudioFocusIdListenerMap.containsKey(getIdForAudioFocusListener(l))) { 2211 return; 2212 } 2213 mAudioFocusIdListenerMap.put(getIdForAudioFocusListener(l), l); 2214 } 2215 } 2216 2217 /** 2218 * @hide 2219 * Causes the specified listener to not be called anymore when focus is gained or lost. 2220 * @param l the listener to unregister. 2221 */ unregisterAudioFocusListener(OnAudioFocusChangeListener l)2222 public void unregisterAudioFocusListener(OnAudioFocusChangeListener l) { 2223 2224 // remove locally 2225 synchronized(mFocusListenerLock) { 2226 mAudioFocusIdListenerMap.remove(getIdForAudioFocusListener(l)); 2227 } 2228 } 2229 2230 2231 /** 2232 * A failed focus change request. 2233 */ 2234 public static final int AUDIOFOCUS_REQUEST_FAILED = 0; 2235 /** 2236 * A successful focus change request. 2237 */ 2238 public static final int AUDIOFOCUS_REQUEST_GRANTED = 1; 2239 /** 2240 * @hide 2241 * A focus change request whose granting is delayed: the request was successful, but the 2242 * requester will only be granted audio focus once the condition that prevented immediate 2243 * granting has ended. 2244 * See {@link #requestAudioFocus(OnAudioFocusChangeListener, AudioAttributes, int, int)} 2245 */ 2246 public static final int AUDIOFOCUS_REQUEST_DELAYED = 2; 2247 2248 2249 /** 2250 * Request audio focus. 2251 * Send a request to obtain the audio focus 2252 * @param l the listener to be notified of audio focus changes 2253 * @param streamType the main audio stream type affected by the focus request 2254 * @param durationHint use {@link #AUDIOFOCUS_GAIN_TRANSIENT} to indicate this focus request 2255 * is temporary, and focus will be abandonned shortly. Examples of transient requests are 2256 * for the playback of driving directions, or notifications sounds. 2257 * Use {@link #AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK} to indicate also that it's ok for 2258 * the previous focus owner to keep playing if it ducks its audio output. 2259 * Alternatively use {@link #AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE} for a temporary request 2260 * that benefits from the system not playing disruptive sounds like notifications, for 2261 * usecases such as voice memo recording, or speech recognition. 2262 * Use {@link #AUDIOFOCUS_GAIN} for a focus request of unknown duration such 2263 * as the playback of a song or a video. 2264 * @return {@link #AUDIOFOCUS_REQUEST_FAILED} or {@link #AUDIOFOCUS_REQUEST_GRANTED} 2265 */ requestAudioFocus(OnAudioFocusChangeListener l, int streamType, int durationHint)2266 public int requestAudioFocus(OnAudioFocusChangeListener l, int streamType, int durationHint) { 2267 int status = AUDIOFOCUS_REQUEST_FAILED; 2268 2269 try { 2270 // status is guaranteed to be either AUDIOFOCUS_REQUEST_FAILED or 2271 // AUDIOFOCUS_REQUEST_GRANTED as focus is requested without the 2272 // AUDIOFOCUS_FLAG_DELAY_OK flag 2273 status = requestAudioFocus(l, 2274 new AudioAttributes.Builder() 2275 .setInternalLegacyStreamType(streamType).build(), 2276 durationHint, 2277 0 /* flags, legacy behavior */); 2278 } catch (IllegalArgumentException e) { 2279 Log.e(TAG, "Audio focus request denied due to ", e); 2280 } 2281 2282 return status; 2283 } 2284 2285 // when adding new flags, add them to the relevant AUDIOFOCUS_FLAGS_APPS or SYSTEM masks 2286 /** 2287 * @hide 2288 * Use this flag when requesting audio focus to indicate it is ok for the requester to not be 2289 * granted audio focus immediately (as indicated by {@link #AUDIOFOCUS_REQUEST_DELAYED}) when 2290 * the system is in a state where focus cannot change, but be granted focus later when 2291 * this condition ends. 2292 */ 2293 @SystemApi 2294 public static final int AUDIOFOCUS_FLAG_DELAY_OK = 0x1 << 0; 2295 /** 2296 * @hide 2297 * Use this flag when requesting audio focus to indicate that the requester 2298 * will pause its media playback (if applicable) when losing audio focus with 2299 * {@link #AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK}, rather than ducking. 2300 * <br>On some platforms, the ducking may be handled without the application being aware of it 2301 * (i.e. it will not transiently lose focus). For applications that for instance play spoken 2302 * content, such as audio book or podcast players, ducking may never be acceptable, and will 2303 * thus always pause. This flag enables them to be declared as such whenever they request focus. 2304 */ 2305 @SystemApi 2306 public static final int AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS = 0x1 << 1; 2307 /** 2308 * @hide 2309 * Use this flag to lock audio focus so granting is temporarily disabled. 2310 * <br>This flag can only be used by owners of a registered 2311 * {@link android.media.audiopolicy.AudioPolicy} in 2312 * {@link #requestAudioFocus(OnAudioFocusChangeListener, AudioAttributes, int, int, AudioPolicy)} 2313 */ 2314 @SystemApi 2315 public static final int AUDIOFOCUS_FLAG_LOCK = 0x1 << 2; 2316 /** @hide */ 2317 public static final int AUDIOFOCUS_FLAGS_APPS = AUDIOFOCUS_FLAG_DELAY_OK 2318 | AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS; 2319 /** @hide */ 2320 public static final int AUDIOFOCUS_FLAGS_SYSTEM = AUDIOFOCUS_FLAG_DELAY_OK 2321 | AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS | AUDIOFOCUS_FLAG_LOCK; 2322 2323 /** 2324 * @hide 2325 * Request audio focus. 2326 * Send a request to obtain the audio focus. This method differs from 2327 * {@link #requestAudioFocus(OnAudioFocusChangeListener, int, int)} in that it can express 2328 * that the requester accepts delayed grants of audio focus. 2329 * @param l the listener to be notified of audio focus changes. It is not allowed to be null 2330 * when the request is flagged with {@link #AUDIOFOCUS_FLAG_DELAY_OK}. 2331 * @param requestAttributes non null {@link AudioAttributes} describing the main reason for 2332 * requesting audio focus. 2333 * @param durationHint use {@link #AUDIOFOCUS_GAIN_TRANSIENT} to indicate this focus request 2334 * is temporary, and focus will be abandonned shortly. Examples of transient requests are 2335 * for the playback of driving directions, or notifications sounds. 2336 * Use {@link #AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK} to indicate also that it's ok for 2337 * the previous focus owner to keep playing if it ducks its audio output. 2338 * Alternatively use {@link #AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE} for a temporary request 2339 * that benefits from the system not playing disruptive sounds like notifications, for 2340 * usecases such as voice memo recording, or speech recognition. 2341 * Use {@link #AUDIOFOCUS_GAIN} for a focus request of unknown duration such 2342 * as the playback of a song or a video. 2343 * @param flags 0 or a combination of {link #AUDIOFOCUS_FLAG_DELAY_OK} 2344 * and {@link #AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS}. 2345 * <br>Use 0 when not using any flags for the request, which behaves like 2346 * {@link #requestAudioFocus(OnAudioFocusChangeListener, int, int)}, where either audio 2347 * focus is granted immediately, or the grant request fails because the system is in a 2348 * state where focus cannot change (e.g. a phone call). 2349 * @return {@link #AUDIOFOCUS_REQUEST_FAILED}, {@link #AUDIOFOCUS_REQUEST_GRANTED} 2350 * or {@link #AUDIOFOCUS_REQUEST_DELAYED}. 2351 * The return value is never {@link #AUDIOFOCUS_REQUEST_DELAYED} when focus is requested 2352 * without the {@link #AUDIOFOCUS_FLAG_DELAY_OK} flag. 2353 * @throws IllegalArgumentException 2354 */ 2355 @SystemApi requestAudioFocus(OnAudioFocusChangeListener l, @NonNull AudioAttributes requestAttributes, int durationHint, int flags)2356 public int requestAudioFocus(OnAudioFocusChangeListener l, 2357 @NonNull AudioAttributes requestAttributes, 2358 int durationHint, 2359 int flags) throws IllegalArgumentException { 2360 if (flags != (flags & AUDIOFOCUS_FLAGS_APPS)) { 2361 throw new IllegalArgumentException("Invalid flags 0x" 2362 + Integer.toHexString(flags).toUpperCase()); 2363 } 2364 return requestAudioFocus(l, requestAttributes, durationHint, 2365 flags & AUDIOFOCUS_FLAGS_APPS, 2366 null /* no AudioPolicy*/); 2367 } 2368 2369 /** 2370 * @hide 2371 * Request or lock audio focus. 2372 * This method is to be used by system components that have registered an 2373 * {@link android.media.audiopolicy.AudioPolicy} to request audio focus, but also to "lock" it 2374 * so focus granting is temporarily disabled. 2375 * @param l see the description of the same parameter in 2376 * {@link #requestAudioFocus(OnAudioFocusChangeListener, AudioAttributes, int, int)} 2377 * @param requestAttributes non null {@link AudioAttributes} describing the main reason for 2378 * requesting audio focus. 2379 * @param durationHint see the description of the same parameter in 2380 * {@link #requestAudioFocus(OnAudioFocusChangeListener, AudioAttributes, int, int)} 2381 * @param flags 0 or a combination of {link #AUDIOFOCUS_FLAG_DELAY_OK}, 2382 * {@link #AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS}, and {@link #AUDIOFOCUS_FLAG_LOCK}. 2383 * <br>Use 0 when not using any flags for the request, which behaves like 2384 * {@link #requestAudioFocus(OnAudioFocusChangeListener, int, int)}, where either audio 2385 * focus is granted immediately, or the grant request fails because the system is in a 2386 * state where focus cannot change (e.g. a phone call). 2387 * @param ap a registered {@link android.media.audiopolicy.AudioPolicy} instance when locking 2388 * focus, or null. 2389 * @return see the description of the same return value in 2390 * {@link #requestAudioFocus(OnAudioFocusChangeListener, AudioAttributes, int, int)} 2391 * @throws IllegalArgumentException 2392 */ 2393 @SystemApi requestAudioFocus(OnAudioFocusChangeListener l, @NonNull AudioAttributes requestAttributes, int durationHint, int flags, AudioPolicy ap)2394 public int requestAudioFocus(OnAudioFocusChangeListener l, 2395 @NonNull AudioAttributes requestAttributes, 2396 int durationHint, 2397 int flags, 2398 AudioPolicy ap) throws IllegalArgumentException { 2399 // parameter checking 2400 if (requestAttributes == null) { 2401 throw new IllegalArgumentException("Illegal null AudioAttributes argument"); 2402 } 2403 if ((durationHint < AUDIOFOCUS_GAIN) || 2404 (durationHint > AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE)) { 2405 throw new IllegalArgumentException("Invalid duration hint"); 2406 } 2407 if (flags != (flags & AUDIOFOCUS_FLAGS_SYSTEM)) { 2408 throw new IllegalArgumentException("Illegal flags 0x" 2409 + Integer.toHexString(flags).toUpperCase()); 2410 } 2411 if (((flags & AUDIOFOCUS_FLAG_DELAY_OK) == AUDIOFOCUS_FLAG_DELAY_OK) && (l == null)) { 2412 throw new IllegalArgumentException( 2413 "Illegal null focus listener when flagged as accepting delayed focus grant"); 2414 } 2415 if (((flags & AUDIOFOCUS_FLAG_LOCK) == AUDIOFOCUS_FLAG_LOCK) && (ap == null)) { 2416 throw new IllegalArgumentException( 2417 "Illegal null audio policy when locking audio focus"); 2418 } 2419 2420 int status = AUDIOFOCUS_REQUEST_FAILED; 2421 registerAudioFocusListener(l); 2422 IAudioService service = getService(); 2423 try { 2424 status = service.requestAudioFocus(requestAttributes, durationHint, mICallBack, 2425 mAudioFocusDispatcher, getIdForAudioFocusListener(l), 2426 getContext().getOpPackageName() /* package name */, flags, 2427 ap != null ? ap.cb() : null); 2428 } catch (RemoteException e) { 2429 throw e.rethrowFromSystemServer(); 2430 } 2431 return status; 2432 } 2433 2434 /** 2435 * @hide 2436 * Used internally by telephony package to request audio focus. Will cause the focus request 2437 * to be associated with the "voice communication" identifier only used in AudioService 2438 * to identify this use case. 2439 * @param streamType use STREAM_RING for focus requests when ringing, VOICE_CALL for 2440 * the establishment of the call 2441 * @param durationHint the type of focus request. AUDIOFOCUS_GAIN_TRANSIENT is recommended so 2442 * media applications resume after a call 2443 */ requestAudioFocusForCall(int streamType, int durationHint)2444 public void requestAudioFocusForCall(int streamType, int durationHint) { 2445 IAudioService service = getService(); 2446 try { 2447 service.requestAudioFocus(new AudioAttributes.Builder() 2448 .setInternalLegacyStreamType(streamType).build(), 2449 durationHint, mICallBack, null, 2450 AudioSystem.IN_VOICE_COMM_FOCUS_ID, 2451 getContext().getOpPackageName(), 2452 AUDIOFOCUS_FLAG_LOCK, 2453 null /* policy token */); 2454 } catch (RemoteException e) { 2455 throw e.rethrowFromSystemServer(); 2456 } 2457 } 2458 2459 /** 2460 * @hide 2461 * Used internally by telephony package to abandon audio focus, typically after a call or 2462 * when ringing ends and the call is rejected or not answered. 2463 * Should match one or more calls to {@link #requestAudioFocusForCall(int, int)}. 2464 */ abandonAudioFocusForCall()2465 public void abandonAudioFocusForCall() { 2466 IAudioService service = getService(); 2467 try { 2468 service.abandonAudioFocus(null, AudioSystem.IN_VOICE_COMM_FOCUS_ID, 2469 null /*AudioAttributes, legacy behavior*/); 2470 } catch (RemoteException e) { 2471 throw e.rethrowFromSystemServer(); 2472 } 2473 } 2474 2475 /** 2476 * Abandon audio focus. Causes the previous focus owner, if any, to receive focus. 2477 * @param l the listener with which focus was requested. 2478 * @return {@link #AUDIOFOCUS_REQUEST_FAILED} or {@link #AUDIOFOCUS_REQUEST_GRANTED} 2479 */ abandonAudioFocus(OnAudioFocusChangeListener l)2480 public int abandonAudioFocus(OnAudioFocusChangeListener l) { 2481 return abandonAudioFocus(l, null /*AudioAttributes, legacy behavior*/); 2482 } 2483 2484 /** 2485 * @hide 2486 * Abandon audio focus. Causes the previous focus owner, if any, to receive focus. 2487 * @param l the listener with which focus was requested. 2488 * @param aa the {@link AudioAttributes} with which audio focus was requested 2489 * @return {@link #AUDIOFOCUS_REQUEST_FAILED} or {@link #AUDIOFOCUS_REQUEST_GRANTED} 2490 */ 2491 @SystemApi abandonAudioFocus(OnAudioFocusChangeListener l, AudioAttributes aa)2492 public int abandonAudioFocus(OnAudioFocusChangeListener l, AudioAttributes aa) { 2493 int status = AUDIOFOCUS_REQUEST_FAILED; 2494 unregisterAudioFocusListener(l); 2495 IAudioService service = getService(); 2496 try { 2497 status = service.abandonAudioFocus(mAudioFocusDispatcher, 2498 getIdForAudioFocusListener(l), aa); 2499 } catch (RemoteException e) { 2500 throw e.rethrowFromSystemServer(); 2501 } 2502 return status; 2503 } 2504 2505 //==================================================================== 2506 // Remote Control 2507 /** 2508 * Register a component to be the sole receiver of MEDIA_BUTTON intents. 2509 * @param eventReceiver identifier of a {@link android.content.BroadcastReceiver} 2510 * that will receive the media button intent. This broadcast receiver must be declared 2511 * in the application manifest. The package of the component must match that of 2512 * the context you're registering from. 2513 * @deprecated Use {@link MediaSession#setMediaButtonReceiver(PendingIntent)} instead. 2514 */ 2515 @Deprecated registerMediaButtonEventReceiver(ComponentName eventReceiver)2516 public void registerMediaButtonEventReceiver(ComponentName eventReceiver) { 2517 if (eventReceiver == null) { 2518 return; 2519 } 2520 if (!eventReceiver.getPackageName().equals(getContext().getPackageName())) { 2521 Log.e(TAG, "registerMediaButtonEventReceiver() error: " + 2522 "receiver and context package names don't match"); 2523 return; 2524 } 2525 // construct a PendingIntent for the media button and register it 2526 Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON); 2527 // the associated intent will be handled by the component being registered 2528 mediaButtonIntent.setComponent(eventReceiver); 2529 PendingIntent pi = PendingIntent.getBroadcast(getContext(), 2530 0/*requestCode, ignored*/, mediaButtonIntent, 0/*flags*/); 2531 registerMediaButtonIntent(pi, eventReceiver); 2532 } 2533 2534 /** 2535 * Register a component to be the sole receiver of MEDIA_BUTTON intents. This is like 2536 * {@link #registerMediaButtonEventReceiver(android.content.ComponentName)}, but allows 2537 * the buttons to go to any PendingIntent. Note that you should only use this form if 2538 * you know you will continue running for the full time until unregistering the 2539 * PendingIntent. 2540 * @param eventReceiver target that will receive media button intents. The PendingIntent 2541 * will be sent an {@link Intent#ACTION_MEDIA_BUTTON} event when a media button action 2542 * occurs, with {@link Intent#EXTRA_KEY_EVENT} added and holding the key code of the 2543 * media button that was pressed. 2544 * @deprecated Use {@link MediaSession#setMediaButtonReceiver(PendingIntent)} instead. 2545 */ 2546 @Deprecated registerMediaButtonEventReceiver(PendingIntent eventReceiver)2547 public void registerMediaButtonEventReceiver(PendingIntent eventReceiver) { 2548 if (eventReceiver == null) { 2549 return; 2550 } 2551 registerMediaButtonIntent(eventReceiver, null); 2552 } 2553 2554 /** 2555 * @hide 2556 * no-op if (pi == null) or (eventReceiver == null) 2557 */ registerMediaButtonIntent(PendingIntent pi, ComponentName eventReceiver)2558 public void registerMediaButtonIntent(PendingIntent pi, ComponentName eventReceiver) { 2559 if (pi == null) { 2560 Log.e(TAG, "Cannot call registerMediaButtonIntent() with a null parameter"); 2561 return; 2562 } 2563 MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(getContext()); 2564 helper.addMediaButtonListener(pi, eventReceiver, getContext()); 2565 } 2566 2567 /** 2568 * Unregister the receiver of MEDIA_BUTTON intents. 2569 * @param eventReceiver identifier of a {@link android.content.BroadcastReceiver} 2570 * that was registered with {@link #registerMediaButtonEventReceiver(ComponentName)}. 2571 * @deprecated Use {@link MediaSession} instead. 2572 */ 2573 @Deprecated unregisterMediaButtonEventReceiver(ComponentName eventReceiver)2574 public void unregisterMediaButtonEventReceiver(ComponentName eventReceiver) { 2575 if (eventReceiver == null) { 2576 return; 2577 } 2578 // construct a PendingIntent for the media button and unregister it 2579 Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON); 2580 // the associated intent will be handled by the component being registered 2581 mediaButtonIntent.setComponent(eventReceiver); 2582 PendingIntent pi = PendingIntent.getBroadcast(getContext(), 2583 0/*requestCode, ignored*/, mediaButtonIntent, 0/*flags*/); 2584 unregisterMediaButtonIntent(pi); 2585 } 2586 2587 /** 2588 * Unregister the receiver of MEDIA_BUTTON intents. 2589 * @param eventReceiver same PendingIntent that was registed with 2590 * {@link #registerMediaButtonEventReceiver(PendingIntent)}. 2591 * @deprecated Use {@link MediaSession} instead. 2592 */ 2593 @Deprecated unregisterMediaButtonEventReceiver(PendingIntent eventReceiver)2594 public void unregisterMediaButtonEventReceiver(PendingIntent eventReceiver) { 2595 if (eventReceiver == null) { 2596 return; 2597 } 2598 unregisterMediaButtonIntent(eventReceiver); 2599 } 2600 2601 /** 2602 * @hide 2603 */ unregisterMediaButtonIntent(PendingIntent pi)2604 public void unregisterMediaButtonIntent(PendingIntent pi) { 2605 MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(getContext()); 2606 helper.removeMediaButtonListener(pi); 2607 } 2608 2609 /** 2610 * Registers the remote control client for providing information to display on the remote 2611 * controls. 2612 * @param rcClient The remote control client from which remote controls will receive 2613 * information to display. 2614 * @see RemoteControlClient 2615 * @deprecated Use {@link MediaSession} instead. 2616 */ 2617 @Deprecated registerRemoteControlClient(RemoteControlClient rcClient)2618 public void registerRemoteControlClient(RemoteControlClient rcClient) { 2619 if ((rcClient == null) || (rcClient.getRcMediaIntent() == null)) { 2620 return; 2621 } 2622 rcClient.registerWithSession(MediaSessionLegacyHelper.getHelper(getContext())); 2623 } 2624 2625 /** 2626 * Unregisters the remote control client that was providing information to display on the 2627 * remote controls. 2628 * @param rcClient The remote control client to unregister. 2629 * @see #registerRemoteControlClient(RemoteControlClient) 2630 * @deprecated Use {@link MediaSession} instead. 2631 */ 2632 @Deprecated unregisterRemoteControlClient(RemoteControlClient rcClient)2633 public void unregisterRemoteControlClient(RemoteControlClient rcClient) { 2634 if ((rcClient == null) || (rcClient.getRcMediaIntent() == null)) { 2635 return; 2636 } 2637 rcClient.unregisterWithSession(MediaSessionLegacyHelper.getHelper(getContext())); 2638 } 2639 2640 /** 2641 * Registers a {@link RemoteController} instance for it to receive media 2642 * metadata updates and playback state information from applications using 2643 * {@link RemoteControlClient}, and control their playback. 2644 * <p> 2645 * Registration requires the {@link RemoteController.OnClientUpdateListener} listener to be 2646 * one of the enabled notification listeners (see 2647 * {@link android.service.notification.NotificationListenerService}). 2648 * 2649 * @param rctlr the object to register. 2650 * @return true if the {@link RemoteController} was successfully registered, 2651 * false if an error occurred, due to an internal system error, or 2652 * insufficient permissions. 2653 * @deprecated Use 2654 * {@link MediaSessionManager#addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, ComponentName)} 2655 * and {@link MediaController} instead. 2656 */ 2657 @Deprecated registerRemoteController(RemoteController rctlr)2658 public boolean registerRemoteController(RemoteController rctlr) { 2659 if (rctlr == null) { 2660 return false; 2661 } 2662 rctlr.startListeningToSessions(); 2663 return true; 2664 } 2665 2666 /** 2667 * Unregisters a {@link RemoteController}, causing it to no longer receive 2668 * media metadata and playback state information, and no longer be capable 2669 * of controlling playback. 2670 * 2671 * @param rctlr the object to unregister. 2672 * @deprecated Use 2673 * {@link MediaSessionManager#removeOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener)} 2674 * instead. 2675 */ 2676 @Deprecated unregisterRemoteController(RemoteController rctlr)2677 public void unregisterRemoteController(RemoteController rctlr) { 2678 if (rctlr == null) { 2679 return; 2680 } 2681 rctlr.stopListeningToSessions(); 2682 } 2683 2684 2685 //==================================================================== 2686 // Audio policy 2687 /** 2688 * @hide 2689 * Register the given {@link AudioPolicy}. 2690 * This call is synchronous and blocks until the registration process successfully completed 2691 * or failed to complete. 2692 * @param policy the non-null {@link AudioPolicy} to register. 2693 * @return {@link #ERROR} if there was an error communicating with the registration service 2694 * or if the user doesn't have the required 2695 * {@link android.Manifest.permission#MODIFY_AUDIO_ROUTING} permission, 2696 * {@link #SUCCESS} otherwise. 2697 */ 2698 @SystemApi registerAudioPolicy(@onNull AudioPolicy policy)2699 public int registerAudioPolicy(@NonNull AudioPolicy policy) { 2700 if (policy == null) { 2701 throw new IllegalArgumentException("Illegal null AudioPolicy argument"); 2702 } 2703 IAudioService service = getService(); 2704 try { 2705 String regId = service.registerAudioPolicy(policy.getConfig(), policy.cb(), 2706 policy.hasFocusListener()); 2707 if (regId == null) { 2708 return ERROR; 2709 } else { 2710 policy.setRegistration(regId); 2711 } 2712 // successful registration 2713 } catch (RemoteException e) { 2714 throw e.rethrowFromSystemServer(); 2715 } 2716 return SUCCESS; 2717 } 2718 2719 /** 2720 * @hide 2721 * @param policy the non-null {@link AudioPolicy} to unregister. 2722 */ 2723 @SystemApi unregisterAudioPolicyAsync(@onNull AudioPolicy policy)2724 public void unregisterAudioPolicyAsync(@NonNull AudioPolicy policy) { 2725 if (policy == null) { 2726 throw new IllegalArgumentException("Illegal null AudioPolicy argument"); 2727 } 2728 IAudioService service = getService(); 2729 try { 2730 service.unregisterAudioPolicyAsync(policy.cb()); 2731 policy.setRegistration(null); 2732 } catch (RemoteException e) { 2733 throw e.rethrowFromSystemServer(); 2734 } 2735 } 2736 2737 2738 //==================================================================== 2739 // Recording configuration 2740 /** 2741 * Interface for receiving update notifications about the recording configuration. Extend 2742 * this abstract class and register it with 2743 * {@link AudioManager#registerAudioRecordingCallback(AudioRecordingCallback, Handler)} 2744 * to be notified. 2745 * Use {@link AudioManager#getActiveRecordingConfigurations()} to query the current 2746 * configuration. 2747 */ 2748 public static abstract class AudioRecordingCallback { 2749 /** 2750 * Called whenever the device recording configuration has changed. 2751 * @param configs list containing the results of 2752 * {@link AudioManager#getActiveRecordingConfigurations()}. 2753 */ onRecordingConfigChanged(List<AudioRecordingConfiguration> configs)2754 public void onRecordingConfigChanged(List<AudioRecordingConfiguration> configs) {} 2755 } 2756 2757 private static class AudioRecordingCallbackInfo { 2758 final AudioRecordingCallback mCb; 2759 final Handler mHandler; AudioRecordingCallbackInfo(AudioRecordingCallback cb, Handler handler)2760 AudioRecordingCallbackInfo(AudioRecordingCallback cb, Handler handler) { 2761 mCb = cb; 2762 mHandler = handler; 2763 } 2764 } 2765 2766 private final static class RecordConfigChangeCallbackData { 2767 final AudioRecordingCallback mCb; 2768 final List<AudioRecordingConfiguration> mConfigs; 2769 RecordConfigChangeCallbackData(AudioRecordingCallback cb, List<AudioRecordingConfiguration> configs)2770 RecordConfigChangeCallbackData(AudioRecordingCallback cb, 2771 List<AudioRecordingConfiguration> configs) { 2772 mCb = cb; 2773 mConfigs = configs; 2774 } 2775 } 2776 2777 /** 2778 * Register a callback to be notified of audio recording changes through 2779 * {@link AudioRecordingCallback} 2780 * @param cb non-null callback to register 2781 * @param handler the {@link Handler} object for the thread on which to execute 2782 * the callback. If <code>null</code>, the {@link Handler} associated with the main 2783 * {@link Looper} will be used. 2784 */ registerAudioRecordingCallback(@onNull AudioRecordingCallback cb, Handler handler)2785 public void registerAudioRecordingCallback(@NonNull AudioRecordingCallback cb, Handler handler) 2786 { 2787 if (cb == null) { 2788 throw new IllegalArgumentException("Illegal null AudioRecordingCallback argument"); 2789 } 2790 2791 synchronized(mRecordCallbackLock) { 2792 // lazy initialization of the list of recording callbacks 2793 if (mRecordCallbackList == null) { 2794 mRecordCallbackList = new ArrayList<AudioRecordingCallbackInfo>(); 2795 } 2796 final int oldCbCount = mRecordCallbackList.size(); 2797 if (!hasRecordCallback_sync(cb)) { 2798 mRecordCallbackList.add(new AudioRecordingCallbackInfo(cb, 2799 new ServiceEventHandlerDelegate(handler).getHandler())); 2800 final int newCbCount = mRecordCallbackList.size(); 2801 if ((oldCbCount == 0) && (newCbCount > 0)) { 2802 // register binder for callbacks 2803 final IAudioService service = getService(); 2804 try { 2805 service.registerRecordingCallback(mRecCb); 2806 } catch (RemoteException e) { 2807 throw e.rethrowFromSystemServer(); 2808 } 2809 } 2810 } else { 2811 Log.w(TAG, "attempt to call registerAudioRecordingCallback() on a previously" 2812 + "registered callback"); 2813 } 2814 } 2815 } 2816 2817 /** 2818 * Unregister an audio recording callback previously registered with 2819 * {@link #registerAudioRecordingCallback(AudioRecordingCallback, Handler)}. 2820 * @param cb non-null callback to unregister 2821 */ unregisterAudioRecordingCallback(@onNull AudioRecordingCallback cb)2822 public void unregisterAudioRecordingCallback(@NonNull AudioRecordingCallback cb) { 2823 if (cb == null) { 2824 throw new IllegalArgumentException("Illegal null AudioRecordingCallback argument"); 2825 } 2826 synchronized(mRecordCallbackLock) { 2827 if (mRecordCallbackList == null) { 2828 return; 2829 } 2830 final int oldCbCount = mRecordCallbackList.size(); 2831 if (removeRecordCallback_sync(cb)) { 2832 final int newCbCount = mRecordCallbackList.size(); 2833 if ((oldCbCount > 0) && (newCbCount == 0)) { 2834 // unregister binder for callbacks 2835 final IAudioService service = getService(); 2836 try { 2837 service.unregisterRecordingCallback(mRecCb); 2838 } catch (RemoteException e) { 2839 throw e.rethrowFromSystemServer(); 2840 } 2841 } 2842 } else { 2843 Log.w(TAG, "attempt to call unregisterAudioRecordingCallback() on a callback" 2844 + " already unregistered or never registered"); 2845 } 2846 } 2847 } 2848 2849 /** 2850 * Returns the current active audio recording configurations of the device. 2851 * @return a non-null list of recording configurations. An empty list indicates there is 2852 * no recording active when queried. 2853 */ getActiveRecordingConfigurations()2854 public @NonNull List<AudioRecordingConfiguration> getActiveRecordingConfigurations() { 2855 final IAudioService service = getService(); 2856 try { 2857 return service.getActiveRecordingConfigurations(); 2858 } catch (RemoteException e) { 2859 throw e.rethrowFromSystemServer(); 2860 } 2861 } 2862 2863 /** 2864 * constants for the recording events, to keep in sync 2865 * with frameworks/av/include/media/AudioPolicy.h 2866 */ 2867 /** @hide */ 2868 public final static int RECORD_CONFIG_EVENT_START = 1; 2869 /** @hide */ 2870 public final static int RECORD_CONFIG_EVENT_STOP = 0; 2871 2872 /** 2873 * All operations on this list are sync'd on mRecordCallbackLock. 2874 * List is lazy-initialized in 2875 * {@link #registerAudioRecordingCallback(AudioRecordingCallback, Handler)}. 2876 * List can be null. 2877 */ 2878 private List<AudioRecordingCallbackInfo> mRecordCallbackList; 2879 private final Object mRecordCallbackLock = new Object(); 2880 2881 /** 2882 * Must be called synchronized on mRecordCallbackLock 2883 */ hasRecordCallback_sync(@onNull AudioRecordingCallback cb)2884 private boolean hasRecordCallback_sync(@NonNull AudioRecordingCallback cb) { 2885 if (mRecordCallbackList != null) { 2886 for (int i=0 ; i < mRecordCallbackList.size() ; i++) { 2887 if (cb.equals(mRecordCallbackList.get(i).mCb)) { 2888 return true; 2889 } 2890 } 2891 } 2892 return false; 2893 } 2894 2895 /** 2896 * Must be called synchronized on mRecordCallbackLock 2897 */ removeRecordCallback_sync(@onNull AudioRecordingCallback cb)2898 private boolean removeRecordCallback_sync(@NonNull AudioRecordingCallback cb) { 2899 if (mRecordCallbackList != null) { 2900 for (int i=0 ; i < mRecordCallbackList.size() ; i++) { 2901 if (cb.equals(mRecordCallbackList.get(i).mCb)) { 2902 mRecordCallbackList.remove(i); 2903 return true; 2904 } 2905 } 2906 } 2907 return false; 2908 } 2909 2910 private final IRecordingConfigDispatcher mRecCb = new IRecordingConfigDispatcher.Stub() { 2911 2912 public void dispatchRecordingConfigChange(List<AudioRecordingConfiguration> configs) { 2913 synchronized(mRecordCallbackLock) { 2914 if (mRecordCallbackList != null) { 2915 for (int i=0 ; i < mRecordCallbackList.size() ; i++) { 2916 final AudioRecordingCallbackInfo arci = mRecordCallbackList.get(i); 2917 if (arci.mHandler != null) { 2918 final Message m = arci.mHandler.obtainMessage( 2919 MSSG_RECORDING_CONFIG_CHANGE/*what*/, 2920 new RecordConfigChangeCallbackData(arci.mCb, configs)/*obj*/); 2921 arci.mHandler.sendMessage(m); 2922 } 2923 } 2924 } 2925 } 2926 } 2927 2928 }; 2929 2930 //===================================================================== 2931 2932 /** 2933 * @hide 2934 * Reload audio settings. This method is called by Settings backup 2935 * agent when audio settings are restored and causes the AudioService 2936 * to read and apply restored settings. 2937 */ reloadAudioSettings()2938 public void reloadAudioSettings() { 2939 IAudioService service = getService(); 2940 try { 2941 service.reloadAudioSettings(); 2942 } catch (RemoteException e) { 2943 throw e.rethrowFromSystemServer(); 2944 } 2945 } 2946 2947 /** 2948 * @hide 2949 * Notifies AudioService that it is connected to an A2DP device that supports absolute volume, 2950 * so that AudioService can send volume change events to the A2DP device, rather than handling 2951 * them. 2952 */ avrcpSupportsAbsoluteVolume(String address, boolean support)2953 public void avrcpSupportsAbsoluteVolume(String address, boolean support) { 2954 IAudioService service = getService(); 2955 try { 2956 service.avrcpSupportsAbsoluteVolume(address, support); 2957 } catch (RemoteException e) { 2958 throw e.rethrowFromSystemServer(); 2959 } 2960 } 2961 2962 /** 2963 * {@hide} 2964 */ 2965 private final IBinder mICallBack = new Binder(); 2966 2967 /** 2968 * Checks whether the phone is in silent mode, with or without vibrate. 2969 * 2970 * @return true if phone is in silent mode, with or without vibrate. 2971 * 2972 * @see #getRingerMode() 2973 * 2974 * @hide pending API Council approval 2975 */ isSilentMode()2976 public boolean isSilentMode() { 2977 int ringerMode = getRingerMode(); 2978 boolean silentMode = 2979 (ringerMode == RINGER_MODE_SILENT) || 2980 (ringerMode == RINGER_MODE_VIBRATE); 2981 return silentMode; 2982 } 2983 2984 // This section re-defines new output device constants from AudioSystem, because the AudioSystem 2985 // class is not used by other parts of the framework, which instead use definitions and methods 2986 // from AudioManager. AudioSystem is an internal class used by AudioManager and AudioService. 2987 2988 /** @hide 2989 * The audio device code for representing "no device." */ 2990 public static final int DEVICE_NONE = AudioSystem.DEVICE_NONE; 2991 /** @hide 2992 * The audio output device code for the small speaker at the front of the device used 2993 * when placing calls. Does not refer to an in-ear headphone without attached microphone, 2994 * such as earbuds, earphones, or in-ear monitors (IEM). Those would be handled as a 2995 * {@link #DEVICE_OUT_WIRED_HEADPHONE}. 2996 */ 2997 public static final int DEVICE_OUT_EARPIECE = AudioSystem.DEVICE_OUT_EARPIECE; 2998 /** @hide 2999 * The audio output device code for the built-in speaker */ 3000 public static final int DEVICE_OUT_SPEAKER = AudioSystem.DEVICE_OUT_SPEAKER; 3001 /** @hide 3002 * The audio output device code for a wired headset with attached microphone */ 3003 public static final int DEVICE_OUT_WIRED_HEADSET = AudioSystem.DEVICE_OUT_WIRED_HEADSET; 3004 /** @hide 3005 * The audio output device code for a wired headphone without attached microphone */ 3006 public static final int DEVICE_OUT_WIRED_HEADPHONE = AudioSystem.DEVICE_OUT_WIRED_HEADPHONE; 3007 /** @hide 3008 * The audio output device code for generic Bluetooth SCO, for voice */ 3009 public static final int DEVICE_OUT_BLUETOOTH_SCO = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO; 3010 /** @hide 3011 * The audio output device code for Bluetooth SCO Headset Profile (HSP) and 3012 * Hands-Free Profile (HFP), for voice 3013 */ 3014 public static final int DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 3015 AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET; 3016 /** @hide 3017 * The audio output device code for Bluetooth SCO car audio, for voice */ 3018 public static final int DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 3019 AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT; 3020 /** @hide 3021 * The audio output device code for generic Bluetooth A2DP, for music */ 3022 public static final int DEVICE_OUT_BLUETOOTH_A2DP = AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP; 3023 /** @hide 3024 * The audio output device code for Bluetooth A2DP headphones, for music */ 3025 public static final int DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 3026 AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES; 3027 /** @hide 3028 * The audio output device code for Bluetooth A2DP external speaker, for music */ 3029 public static final int DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 3030 AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER; 3031 /** @hide 3032 * The audio output device code for S/PDIF (legacy) or HDMI 3033 * Deprecated: replaced by {@link #DEVICE_OUT_HDMI} */ 3034 public static final int DEVICE_OUT_AUX_DIGITAL = AudioSystem.DEVICE_OUT_AUX_DIGITAL; 3035 /** @hide 3036 * The audio output device code for HDMI */ 3037 public static final int DEVICE_OUT_HDMI = AudioSystem.DEVICE_OUT_HDMI; 3038 /** @hide 3039 * The audio output device code for an analog wired headset attached via a 3040 * docking station 3041 */ 3042 public static final int DEVICE_OUT_ANLG_DOCK_HEADSET = AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET; 3043 /** @hide 3044 * The audio output device code for a digital wired headset attached via a 3045 * docking station 3046 */ 3047 public static final int DEVICE_OUT_DGTL_DOCK_HEADSET = AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET; 3048 /** @hide 3049 * The audio output device code for a USB audio accessory. The accessory is in USB host 3050 * mode and the Android device in USB device mode 3051 */ 3052 public static final int DEVICE_OUT_USB_ACCESSORY = AudioSystem.DEVICE_OUT_USB_ACCESSORY; 3053 /** @hide 3054 * The audio output device code for a USB audio device. The device is in USB device 3055 * mode and the Android device in USB host mode 3056 */ 3057 public static final int DEVICE_OUT_USB_DEVICE = AudioSystem.DEVICE_OUT_USB_DEVICE; 3058 /** @hide 3059 * The audio output device code for projection output. 3060 */ 3061 public static final int DEVICE_OUT_REMOTE_SUBMIX = AudioSystem.DEVICE_OUT_REMOTE_SUBMIX; 3062 /** @hide 3063 * The audio output device code the telephony voice TX path. 3064 */ 3065 public static final int DEVICE_OUT_TELEPHONY_TX = AudioSystem.DEVICE_OUT_TELEPHONY_TX; 3066 /** @hide 3067 * The audio output device code for an analog jack with line impedance detected. 3068 */ 3069 public static final int DEVICE_OUT_LINE = AudioSystem.DEVICE_OUT_LINE; 3070 /** @hide 3071 * The audio output device code for HDMI Audio Return Channel. 3072 */ 3073 public static final int DEVICE_OUT_HDMI_ARC = AudioSystem.DEVICE_OUT_HDMI_ARC; 3074 /** @hide 3075 * The audio output device code for S/PDIF digital connection. 3076 */ 3077 public static final int DEVICE_OUT_SPDIF = AudioSystem.DEVICE_OUT_SPDIF; 3078 /** @hide 3079 * The audio output device code for built-in FM transmitter. 3080 */ 3081 public static final int DEVICE_OUT_FM = AudioSystem.DEVICE_OUT_FM; 3082 /** @hide 3083 * This is not used as a returned value from {@link #getDevicesForStream}, but could be 3084 * used in the future in a set method to select whatever default device is chosen by the 3085 * platform-specific implementation. 3086 */ 3087 public static final int DEVICE_OUT_DEFAULT = AudioSystem.DEVICE_OUT_DEFAULT; 3088 3089 /** @hide 3090 * The audio input device code for default built-in microphone 3091 */ 3092 public static final int DEVICE_IN_BUILTIN_MIC = AudioSystem.DEVICE_IN_BUILTIN_MIC; 3093 /** @hide 3094 * The audio input device code for a Bluetooth SCO headset 3095 */ 3096 public static final int DEVICE_IN_BLUETOOTH_SCO_HEADSET = 3097 AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET; 3098 /** @hide 3099 * The audio input device code for wired headset microphone 3100 */ 3101 public static final int DEVICE_IN_WIRED_HEADSET = 3102 AudioSystem.DEVICE_IN_WIRED_HEADSET; 3103 /** @hide 3104 * The audio input device code for HDMI 3105 */ 3106 public static final int DEVICE_IN_HDMI = 3107 AudioSystem.DEVICE_IN_HDMI; 3108 /** @hide 3109 * The audio input device code for telephony voice RX path 3110 */ 3111 public static final int DEVICE_IN_TELEPHONY_RX = 3112 AudioSystem.DEVICE_IN_TELEPHONY_RX; 3113 /** @hide 3114 * The audio input device code for built-in microphone pointing to the back 3115 */ 3116 public static final int DEVICE_IN_BACK_MIC = 3117 AudioSystem.DEVICE_IN_BACK_MIC; 3118 /** @hide 3119 * The audio input device code for analog from a docking station 3120 */ 3121 public static final int DEVICE_IN_ANLG_DOCK_HEADSET = 3122 AudioSystem.DEVICE_IN_ANLG_DOCK_HEADSET; 3123 /** @hide 3124 * The audio input device code for digital from a docking station 3125 */ 3126 public static final int DEVICE_IN_DGTL_DOCK_HEADSET = 3127 AudioSystem.DEVICE_IN_DGTL_DOCK_HEADSET; 3128 /** @hide 3129 * The audio input device code for a USB audio accessory. The accessory is in USB host 3130 * mode and the Android device in USB device mode 3131 */ 3132 public static final int DEVICE_IN_USB_ACCESSORY = 3133 AudioSystem.DEVICE_IN_USB_ACCESSORY; 3134 /** @hide 3135 * The audio input device code for a USB audio device. The device is in USB device 3136 * mode and the Android device in USB host mode 3137 */ 3138 public static final int DEVICE_IN_USB_DEVICE = 3139 AudioSystem.DEVICE_IN_USB_DEVICE; 3140 /** @hide 3141 * The audio input device code for a FM radio tuner 3142 */ 3143 public static final int DEVICE_IN_FM_TUNER = AudioSystem.DEVICE_IN_FM_TUNER; 3144 /** @hide 3145 * The audio input device code for a TV tuner 3146 */ 3147 public static final int DEVICE_IN_TV_TUNER = AudioSystem.DEVICE_IN_TV_TUNER; 3148 /** @hide 3149 * The audio input device code for an analog jack with line impedance detected 3150 */ 3151 public static final int DEVICE_IN_LINE = AudioSystem.DEVICE_IN_LINE; 3152 /** @hide 3153 * The audio input device code for a S/PDIF digital connection 3154 */ 3155 public static final int DEVICE_IN_SPDIF = AudioSystem.DEVICE_IN_SPDIF; 3156 /** @hide 3157 * The audio input device code for audio loopback 3158 */ 3159 public static final int DEVICE_IN_LOOPBACK = AudioSystem.DEVICE_IN_LOOPBACK; 3160 3161 /** 3162 * Return true if the device code corresponds to an output device. 3163 * @hide 3164 */ isOutputDevice(int device)3165 public static boolean isOutputDevice(int device) 3166 { 3167 return (device & AudioSystem.DEVICE_BIT_IN) == 0; 3168 } 3169 3170 /** 3171 * Return true if the device code corresponds to an input device. 3172 * @hide 3173 */ isInputDevice(int device)3174 public static boolean isInputDevice(int device) 3175 { 3176 return (device & AudioSystem.DEVICE_BIT_IN) == AudioSystem.DEVICE_BIT_IN; 3177 } 3178 3179 3180 /** 3181 * Return the enabled devices for the specified output stream type. 3182 * 3183 * @param streamType The stream type to query. One of 3184 * {@link #STREAM_VOICE_CALL}, 3185 * {@link #STREAM_SYSTEM}, 3186 * {@link #STREAM_RING}, 3187 * {@link #STREAM_MUSIC}, 3188 * {@link #STREAM_ALARM}, 3189 * {@link #STREAM_NOTIFICATION}, 3190 * {@link #STREAM_DTMF}. 3191 * 3192 * @return The bit-mask "or" of audio output device codes for all enabled devices on this 3193 * stream. Zero or more of 3194 * {@link #DEVICE_OUT_EARPIECE}, 3195 * {@link #DEVICE_OUT_SPEAKER}, 3196 * {@link #DEVICE_OUT_WIRED_HEADSET}, 3197 * {@link #DEVICE_OUT_WIRED_HEADPHONE}, 3198 * {@link #DEVICE_OUT_BLUETOOTH_SCO}, 3199 * {@link #DEVICE_OUT_BLUETOOTH_SCO_HEADSET}, 3200 * {@link #DEVICE_OUT_BLUETOOTH_SCO_CARKIT}, 3201 * {@link #DEVICE_OUT_BLUETOOTH_A2DP}, 3202 * {@link #DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES}, 3203 * {@link #DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER}, 3204 * {@link #DEVICE_OUT_HDMI}, 3205 * {@link #DEVICE_OUT_ANLG_DOCK_HEADSET}, 3206 * {@link #DEVICE_OUT_DGTL_DOCK_HEADSET}. 3207 * {@link #DEVICE_OUT_USB_ACCESSORY}. 3208 * {@link #DEVICE_OUT_USB_DEVICE}. 3209 * {@link #DEVICE_OUT_REMOTE_SUBMIX}. 3210 * {@link #DEVICE_OUT_TELEPHONY_TX}. 3211 * {@link #DEVICE_OUT_LINE}. 3212 * {@link #DEVICE_OUT_HDMI_ARC}. 3213 * {@link #DEVICE_OUT_SPDIF}. 3214 * {@link #DEVICE_OUT_FM}. 3215 * {@link #DEVICE_OUT_DEFAULT} is not used here. 3216 * 3217 * The implementation may support additional device codes beyond those listed, so 3218 * the application should ignore any bits which it does not recognize. 3219 * Note that the information may be imprecise when the implementation 3220 * cannot distinguish whether a particular device is enabled. 3221 * 3222 * {@hide} 3223 */ getDevicesForStream(int streamType)3224 public int getDevicesForStream(int streamType) { 3225 switch (streamType) { 3226 case STREAM_VOICE_CALL: 3227 case STREAM_SYSTEM: 3228 case STREAM_RING: 3229 case STREAM_MUSIC: 3230 case STREAM_ALARM: 3231 case STREAM_NOTIFICATION: 3232 case STREAM_DTMF: 3233 return AudioSystem.getDevicesForStream(streamType); 3234 default: 3235 return 0; 3236 } 3237 } 3238 3239 /** 3240 * Indicate wired accessory connection state change. 3241 * @param device type of device connected/disconnected (AudioManager.DEVICE_OUT_xxx) 3242 * @param state new connection state: 1 connected, 0 disconnected 3243 * @param name device name 3244 * {@hide} 3245 */ setWiredDeviceConnectionState(int type, int state, String address, String name)3246 public void setWiredDeviceConnectionState(int type, int state, String address, String name) { 3247 IAudioService service = getService(); 3248 try { 3249 service.setWiredDeviceConnectionState(type, state, address, name, 3250 mApplicationContext.getOpPackageName()); 3251 } catch (RemoteException e) { 3252 throw e.rethrowFromSystemServer(); 3253 } 3254 } 3255 3256 /** 3257 * Indicate A2DP source or sink connection state change. 3258 * @param device Bluetooth device connected/disconnected 3259 * @param state new connection state (BluetoothProfile.STATE_xxx) 3260 * @param profile profile for the A2DP device 3261 * (either {@link android.bluetooth.BluetoothProfile.A2DP} or 3262 * {@link android.bluetooth.BluetoothProfile.A2DP_SINK}) 3263 * @return a delay in ms that the caller should wait before broadcasting 3264 * BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED intent. 3265 * {@hide} 3266 */ setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state, int profile)3267 public int setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state, 3268 int profile) { 3269 IAudioService service = getService(); 3270 int delay = 0; 3271 try { 3272 delay = service.setBluetoothA2dpDeviceConnectionState(device, state, profile); 3273 } catch (RemoteException e) { 3274 throw e.rethrowFromSystemServer(); 3275 } 3276 return delay; 3277 } 3278 3279 /** {@hide} */ getRingtonePlayer()3280 public IRingtonePlayer getRingtonePlayer() { 3281 try { 3282 return getService().getRingtonePlayer(); 3283 } catch (RemoteException e) { 3284 throw e.rethrowFromSystemServer(); 3285 } 3286 } 3287 3288 /** 3289 * Used as a key for {@link #getProperty} to request the native or optimal output sample rate 3290 * for this device's primary output stream, in decimal Hz. 3291 */ 3292 // FIXME Deprecate 3293 public static final String PROPERTY_OUTPUT_SAMPLE_RATE = 3294 "android.media.property.OUTPUT_SAMPLE_RATE"; 3295 3296 /** 3297 * Used as a key for {@link #getProperty} to request the native or optimal output buffer size 3298 * for this device's primary output stream, in decimal PCM frames. 3299 */ 3300 // FIXME Deprecate 3301 public static final String PROPERTY_OUTPUT_FRAMES_PER_BUFFER = 3302 "android.media.property.OUTPUT_FRAMES_PER_BUFFER"; 3303 3304 /** 3305 * Used as a key for {@link #getProperty} to determine if the default microphone audio source 3306 * supports near-ultrasound frequencies (range of 18 - 21 kHz). 3307 */ 3308 public static final String PROPERTY_SUPPORT_MIC_NEAR_ULTRASOUND = 3309 "android.media.property.SUPPORT_MIC_NEAR_ULTRASOUND"; 3310 3311 /** 3312 * Used as a key for {@link #getProperty} to determine if the default speaker audio path 3313 * supports near-ultrasound frequencies (range of 18 - 21 kHz). 3314 */ 3315 public static final String PROPERTY_SUPPORT_SPEAKER_NEAR_ULTRASOUND = 3316 "android.media.property.SUPPORT_SPEAKER_NEAR_ULTRASOUND"; 3317 3318 /** 3319 * Used as a key for {@link #getProperty} to determine if the unprocessed audio source is 3320 * available and supported with the expected frequency range and level response. 3321 */ 3322 public static final String PROPERTY_SUPPORT_AUDIO_SOURCE_UNPROCESSED = 3323 "android.media.property.SUPPORT_AUDIO_SOURCE_UNPROCESSED"; 3324 /** 3325 * Returns the value of the property with the specified key. 3326 * @param key One of the strings corresponding to a property key: either 3327 * {@link #PROPERTY_OUTPUT_SAMPLE_RATE}, 3328 * {@link #PROPERTY_OUTPUT_FRAMES_PER_BUFFER}, 3329 * {@link #PROPERTY_SUPPORT_MIC_NEAR_ULTRASOUND}, 3330 * {@link #PROPERTY_SUPPORT_SPEAKER_NEAR_ULTRASOUND}, or 3331 * {@link #PROPERTY_SUPPORT_AUDIO_SOURCE_UNPROCESSED}. 3332 * @return A string representing the associated value for that property key, 3333 * or null if there is no value for that key. 3334 */ getProperty(String key)3335 public String getProperty(String key) { 3336 if (PROPERTY_OUTPUT_SAMPLE_RATE.equals(key)) { 3337 int outputSampleRate = AudioSystem.getPrimaryOutputSamplingRate(); 3338 return outputSampleRate > 0 ? Integer.toString(outputSampleRate) : null; 3339 } else if (PROPERTY_OUTPUT_FRAMES_PER_BUFFER.equals(key)) { 3340 int outputFramesPerBuffer = AudioSystem.getPrimaryOutputFrameCount(); 3341 return outputFramesPerBuffer > 0 ? Integer.toString(outputFramesPerBuffer) : null; 3342 } else if (PROPERTY_SUPPORT_MIC_NEAR_ULTRASOUND.equals(key)) { 3343 // Will throw a RuntimeException Resources.NotFoundException if this config value is 3344 // not found. 3345 return String.valueOf(getContext().getResources().getBoolean( 3346 com.android.internal.R.bool.config_supportMicNearUltrasound)); 3347 } else if (PROPERTY_SUPPORT_SPEAKER_NEAR_ULTRASOUND.equals(key)) { 3348 return String.valueOf(getContext().getResources().getBoolean( 3349 com.android.internal.R.bool.config_supportSpeakerNearUltrasound)); 3350 } else if (PROPERTY_SUPPORT_AUDIO_SOURCE_UNPROCESSED.equals(key)) { 3351 return String.valueOf(getContext().getResources().getBoolean( 3352 com.android.internal.R.bool.config_supportAudioSourceUnprocessed)); 3353 } else { 3354 // null or unknown key 3355 return null; 3356 } 3357 } 3358 3359 /** 3360 * Returns the estimated latency for the given stream type in milliseconds. 3361 * 3362 * DO NOT UNHIDE. The existing approach for doing A/V sync has too many problems. We need 3363 * a better solution. 3364 * @hide 3365 */ getOutputLatency(int streamType)3366 public int getOutputLatency(int streamType) { 3367 return AudioSystem.getOutputLatency(streamType); 3368 } 3369 3370 /** 3371 * Registers a global volume controller interface. Currently limited to SystemUI. 3372 * 3373 * @hide 3374 */ setVolumeController(IVolumeController controller)3375 public void setVolumeController(IVolumeController controller) { 3376 try { 3377 getService().setVolumeController(controller); 3378 } catch (RemoteException e) { 3379 throw e.rethrowFromSystemServer(); 3380 } 3381 } 3382 3383 /** 3384 * Notify audio manager about volume controller visibility changes. 3385 * Currently limited to SystemUI. 3386 * 3387 * @hide 3388 */ notifyVolumeControllerVisible(IVolumeController controller, boolean visible)3389 public void notifyVolumeControllerVisible(IVolumeController controller, boolean visible) { 3390 try { 3391 getService().notifyVolumeControllerVisible(controller, visible); 3392 } catch (RemoteException e) { 3393 throw e.rethrowFromSystemServer(); 3394 } 3395 } 3396 3397 /** 3398 * Only useful for volume controllers. 3399 * @hide 3400 */ isStreamAffectedByRingerMode(int streamType)3401 public boolean isStreamAffectedByRingerMode(int streamType) { 3402 try { 3403 return getService().isStreamAffectedByRingerMode(streamType); 3404 } catch (RemoteException e) { 3405 throw e.rethrowFromSystemServer(); 3406 } 3407 } 3408 3409 /** 3410 * Only useful for volume controllers. 3411 * @hide 3412 */ isStreamAffectedByMute(int streamType)3413 public boolean isStreamAffectedByMute(int streamType) { 3414 try { 3415 return getService().isStreamAffectedByMute(streamType); 3416 } catch (RemoteException e) { 3417 throw e.rethrowFromSystemServer(); 3418 } 3419 } 3420 3421 /** 3422 * Only useful for volume controllers. 3423 * @hide 3424 */ disableSafeMediaVolume()3425 public void disableSafeMediaVolume() { 3426 try { 3427 getService().disableSafeMediaVolume(mApplicationContext.getOpPackageName()); 3428 } catch (RemoteException e) { 3429 throw e.rethrowFromSystemServer(); 3430 } 3431 } 3432 3433 /** 3434 * Only useful for volume controllers. 3435 * @hide 3436 */ setRingerModeInternal(int ringerMode)3437 public void setRingerModeInternal(int ringerMode) { 3438 try { 3439 getService().setRingerModeInternal(ringerMode, getContext().getOpPackageName()); 3440 } catch (RemoteException e) { 3441 throw e.rethrowFromSystemServer(); 3442 } 3443 } 3444 3445 /** 3446 * Only useful for volume controllers. 3447 * @hide 3448 */ getRingerModeInternal()3449 public int getRingerModeInternal() { 3450 try { 3451 return getService().getRingerModeInternal(); 3452 } catch (RemoteException e) { 3453 throw e.rethrowFromSystemServer(); 3454 } 3455 } 3456 3457 /** 3458 * Only useful for volume controllers. 3459 * @hide 3460 */ setVolumePolicy(VolumePolicy policy)3461 public void setVolumePolicy(VolumePolicy policy) { 3462 try { 3463 getService().setVolumePolicy(policy); 3464 } catch (RemoteException e) { 3465 throw e.rethrowFromSystemServer(); 3466 } 3467 } 3468 3469 /** 3470 * Set Hdmi Cec system audio mode. 3471 * 3472 * @param on whether to be on system audio mode 3473 * @return output device type. 0 (DEVICE_NONE) if failed to set device. 3474 * @hide 3475 */ setHdmiSystemAudioSupported(boolean on)3476 public int setHdmiSystemAudioSupported(boolean on) { 3477 try { 3478 return getService().setHdmiSystemAudioSupported(on); 3479 } catch (RemoteException e) { 3480 throw e.rethrowFromSystemServer(); 3481 } 3482 } 3483 3484 /** 3485 * Returns true if Hdmi Cec system audio mode is supported. 3486 * 3487 * @hide 3488 */ 3489 @SystemApi isHdmiSystemAudioSupported()3490 public boolean isHdmiSystemAudioSupported() { 3491 try { 3492 return getService().isHdmiSystemAudioSupported(); 3493 } catch (RemoteException e) { 3494 throw e.rethrowFromSystemServer(); 3495 } 3496 } 3497 3498 /** 3499 * Return codes for listAudioPorts(), createAudioPatch() ... 3500 */ 3501 3502 /** @hide 3503 * CANDIDATE FOR PUBLIC API 3504 */ 3505 public static final int SUCCESS = AudioSystem.SUCCESS; 3506 /** 3507 * A default error code. 3508 */ 3509 public static final int ERROR = AudioSystem.ERROR; 3510 /** @hide 3511 * CANDIDATE FOR PUBLIC API 3512 */ 3513 public static final int ERROR_BAD_VALUE = AudioSystem.BAD_VALUE; 3514 /** @hide 3515 */ 3516 public static final int ERROR_INVALID_OPERATION = AudioSystem.INVALID_OPERATION; 3517 /** @hide 3518 */ 3519 public static final int ERROR_PERMISSION_DENIED = AudioSystem.PERMISSION_DENIED; 3520 /** @hide 3521 */ 3522 public static final int ERROR_NO_INIT = AudioSystem.NO_INIT; 3523 /** 3524 * An error code indicating that the object reporting it is no longer valid and needs to 3525 * be recreated. 3526 */ 3527 public static final int ERROR_DEAD_OBJECT = AudioSystem.DEAD_OBJECT; 3528 3529 /** 3530 * Returns a list of descriptors for all audio ports managed by the audio framework. 3531 * Audio ports are nodes in the audio framework or audio hardware that can be configured 3532 * or connected and disconnected with createAudioPatch() or releaseAudioPatch(). 3533 * See AudioPort for a list of attributes of each audio port. 3534 * @param ports An AudioPort ArrayList where the list will be returned. 3535 * @hide 3536 */ listAudioPorts(ArrayList<AudioPort> ports)3537 public static int listAudioPorts(ArrayList<AudioPort> ports) { 3538 return updateAudioPortCache(ports, null, null); 3539 } 3540 3541 /** 3542 * Returns a list of descriptors for all audio ports managed by the audio framework as 3543 * it was before the last update calback. 3544 * @param ports An AudioPort ArrayList where the list will be returned. 3545 * @hide 3546 */ listPreviousAudioPorts(ArrayList<AudioPort> ports)3547 public static int listPreviousAudioPorts(ArrayList<AudioPort> ports) { 3548 return updateAudioPortCache(null, null, ports); 3549 } 3550 3551 /** 3552 * Specialized version of listAudioPorts() listing only audio devices (AudioDevicePort) 3553 * @see listAudioPorts(ArrayList<AudioPort>) 3554 * @hide 3555 */ listAudioDevicePorts(ArrayList<AudioDevicePort> devices)3556 public static int listAudioDevicePorts(ArrayList<AudioDevicePort> devices) { 3557 if (devices == null) { 3558 return ERROR_BAD_VALUE; 3559 } 3560 ArrayList<AudioPort> ports = new ArrayList<AudioPort>(); 3561 int status = updateAudioPortCache(ports, null, null); 3562 if (status == SUCCESS) { 3563 filterDevicePorts(ports, devices); 3564 } 3565 return status; 3566 } 3567 3568 /** 3569 * Specialized version of listPreviousAudioPorts() listing only audio devices (AudioDevicePort) 3570 * @see listPreviousAudioPorts(ArrayList<AudioPort>) 3571 * @hide 3572 */ listPreviousAudioDevicePorts(ArrayList<AudioDevicePort> devices)3573 public static int listPreviousAudioDevicePorts(ArrayList<AudioDevicePort> devices) { 3574 if (devices == null) { 3575 return ERROR_BAD_VALUE; 3576 } 3577 ArrayList<AudioPort> ports = new ArrayList<AudioPort>(); 3578 int status = updateAudioPortCache(null, null, ports); 3579 if (status == SUCCESS) { 3580 filterDevicePorts(ports, devices); 3581 } 3582 return status; 3583 } 3584 filterDevicePorts(ArrayList<AudioPort> ports, ArrayList<AudioDevicePort> devices)3585 private static void filterDevicePorts(ArrayList<AudioPort> ports, 3586 ArrayList<AudioDevicePort> devices) { 3587 devices.clear(); 3588 for (int i = 0; i < ports.size(); i++) { 3589 if (ports.get(i) instanceof AudioDevicePort) { 3590 devices.add((AudioDevicePort)ports.get(i)); 3591 } 3592 } 3593 } 3594 3595 /** 3596 * Create a connection between two or more devices. The framework will reject the request if 3597 * device types are not compatible or the implementation does not support the requested 3598 * configuration. 3599 * NOTE: current implementation is limited to one source and one sink per patch. 3600 * @param patch AudioPatch array where the newly created patch will be returned. 3601 * As input, if patch[0] is not null, the specified patch will be replaced by the 3602 * new patch created. This avoids calling releaseAudioPatch() when modifying a 3603 * patch and allows the implementation to optimize transitions. 3604 * @param sources List of source audio ports. All must be AudioPort.ROLE_SOURCE. 3605 * @param sinks List of sink audio ports. All must be AudioPort.ROLE_SINK. 3606 * 3607 * @return - {@link #SUCCESS} if connection is successful. 3608 * - {@link #ERROR_BAD_VALUE} if incompatible device types are passed. 3609 * - {@link #ERROR_INVALID_OPERATION} if the requested connection is not supported. 3610 * - {@link #ERROR_PERMISSION_DENIED} if the client does not have permission to create 3611 * a patch. 3612 * - {@link #ERROR_DEAD_OBJECT} if the server process is dead 3613 * - {@link #ERROR} if patch cannot be connected for any other reason. 3614 * 3615 * patch[0] contains the newly created patch 3616 * @hide 3617 */ createAudioPatch(AudioPatch[] patch, AudioPortConfig[] sources, AudioPortConfig[] sinks)3618 public static int createAudioPatch(AudioPatch[] patch, 3619 AudioPortConfig[] sources, 3620 AudioPortConfig[] sinks) { 3621 return AudioSystem.createAudioPatch(patch, sources, sinks); 3622 } 3623 3624 /** 3625 * Releases an existing audio patch connection. 3626 * @param patch The audio patch to disconnect. 3627 * @return - {@link #SUCCESS} if disconnection is successful. 3628 * - {@link #ERROR_BAD_VALUE} if the specified patch does not exist. 3629 * - {@link #ERROR_PERMISSION_DENIED} if the client does not have permission to release 3630 * a patch. 3631 * - {@link #ERROR_DEAD_OBJECT} if the server process is dead 3632 * - {@link #ERROR} if patch cannot be released for any other reason. 3633 * @hide 3634 */ releaseAudioPatch(AudioPatch patch)3635 public static int releaseAudioPatch(AudioPatch patch) { 3636 return AudioSystem.releaseAudioPatch(patch); 3637 } 3638 3639 /** 3640 * List all existing connections between audio ports. 3641 * @param patches An AudioPatch array where the list will be returned. 3642 * @hide 3643 */ listAudioPatches(ArrayList<AudioPatch> patches)3644 public static int listAudioPatches(ArrayList<AudioPatch> patches) { 3645 return updateAudioPortCache(null, patches, null); 3646 } 3647 3648 /** 3649 * Set the gain on the specified AudioPort. The AudioGainConfig config is build by 3650 * AudioGain.buildConfig() 3651 * @hide 3652 */ setAudioPortGain(AudioPort port, AudioGainConfig gain)3653 public static int setAudioPortGain(AudioPort port, AudioGainConfig gain) { 3654 if (port == null || gain == null) { 3655 return ERROR_BAD_VALUE; 3656 } 3657 AudioPortConfig activeConfig = port.activeConfig(); 3658 AudioPortConfig config = new AudioPortConfig(port, activeConfig.samplingRate(), 3659 activeConfig.channelMask(), activeConfig.format(), gain); 3660 config.mConfigMask = AudioPortConfig.GAIN; 3661 return AudioSystem.setAudioPortConfig(config); 3662 } 3663 3664 /** 3665 * Listener registered by client to be notified upon new audio port connections, 3666 * disconnections or attributes update. 3667 * @hide 3668 */ 3669 public interface OnAudioPortUpdateListener { 3670 /** 3671 * Callback method called upon audio port list update. 3672 * @param portList the updated list of audio ports 3673 */ onAudioPortListUpdate(AudioPort[] portList)3674 public void onAudioPortListUpdate(AudioPort[] portList); 3675 3676 /** 3677 * Callback method called upon audio patch list update. 3678 * @param patchList the updated list of audio patches 3679 */ onAudioPatchListUpdate(AudioPatch[] patchList)3680 public void onAudioPatchListUpdate(AudioPatch[] patchList); 3681 3682 /** 3683 * Callback method called when the mediaserver dies 3684 */ onServiceDied()3685 public void onServiceDied(); 3686 } 3687 3688 /** 3689 * Register an audio port list update listener. 3690 * @hide 3691 */ registerAudioPortUpdateListener(OnAudioPortUpdateListener l)3692 public void registerAudioPortUpdateListener(OnAudioPortUpdateListener l) { 3693 sAudioPortEventHandler.init(); 3694 sAudioPortEventHandler.registerListener(l); 3695 } 3696 3697 /** 3698 * Unregister an audio port list update listener. 3699 * @hide 3700 */ unregisterAudioPortUpdateListener(OnAudioPortUpdateListener l)3701 public void unregisterAudioPortUpdateListener(OnAudioPortUpdateListener l) { 3702 sAudioPortEventHandler.unregisterListener(l); 3703 } 3704 3705 // 3706 // AudioPort implementation 3707 // 3708 3709 static final int AUDIOPORT_GENERATION_INIT = 0; 3710 static Integer sAudioPortGeneration = new Integer(AUDIOPORT_GENERATION_INIT); 3711 static ArrayList<AudioPort> sAudioPortsCached = new ArrayList<AudioPort>(); 3712 static ArrayList<AudioPort> sPreviousAudioPortsCached = new ArrayList<AudioPort>(); 3713 static ArrayList<AudioPatch> sAudioPatchesCached = new ArrayList<AudioPatch>(); 3714 resetAudioPortGeneration()3715 static int resetAudioPortGeneration() { 3716 int generation; 3717 synchronized (sAudioPortGeneration) { 3718 generation = sAudioPortGeneration; 3719 sAudioPortGeneration = AUDIOPORT_GENERATION_INIT; 3720 } 3721 return generation; 3722 } 3723 updateAudioPortCache(ArrayList<AudioPort> ports, ArrayList<AudioPatch> patches, ArrayList<AudioPort> previousPorts)3724 static int updateAudioPortCache(ArrayList<AudioPort> ports, ArrayList<AudioPatch> patches, 3725 ArrayList<AudioPort> previousPorts) { 3726 sAudioPortEventHandler.init(); 3727 synchronized (sAudioPortGeneration) { 3728 3729 if (sAudioPortGeneration == AUDIOPORT_GENERATION_INIT) { 3730 int[] patchGeneration = new int[1]; 3731 int[] portGeneration = new int[1]; 3732 int status; 3733 ArrayList<AudioPort> newPorts = new ArrayList<AudioPort>(); 3734 ArrayList<AudioPatch> newPatches = new ArrayList<AudioPatch>(); 3735 3736 do { 3737 newPorts.clear(); 3738 status = AudioSystem.listAudioPorts(newPorts, portGeneration); 3739 if (status != SUCCESS) { 3740 Log.w(TAG, "updateAudioPortCache: listAudioPorts failed"); 3741 return status; 3742 } 3743 newPatches.clear(); 3744 status = AudioSystem.listAudioPatches(newPatches, patchGeneration); 3745 if (status != SUCCESS) { 3746 Log.w(TAG, "updateAudioPortCache: listAudioPatches failed"); 3747 return status; 3748 } 3749 } while (patchGeneration[0] != portGeneration[0]); 3750 3751 for (int i = 0; i < newPatches.size(); i++) { 3752 for (int j = 0; j < newPatches.get(i).sources().length; j++) { 3753 AudioPortConfig portCfg = updatePortConfig(newPatches.get(i).sources()[j], 3754 newPorts); 3755 newPatches.get(i).sources()[j] = portCfg; 3756 } 3757 for (int j = 0; j < newPatches.get(i).sinks().length; j++) { 3758 AudioPortConfig portCfg = updatePortConfig(newPatches.get(i).sinks()[j], 3759 newPorts); 3760 newPatches.get(i).sinks()[j] = portCfg; 3761 } 3762 } 3763 for (Iterator<AudioPatch> i = newPatches.iterator(); i.hasNext(); ) { 3764 AudioPatch newPatch = i.next(); 3765 boolean hasInvalidPort = false; 3766 for (AudioPortConfig portCfg : newPatch.sources()) { 3767 if (portCfg == null) { 3768 hasInvalidPort = true; 3769 break; 3770 } 3771 } 3772 for (AudioPortConfig portCfg : newPatch.sinks()) { 3773 if (portCfg == null) { 3774 hasInvalidPort = true; 3775 break; 3776 } 3777 } 3778 if (hasInvalidPort) { 3779 // Temporarily remove patches with invalid ports. One who created the patch 3780 // is responsible for dealing with the port change. 3781 i.remove(); 3782 } 3783 } 3784 3785 sPreviousAudioPortsCached = sAudioPortsCached; 3786 sAudioPortsCached = newPorts; 3787 sAudioPatchesCached = newPatches; 3788 sAudioPortGeneration = portGeneration[0]; 3789 } 3790 if (ports != null) { 3791 ports.clear(); 3792 ports.addAll(sAudioPortsCached); 3793 } 3794 if (patches != null) { 3795 patches.clear(); 3796 patches.addAll(sAudioPatchesCached); 3797 } 3798 if (previousPorts != null) { 3799 previousPorts.clear(); 3800 previousPorts.addAll(sPreviousAudioPortsCached); 3801 } 3802 } 3803 return SUCCESS; 3804 } 3805 updatePortConfig(AudioPortConfig portCfg, ArrayList<AudioPort> ports)3806 static AudioPortConfig updatePortConfig(AudioPortConfig portCfg, ArrayList<AudioPort> ports) { 3807 AudioPort port = portCfg.port(); 3808 int k; 3809 for (k = 0; k < ports.size(); k++) { 3810 // compare handles because the port returned by JNI is not of the correct 3811 // subclass 3812 if (ports.get(k).handle().equals(port.handle())) { 3813 port = ports.get(k); 3814 break; 3815 } 3816 } 3817 if (k == ports.size()) { 3818 // this hould never happen 3819 Log.e(TAG, "updatePortConfig port not found for handle: "+port.handle().id()); 3820 return null; 3821 } 3822 AudioGainConfig gainCfg = portCfg.gain(); 3823 if (gainCfg != null) { 3824 AudioGain gain = port.gain(gainCfg.index()); 3825 gainCfg = gain.buildConfig(gainCfg.mode(), 3826 gainCfg.channelMask(), 3827 gainCfg.values(), 3828 gainCfg.rampDurationMs()); 3829 } 3830 return port.buildConfig(portCfg.samplingRate(), 3831 portCfg.channelMask(), 3832 portCfg.format(), 3833 gainCfg); 3834 } 3835 3836 private OnAmPortUpdateListener mPortListener = null; 3837 3838 /** 3839 * The message sent to apps when the contents of the device list changes if they provide 3840 * a {#link Handler} object to addOnAudioDeviceConnectionListener(). 3841 */ 3842 private final static int MSG_DEVICES_CALLBACK_REGISTERED = 0; 3843 private final static int MSG_DEVICES_DEVICES_ADDED = 1; 3844 private final static int MSG_DEVICES_DEVICES_REMOVED = 2; 3845 3846 /** 3847 * The list of {@link AudioDeviceCallback} objects to receive add/remove notifications. 3848 */ 3849 private ArrayMap<AudioDeviceCallback, NativeEventHandlerDelegate> 3850 mDeviceCallbacks = 3851 new ArrayMap<AudioDeviceCallback, NativeEventHandlerDelegate>(); 3852 3853 /** 3854 * The following are flags to allow users of {@link AudioManager#getDevices(int)} to filter 3855 * the results list to only those device types they are interested in. 3856 */ 3857 /** 3858 * Specifies to the {@link AudioManager#getDevices(int)} method to include 3859 * source (i.e. input) audio devices. 3860 */ 3861 public static final int GET_DEVICES_INPUTS = 0x0001; 3862 3863 /** 3864 * Specifies to the {@link AudioManager#getDevices(int)} method to include 3865 * sink (i.e. output) audio devices. 3866 */ 3867 public static final int GET_DEVICES_OUTPUTS = 0x0002; 3868 3869 /** 3870 * Specifies to the {@link AudioManager#getDevices(int)} method to include both 3871 * source and sink devices. 3872 */ 3873 public static final int GET_DEVICES_ALL = GET_DEVICES_OUTPUTS | GET_DEVICES_INPUTS; 3874 3875 /** 3876 * Determines if a given AudioDevicePort meets the specified filter criteria. 3877 * @param port The port to test. 3878 * @param flags A set of bitflags specifying the criteria to test. 3879 * @see {@link GET_DEVICES_OUTPUTS} and {@link GET_DEVICES_INPUTS} 3880 **/ checkFlags(AudioDevicePort port, int flags)3881 private static boolean checkFlags(AudioDevicePort port, int flags) { 3882 return port.role() == AudioPort.ROLE_SINK && (flags & GET_DEVICES_OUTPUTS) != 0 || 3883 port.role() == AudioPort.ROLE_SOURCE && (flags & GET_DEVICES_INPUTS) != 0; 3884 } 3885 checkTypes(AudioDevicePort port)3886 private static boolean checkTypes(AudioDevicePort port) { 3887 return AudioDeviceInfo.convertInternalDeviceToDeviceType(port.type()) != 3888 AudioDeviceInfo.TYPE_UNKNOWN && 3889 port.type() != AudioSystem.DEVICE_IN_BACK_MIC; 3890 } 3891 3892 /** 3893 * Returns an array of {@link AudioDeviceInfo} objects corresponding to the audio devices 3894 * currently connected to the system and meeting the criteria specified in the 3895 * <code>flags</code> parameter. 3896 * @param flags A set of bitflags specifying the criteria to test. 3897 * @see {@link GET_DEVICES_OUTPUTS}, {@link GET_DEVICES_INPUTS} and {@link GET_DEVICES_ALL}. 3898 * @return A (possibly zero-length) array of AudioDeviceInfo objects. 3899 */ getDevices(int flags)3900 public AudioDeviceInfo[] getDevices(int flags) { 3901 return getDevicesStatic(flags); 3902 } 3903 3904 /** 3905 * Does the actual computation to generate an array of (externally-visible) AudioDeviceInfo 3906 * objects from the current (internal) AudioDevicePort list. 3907 */ 3908 private static AudioDeviceInfo[] infoListFromPortList(ArrayList<AudioDevicePort> ports, int flags)3909 infoListFromPortList(ArrayList<AudioDevicePort> ports, int flags) { 3910 3911 // figure out how many AudioDeviceInfo we need space for... 3912 int numRecs = 0; 3913 for (AudioDevicePort port : ports) { 3914 if (checkTypes(port) && checkFlags(port, flags)) { 3915 numRecs++; 3916 } 3917 } 3918 3919 // Now load them up... 3920 AudioDeviceInfo[] deviceList = new AudioDeviceInfo[numRecs]; 3921 int slot = 0; 3922 for (AudioDevicePort port : ports) { 3923 if (checkTypes(port) && checkFlags(port, flags)) { 3924 deviceList[slot++] = new AudioDeviceInfo(port); 3925 } 3926 } 3927 3928 return deviceList; 3929 } 3930 3931 /* 3932 * Calculate the list of ports that are in ports_B, but not in ports_A. This is used by 3933 * the add/remove callback mechanism to provide a list of the newly added or removed devices 3934 * rather than the whole list and make the app figure it out. 3935 * Note that calling this method with: 3936 * ports_A == PREVIOUS_ports and ports_B == CURRENT_ports will calculated ADDED ports. 3937 * ports_A == CURRENT_ports and ports_B == PREVIOUS_ports will calculated REMOVED ports. 3938 */ calcListDeltas( ArrayList<AudioDevicePort> ports_A, ArrayList<AudioDevicePort> ports_B, int flags)3939 private static AudioDeviceInfo[] calcListDeltas( 3940 ArrayList<AudioDevicePort> ports_A, ArrayList<AudioDevicePort> ports_B, int flags) { 3941 3942 ArrayList<AudioDevicePort> delta_ports = new ArrayList<AudioDevicePort>(); 3943 3944 AudioDevicePort cur_port = null; 3945 for (int cur_index = 0; cur_index < ports_B.size(); cur_index++) { 3946 boolean cur_port_found = false; 3947 cur_port = ports_B.get(cur_index); 3948 for (int prev_index = 0; 3949 prev_index < ports_A.size() && !cur_port_found; 3950 prev_index++) { 3951 cur_port_found = (cur_port.id() == ports_A.get(prev_index).id()); 3952 } 3953 3954 if (!cur_port_found) { 3955 delta_ports.add(cur_port); 3956 } 3957 } 3958 3959 return infoListFromPortList(delta_ports, flags); 3960 } 3961 3962 /** 3963 * Generates a list of AudioDeviceInfo objects corresponding to the audio devices currently 3964 * connected to the system and meeting the criteria specified in the <code>flags</code> 3965 * parameter. 3966 * This is an internal function. The public API front is getDevices(int). 3967 * @param flags A set of bitflags specifying the criteria to test. 3968 * @see {@link GET_DEVICES_OUTPUTS}, {@link GET_DEVICES_INPUTS} and {@link GET_DEVICES_ALL}. 3969 * @return A (possibly zero-length) array of AudioDeviceInfo objects. 3970 * @hide 3971 */ getDevicesStatic(int flags)3972 public static AudioDeviceInfo[] getDevicesStatic(int flags) { 3973 ArrayList<AudioDevicePort> ports = new ArrayList<AudioDevicePort>(); 3974 int status = AudioManager.listAudioDevicePorts(ports); 3975 if (status != AudioManager.SUCCESS) { 3976 // fail and bail! 3977 return new AudioDeviceInfo[0]; // Always return an array. 3978 } 3979 3980 return infoListFromPortList(ports, flags); 3981 } 3982 3983 /** 3984 * Registers an {@link AudioDeviceCallback} object to receive notifications of changes 3985 * to the set of connected audio devices. 3986 * @param callback The {@link AudioDeviceCallback} object to receive connect/disconnect 3987 * notifications. 3988 * @param handler Specifies the {@link Handler} object for the thread on which to execute 3989 * the callback. If <code>null</code>, the {@link Handler} associated with the main 3990 * {@link Looper} will be used. 3991 */ registerAudioDeviceCallback(AudioDeviceCallback callback, android.os.Handler handler)3992 public void registerAudioDeviceCallback(AudioDeviceCallback callback, 3993 android.os.Handler handler) { 3994 synchronized (mDeviceCallbacks) { 3995 if (callback != null && !mDeviceCallbacks.containsKey(callback)) { 3996 if (mDeviceCallbacks.size() == 0) { 3997 if (mPortListener == null) { 3998 mPortListener = new OnAmPortUpdateListener(); 3999 } 4000 registerAudioPortUpdateListener(mPortListener); 4001 } 4002 NativeEventHandlerDelegate delegate = 4003 new NativeEventHandlerDelegate(callback, handler); 4004 mDeviceCallbacks.put(callback, delegate); 4005 broadcastDeviceListChange(delegate.getHandler()); 4006 } 4007 } 4008 } 4009 4010 /** 4011 * Unregisters an {@link AudioDeviceCallback} object which has been previously registered 4012 * to receive notifications of changes to the set of connected audio devices. 4013 * @param callback The {@link AudioDeviceCallback} object that was previously registered 4014 * with {@link AudioManager#registerAudioDeviceCallback) to be unregistered. 4015 */ unregisterAudioDeviceCallback(AudioDeviceCallback callback)4016 public void unregisterAudioDeviceCallback(AudioDeviceCallback callback) { 4017 synchronized (mDeviceCallbacks) { 4018 if (mDeviceCallbacks.containsKey(callback)) { 4019 mDeviceCallbacks.remove(callback); 4020 if (mDeviceCallbacks.size() == 0) { 4021 unregisterAudioPortUpdateListener(mPortListener); 4022 } 4023 } 4024 } 4025 } 4026 4027 // Since we need to calculate the changes since THE LAST NOTIFICATION, and not since the 4028 // (unpredictable) last time updateAudioPortCache() was called by someone, keep a list 4029 // of the ports that exist at the time of the last notification. 4030 private ArrayList<AudioDevicePort> mPreviousPorts = new ArrayList<AudioDevicePort>(); 4031 4032 /** 4033 * Internal method to compute and generate add/remove messages and then send to any 4034 * registered callbacks. 4035 */ broadcastDeviceListChange(Handler handler)4036 private void broadcastDeviceListChange(Handler handler) { 4037 int status; 4038 4039 // Get the new current set of ports 4040 ArrayList<AudioDevicePort> current_ports = new ArrayList<AudioDevicePort>(); 4041 status = AudioManager.listAudioDevicePorts(current_ports); 4042 if (status != AudioManager.SUCCESS) { 4043 return; 4044 } 4045 4046 if (handler != null) { 4047 // This is the callback for the registration, so send the current list 4048 AudioDeviceInfo[] deviceList = 4049 infoListFromPortList(current_ports, GET_DEVICES_ALL); 4050 handler.sendMessage( 4051 Message.obtain(handler, MSG_DEVICES_CALLBACK_REGISTERED, deviceList)); 4052 } else { 4053 AudioDeviceInfo[] added_devices = 4054 calcListDeltas(mPreviousPorts, current_ports, GET_DEVICES_ALL); 4055 AudioDeviceInfo[] removed_devices = 4056 calcListDeltas(current_ports, mPreviousPorts, GET_DEVICES_ALL); 4057 4058 if (added_devices.length != 0 || removed_devices.length != 0) { 4059 synchronized (mDeviceCallbacks) { 4060 for (int i = 0; i < mDeviceCallbacks.size(); i++) { 4061 handler = mDeviceCallbacks.valueAt(i).getHandler(); 4062 if (handler != null) { 4063 if (added_devices.length != 0) { 4064 handler.sendMessage(Message.obtain(handler, 4065 MSG_DEVICES_DEVICES_ADDED, 4066 added_devices)); 4067 } 4068 if (removed_devices.length != 0) { 4069 handler.sendMessage(Message.obtain(handler, 4070 MSG_DEVICES_DEVICES_REMOVED, 4071 removed_devices)); 4072 } 4073 } 4074 } 4075 } 4076 } 4077 } 4078 4079 mPreviousPorts = current_ports; 4080 } 4081 4082 /** 4083 * Handles Port list update notifications from the AudioManager 4084 */ 4085 private class OnAmPortUpdateListener implements AudioManager.OnAudioPortUpdateListener { 4086 static final String TAG = "OnAmPortUpdateListener"; onAudioPortListUpdate(AudioPort[] portList)4087 public void onAudioPortListUpdate(AudioPort[] portList) { 4088 broadcastDeviceListChange(null); 4089 } 4090 4091 /** 4092 * Callback method called upon audio patch list update. 4093 * Note: We don't do anything with Patches at this time, so ignore this notification. 4094 * @param patchList the updated list of audio patches. 4095 */ onAudioPatchListUpdate(AudioPatch[] patchList)4096 public void onAudioPatchListUpdate(AudioPatch[] patchList) {} 4097 4098 /** 4099 * Callback method called when the mediaserver dies 4100 */ onServiceDied()4101 public void onServiceDied() { 4102 broadcastDeviceListChange(null); 4103 } 4104 } 4105 4106 //--------------------------------------------------------- 4107 // Inner classes 4108 //-------------------- 4109 /** 4110 * Helper class to handle the forwarding of native events to the appropriate listener 4111 * (potentially) handled in a different thread. 4112 */ 4113 private class NativeEventHandlerDelegate { 4114 private final Handler mHandler; 4115 NativeEventHandlerDelegate(final AudioDeviceCallback callback, Handler handler)4116 NativeEventHandlerDelegate(final AudioDeviceCallback callback, 4117 Handler handler) { 4118 // find the looper for our new event handler 4119 Looper looper; 4120 if (handler != null) { 4121 looper = handler.getLooper(); 4122 } else { 4123 // no given handler, use the looper the addListener call was called in 4124 looper = Looper.getMainLooper(); 4125 } 4126 4127 // construct the event handler with this looper 4128 if (looper != null) { 4129 // implement the event handler delegate 4130 mHandler = new Handler(looper) { 4131 @Override 4132 public void handleMessage(Message msg) { 4133 switch(msg.what) { 4134 case MSG_DEVICES_CALLBACK_REGISTERED: 4135 case MSG_DEVICES_DEVICES_ADDED: 4136 if (callback != null) { 4137 callback.onAudioDevicesAdded((AudioDeviceInfo[])msg.obj); 4138 } 4139 break; 4140 4141 case MSG_DEVICES_DEVICES_REMOVED: 4142 if (callback != null) { 4143 callback.onAudioDevicesRemoved((AudioDeviceInfo[])msg.obj); 4144 } 4145 break; 4146 4147 default: 4148 Log.e(TAG, "Unknown native event type: " + msg.what); 4149 break; 4150 } 4151 } 4152 }; 4153 } else { 4154 mHandler = null; 4155 } 4156 } 4157 getHandler()4158 Handler getHandler() { 4159 return mHandler; 4160 } 4161 } 4162 } 4163