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 */ 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 */ 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 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 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 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 */ 690 public void dispatchMediaKeyEvent(KeyEvent keyEvent) { 691 MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(getContext()); 692 helper.sendMediaButtonEvent(keyEvent, false); 693 } 694 695 /** 696 * @hide 697 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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()} 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 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 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 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 */ 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 */ 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 */ 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 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 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 */ 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 */ 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 */ 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 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 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 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 */ 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 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 2594 public void unregisterMediaButtonEventReceiver(PendingIntent eventReceiver) { 2595 if (eventReceiver == null) { 2596 return; 2597 } 2598 unregisterMediaButtonIntent(eventReceiver); 2599 } 2600 2601 /** 2602 * @hide 2603 */ 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 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 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 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 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 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 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 * @see AudioRecordingConfiguration 2748 */ 2749 public static abstract class AudioRecordingCallback { 2750 /** 2751 * Called whenever the device recording configuration has changed. 2752 * @param configs list containing the results of 2753 * {@link AudioManager#getActiveRecordingConfigurations()}. 2754 */ 2755 public void onRecordingConfigChanged(List<AudioRecordingConfiguration> configs) {} 2756 } 2757 2758 private static class AudioRecordingCallbackInfo { 2759 final AudioRecordingCallback mCb; 2760 final Handler mHandler; 2761 AudioRecordingCallbackInfo(AudioRecordingCallback cb, Handler handler) { 2762 mCb = cb; 2763 mHandler = handler; 2764 } 2765 } 2766 2767 private final static class RecordConfigChangeCallbackData { 2768 final AudioRecordingCallback mCb; 2769 final List<AudioRecordingConfiguration> mConfigs; 2770 2771 RecordConfigChangeCallbackData(AudioRecordingCallback cb, 2772 List<AudioRecordingConfiguration> configs) { 2773 mCb = cb; 2774 mConfigs = configs; 2775 } 2776 } 2777 2778 /** 2779 * Register a callback to be notified of audio recording changes through 2780 * {@link AudioRecordingCallback} 2781 * @param cb non-null callback to register 2782 * @param handler the {@link Handler} object for the thread on which to execute 2783 * the callback. If <code>null</code>, the {@link Handler} associated with the main 2784 * {@link Looper} will be used. 2785 */ 2786 public void registerAudioRecordingCallback(@NonNull AudioRecordingCallback cb, Handler handler) 2787 { 2788 if (cb == null) { 2789 throw new IllegalArgumentException("Illegal null AudioRecordingCallback argument"); 2790 } 2791 2792 synchronized(mRecordCallbackLock) { 2793 // lazy initialization of the list of recording callbacks 2794 if (mRecordCallbackList == null) { 2795 mRecordCallbackList = new ArrayList<AudioRecordingCallbackInfo>(); 2796 } 2797 final int oldCbCount = mRecordCallbackList.size(); 2798 if (!hasRecordCallback_sync(cb)) { 2799 mRecordCallbackList.add(new AudioRecordingCallbackInfo(cb, 2800 new ServiceEventHandlerDelegate(handler).getHandler())); 2801 final int newCbCount = mRecordCallbackList.size(); 2802 if ((oldCbCount == 0) && (newCbCount > 0)) { 2803 // register binder for callbacks 2804 final IAudioService service = getService(); 2805 try { 2806 service.registerRecordingCallback(mRecCb); 2807 } catch (RemoteException e) { 2808 throw e.rethrowFromSystemServer(); 2809 } 2810 } 2811 } else { 2812 Log.w(TAG, "attempt to call registerAudioRecordingCallback() on a previously" 2813 + "registered callback"); 2814 } 2815 } 2816 } 2817 2818 /** 2819 * Unregister an audio recording callback previously registered with 2820 * {@link #registerAudioRecordingCallback(AudioRecordingCallback, Handler)}. 2821 * @param cb non-null callback to unregister 2822 */ 2823 public void unregisterAudioRecordingCallback(@NonNull AudioRecordingCallback cb) { 2824 if (cb == null) { 2825 throw new IllegalArgumentException("Illegal null AudioRecordingCallback argument"); 2826 } 2827 synchronized(mRecordCallbackLock) { 2828 if (mRecordCallbackList == null) { 2829 return; 2830 } 2831 final int oldCbCount = mRecordCallbackList.size(); 2832 if (removeRecordCallback_sync(cb)) { 2833 final int newCbCount = mRecordCallbackList.size(); 2834 if ((oldCbCount > 0) && (newCbCount == 0)) { 2835 // unregister binder for callbacks 2836 final IAudioService service = getService(); 2837 try { 2838 service.unregisterRecordingCallback(mRecCb); 2839 } catch (RemoteException e) { 2840 throw e.rethrowFromSystemServer(); 2841 } 2842 } 2843 } else { 2844 Log.w(TAG, "attempt to call unregisterAudioRecordingCallback() on a callback" 2845 + " already unregistered or never registered"); 2846 } 2847 } 2848 } 2849 2850 /** 2851 * Returns the current active audio recording configurations of the device. 2852 * @return a non-null list of recording configurations. An empty list indicates there is 2853 * no recording active when queried. 2854 * @see AudioRecordingConfiguration 2855 */ 2856 public @NonNull List<AudioRecordingConfiguration> getActiveRecordingConfigurations() { 2857 final IAudioService service = getService(); 2858 try { 2859 return service.getActiveRecordingConfigurations(); 2860 } catch (RemoteException e) { 2861 throw e.rethrowFromSystemServer(); 2862 } 2863 } 2864 2865 /** 2866 * constants for the recording events, to keep in sync 2867 * with frameworks/av/include/media/AudioPolicy.h 2868 */ 2869 /** @hide */ 2870 public final static int RECORD_CONFIG_EVENT_START = 1; 2871 /** @hide */ 2872 public final static int RECORD_CONFIG_EVENT_STOP = 0; 2873 2874 /** 2875 * All operations on this list are sync'd on mRecordCallbackLock. 2876 * List is lazy-initialized in 2877 * {@link #registerAudioRecordingCallback(AudioRecordingCallback, Handler)}. 2878 * List can be null. 2879 */ 2880 private List<AudioRecordingCallbackInfo> mRecordCallbackList; 2881 private final Object mRecordCallbackLock = new Object(); 2882 2883 /** 2884 * Must be called synchronized on mRecordCallbackLock 2885 */ 2886 private boolean hasRecordCallback_sync(@NonNull AudioRecordingCallback cb) { 2887 if (mRecordCallbackList != null) { 2888 for (int i=0 ; i < mRecordCallbackList.size() ; i++) { 2889 if (cb.equals(mRecordCallbackList.get(i).mCb)) { 2890 return true; 2891 } 2892 } 2893 } 2894 return false; 2895 } 2896 2897 /** 2898 * Must be called synchronized on mRecordCallbackLock 2899 */ 2900 private boolean removeRecordCallback_sync(@NonNull AudioRecordingCallback cb) { 2901 if (mRecordCallbackList != null) { 2902 for (int i=0 ; i < mRecordCallbackList.size() ; i++) { 2903 if (cb.equals(mRecordCallbackList.get(i).mCb)) { 2904 mRecordCallbackList.remove(i); 2905 return true; 2906 } 2907 } 2908 } 2909 return false; 2910 } 2911 2912 private final IRecordingConfigDispatcher mRecCb = new IRecordingConfigDispatcher.Stub() { 2913 2914 public void dispatchRecordingConfigChange(List<AudioRecordingConfiguration> configs) { 2915 synchronized(mRecordCallbackLock) { 2916 if (mRecordCallbackList != null) { 2917 for (int i=0 ; i < mRecordCallbackList.size() ; i++) { 2918 final AudioRecordingCallbackInfo arci = mRecordCallbackList.get(i); 2919 if (arci.mHandler != null) { 2920 final Message m = arci.mHandler.obtainMessage( 2921 MSSG_RECORDING_CONFIG_CHANGE/*what*/, 2922 new RecordConfigChangeCallbackData(arci.mCb, configs)/*obj*/); 2923 arci.mHandler.sendMessage(m); 2924 } 2925 } 2926 } 2927 } 2928 } 2929 2930 }; 2931 2932 //===================================================================== 2933 2934 /** 2935 * @hide 2936 * Reload audio settings. This method is called by Settings backup 2937 * agent when audio settings are restored and causes the AudioService 2938 * to read and apply restored settings. 2939 */ 2940 public void reloadAudioSettings() { 2941 IAudioService service = getService(); 2942 try { 2943 service.reloadAudioSettings(); 2944 } catch (RemoteException e) { 2945 throw e.rethrowFromSystemServer(); 2946 } 2947 } 2948 2949 /** 2950 * @hide 2951 * Notifies AudioService that it is connected to an A2DP device that supports absolute volume, 2952 * so that AudioService can send volume change events to the A2DP device, rather than handling 2953 * them. 2954 */ 2955 public void avrcpSupportsAbsoluteVolume(String address, boolean support) { 2956 IAudioService service = getService(); 2957 try { 2958 service.avrcpSupportsAbsoluteVolume(address, support); 2959 } catch (RemoteException e) { 2960 throw e.rethrowFromSystemServer(); 2961 } 2962 } 2963 2964 /** 2965 * {@hide} 2966 */ 2967 private final IBinder mICallBack = new Binder(); 2968 2969 /** 2970 * Checks whether the phone is in silent mode, with or without vibrate. 2971 * 2972 * @return true if phone is in silent mode, with or without vibrate. 2973 * 2974 * @see #getRingerMode() 2975 * 2976 * @hide pending API Council approval 2977 */ 2978 public boolean isSilentMode() { 2979 int ringerMode = getRingerMode(); 2980 boolean silentMode = 2981 (ringerMode == RINGER_MODE_SILENT) || 2982 (ringerMode == RINGER_MODE_VIBRATE); 2983 return silentMode; 2984 } 2985 2986 // This section re-defines new output device constants from AudioSystem, because the AudioSystem 2987 // class is not used by other parts of the framework, which instead use definitions and methods 2988 // from AudioManager. AudioSystem is an internal class used by AudioManager and AudioService. 2989 2990 /** @hide 2991 * The audio device code for representing "no device." */ 2992 public static final int DEVICE_NONE = AudioSystem.DEVICE_NONE; 2993 /** @hide 2994 * The audio output device code for the small speaker at the front of the device used 2995 * when placing calls. Does not refer to an in-ear headphone without attached microphone, 2996 * such as earbuds, earphones, or in-ear monitors (IEM). Those would be handled as a 2997 * {@link #DEVICE_OUT_WIRED_HEADPHONE}. 2998 */ 2999 public static final int DEVICE_OUT_EARPIECE = AudioSystem.DEVICE_OUT_EARPIECE; 3000 /** @hide 3001 * The audio output device code for the built-in speaker */ 3002 public static final int DEVICE_OUT_SPEAKER = AudioSystem.DEVICE_OUT_SPEAKER; 3003 /** @hide 3004 * The audio output device code for a wired headset with attached microphone */ 3005 public static final int DEVICE_OUT_WIRED_HEADSET = AudioSystem.DEVICE_OUT_WIRED_HEADSET; 3006 /** @hide 3007 * The audio output device code for a wired headphone without attached microphone */ 3008 public static final int DEVICE_OUT_WIRED_HEADPHONE = AudioSystem.DEVICE_OUT_WIRED_HEADPHONE; 3009 /** @hide 3010 * The audio output device code for generic Bluetooth SCO, for voice */ 3011 public static final int DEVICE_OUT_BLUETOOTH_SCO = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO; 3012 /** @hide 3013 * The audio output device code for Bluetooth SCO Headset Profile (HSP) and 3014 * Hands-Free Profile (HFP), for voice 3015 */ 3016 public static final int DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 3017 AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET; 3018 /** @hide 3019 * The audio output device code for Bluetooth SCO car audio, for voice */ 3020 public static final int DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 3021 AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT; 3022 /** @hide 3023 * The audio output device code for generic Bluetooth A2DP, for music */ 3024 public static final int DEVICE_OUT_BLUETOOTH_A2DP = AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP; 3025 /** @hide 3026 * The audio output device code for Bluetooth A2DP headphones, for music */ 3027 public static final int DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 3028 AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES; 3029 /** @hide 3030 * The audio output device code for Bluetooth A2DP external speaker, for music */ 3031 public static final int DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 3032 AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER; 3033 /** @hide 3034 * The audio output device code for S/PDIF (legacy) or HDMI 3035 * Deprecated: replaced by {@link #DEVICE_OUT_HDMI} */ 3036 public static final int DEVICE_OUT_AUX_DIGITAL = AudioSystem.DEVICE_OUT_AUX_DIGITAL; 3037 /** @hide 3038 * The audio output device code for HDMI */ 3039 public static final int DEVICE_OUT_HDMI = AudioSystem.DEVICE_OUT_HDMI; 3040 /** @hide 3041 * The audio output device code for an analog wired headset attached via a 3042 * docking station 3043 */ 3044 public static final int DEVICE_OUT_ANLG_DOCK_HEADSET = AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET; 3045 /** @hide 3046 * The audio output device code for a digital wired headset attached via a 3047 * docking station 3048 */ 3049 public static final int DEVICE_OUT_DGTL_DOCK_HEADSET = AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET; 3050 /** @hide 3051 * The audio output device code for a USB audio accessory. The accessory is in USB host 3052 * mode and the Android device in USB device mode 3053 */ 3054 public static final int DEVICE_OUT_USB_ACCESSORY = AudioSystem.DEVICE_OUT_USB_ACCESSORY; 3055 /** @hide 3056 * The audio output device code for a USB audio device. The device is in USB device 3057 * mode and the Android device in USB host mode 3058 */ 3059 public static final int DEVICE_OUT_USB_DEVICE = AudioSystem.DEVICE_OUT_USB_DEVICE; 3060 /** @hide 3061 * The audio output device code for projection output. 3062 */ 3063 public static final int DEVICE_OUT_REMOTE_SUBMIX = AudioSystem.DEVICE_OUT_REMOTE_SUBMIX; 3064 /** @hide 3065 * The audio output device code the telephony voice TX path. 3066 */ 3067 public static final int DEVICE_OUT_TELEPHONY_TX = AudioSystem.DEVICE_OUT_TELEPHONY_TX; 3068 /** @hide 3069 * The audio output device code for an analog jack with line impedance detected. 3070 */ 3071 public static final int DEVICE_OUT_LINE = AudioSystem.DEVICE_OUT_LINE; 3072 /** @hide 3073 * The audio output device code for HDMI Audio Return Channel. 3074 */ 3075 public static final int DEVICE_OUT_HDMI_ARC = AudioSystem.DEVICE_OUT_HDMI_ARC; 3076 /** @hide 3077 * The audio output device code for S/PDIF digital connection. 3078 */ 3079 public static final int DEVICE_OUT_SPDIF = AudioSystem.DEVICE_OUT_SPDIF; 3080 /** @hide 3081 * The audio output device code for built-in FM transmitter. 3082 */ 3083 public static final int DEVICE_OUT_FM = AudioSystem.DEVICE_OUT_FM; 3084 /** @hide 3085 * This is not used as a returned value from {@link #getDevicesForStream}, but could be 3086 * used in the future in a set method to select whatever default device is chosen by the 3087 * platform-specific implementation. 3088 */ 3089 public static final int DEVICE_OUT_DEFAULT = AudioSystem.DEVICE_OUT_DEFAULT; 3090 3091 /** @hide 3092 * The audio input device code for default built-in microphone 3093 */ 3094 public static final int DEVICE_IN_BUILTIN_MIC = AudioSystem.DEVICE_IN_BUILTIN_MIC; 3095 /** @hide 3096 * The audio input device code for a Bluetooth SCO headset 3097 */ 3098 public static final int DEVICE_IN_BLUETOOTH_SCO_HEADSET = 3099 AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET; 3100 /** @hide 3101 * The audio input device code for wired headset microphone 3102 */ 3103 public static final int DEVICE_IN_WIRED_HEADSET = 3104 AudioSystem.DEVICE_IN_WIRED_HEADSET; 3105 /** @hide 3106 * The audio input device code for HDMI 3107 */ 3108 public static final int DEVICE_IN_HDMI = 3109 AudioSystem.DEVICE_IN_HDMI; 3110 /** @hide 3111 * The audio input device code for telephony voice RX path 3112 */ 3113 public static final int DEVICE_IN_TELEPHONY_RX = 3114 AudioSystem.DEVICE_IN_TELEPHONY_RX; 3115 /** @hide 3116 * The audio input device code for built-in microphone pointing to the back 3117 */ 3118 public static final int DEVICE_IN_BACK_MIC = 3119 AudioSystem.DEVICE_IN_BACK_MIC; 3120 /** @hide 3121 * The audio input device code for analog from a docking station 3122 */ 3123 public static final int DEVICE_IN_ANLG_DOCK_HEADSET = 3124 AudioSystem.DEVICE_IN_ANLG_DOCK_HEADSET; 3125 /** @hide 3126 * The audio input device code for digital from a docking station 3127 */ 3128 public static final int DEVICE_IN_DGTL_DOCK_HEADSET = 3129 AudioSystem.DEVICE_IN_DGTL_DOCK_HEADSET; 3130 /** @hide 3131 * The audio input device code for a USB audio accessory. The accessory is in USB host 3132 * mode and the Android device in USB device mode 3133 */ 3134 public static final int DEVICE_IN_USB_ACCESSORY = 3135 AudioSystem.DEVICE_IN_USB_ACCESSORY; 3136 /** @hide 3137 * The audio input device code for a USB audio device. The device is in USB device 3138 * mode and the Android device in USB host mode 3139 */ 3140 public static final int DEVICE_IN_USB_DEVICE = 3141 AudioSystem.DEVICE_IN_USB_DEVICE; 3142 /** @hide 3143 * The audio input device code for a FM radio tuner 3144 */ 3145 public static final int DEVICE_IN_FM_TUNER = AudioSystem.DEVICE_IN_FM_TUNER; 3146 /** @hide 3147 * The audio input device code for a TV tuner 3148 */ 3149 public static final int DEVICE_IN_TV_TUNER = AudioSystem.DEVICE_IN_TV_TUNER; 3150 /** @hide 3151 * The audio input device code for an analog jack with line impedance detected 3152 */ 3153 public static final int DEVICE_IN_LINE = AudioSystem.DEVICE_IN_LINE; 3154 /** @hide 3155 * The audio input device code for a S/PDIF digital connection 3156 */ 3157 public static final int DEVICE_IN_SPDIF = AudioSystem.DEVICE_IN_SPDIF; 3158 /** @hide 3159 * The audio input device code for audio loopback 3160 */ 3161 public static final int DEVICE_IN_LOOPBACK = AudioSystem.DEVICE_IN_LOOPBACK; 3162 3163 /** 3164 * Return true if the device code corresponds to an output device. 3165 * @hide 3166 */ 3167 public static boolean isOutputDevice(int device) 3168 { 3169 return (device & AudioSystem.DEVICE_BIT_IN) == 0; 3170 } 3171 3172 /** 3173 * Return true if the device code corresponds to an input device. 3174 * @hide 3175 */ 3176 public static boolean isInputDevice(int device) 3177 { 3178 return (device & AudioSystem.DEVICE_BIT_IN) == AudioSystem.DEVICE_BIT_IN; 3179 } 3180 3181 3182 /** 3183 * Return the enabled devices for the specified output stream type. 3184 * 3185 * @param streamType The stream type to query. One of 3186 * {@link #STREAM_VOICE_CALL}, 3187 * {@link #STREAM_SYSTEM}, 3188 * {@link #STREAM_RING}, 3189 * {@link #STREAM_MUSIC}, 3190 * {@link #STREAM_ALARM}, 3191 * {@link #STREAM_NOTIFICATION}, 3192 * {@link #STREAM_DTMF}. 3193 * 3194 * @return The bit-mask "or" of audio output device codes for all enabled devices on this 3195 * stream. Zero or more of 3196 * {@link #DEVICE_OUT_EARPIECE}, 3197 * {@link #DEVICE_OUT_SPEAKER}, 3198 * {@link #DEVICE_OUT_WIRED_HEADSET}, 3199 * {@link #DEVICE_OUT_WIRED_HEADPHONE}, 3200 * {@link #DEVICE_OUT_BLUETOOTH_SCO}, 3201 * {@link #DEVICE_OUT_BLUETOOTH_SCO_HEADSET}, 3202 * {@link #DEVICE_OUT_BLUETOOTH_SCO_CARKIT}, 3203 * {@link #DEVICE_OUT_BLUETOOTH_A2DP}, 3204 * {@link #DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES}, 3205 * {@link #DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER}, 3206 * {@link #DEVICE_OUT_HDMI}, 3207 * {@link #DEVICE_OUT_ANLG_DOCK_HEADSET}, 3208 * {@link #DEVICE_OUT_DGTL_DOCK_HEADSET}. 3209 * {@link #DEVICE_OUT_USB_ACCESSORY}. 3210 * {@link #DEVICE_OUT_USB_DEVICE}. 3211 * {@link #DEVICE_OUT_REMOTE_SUBMIX}. 3212 * {@link #DEVICE_OUT_TELEPHONY_TX}. 3213 * {@link #DEVICE_OUT_LINE}. 3214 * {@link #DEVICE_OUT_HDMI_ARC}. 3215 * {@link #DEVICE_OUT_SPDIF}. 3216 * {@link #DEVICE_OUT_FM}. 3217 * {@link #DEVICE_OUT_DEFAULT} is not used here. 3218 * 3219 * The implementation may support additional device codes beyond those listed, so 3220 * the application should ignore any bits which it does not recognize. 3221 * Note that the information may be imprecise when the implementation 3222 * cannot distinguish whether a particular device is enabled. 3223 * 3224 * {@hide} 3225 */ 3226 public int getDevicesForStream(int streamType) { 3227 switch (streamType) { 3228 case STREAM_VOICE_CALL: 3229 case STREAM_SYSTEM: 3230 case STREAM_RING: 3231 case STREAM_MUSIC: 3232 case STREAM_ALARM: 3233 case STREAM_NOTIFICATION: 3234 case STREAM_DTMF: 3235 return AudioSystem.getDevicesForStream(streamType); 3236 default: 3237 return 0; 3238 } 3239 } 3240 3241 /** 3242 * Indicate wired accessory connection state change. 3243 * @param device type of device connected/disconnected (AudioManager.DEVICE_OUT_xxx) 3244 * @param state new connection state: 1 connected, 0 disconnected 3245 * @param name device name 3246 * {@hide} 3247 */ 3248 public void setWiredDeviceConnectionState(int type, int state, String address, String name) { 3249 IAudioService service = getService(); 3250 try { 3251 service.setWiredDeviceConnectionState(type, state, address, name, 3252 mApplicationContext.getOpPackageName()); 3253 } catch (RemoteException e) { 3254 throw e.rethrowFromSystemServer(); 3255 } 3256 } 3257 3258 /** 3259 * Indicate A2DP source or sink connection state change. 3260 * @param device Bluetooth device connected/disconnected 3261 * @param state new connection state (BluetoothProfile.STATE_xxx) 3262 * @param profile profile for the A2DP device 3263 * (either {@link android.bluetooth.BluetoothProfile.A2DP} or 3264 * {@link android.bluetooth.BluetoothProfile.A2DP_SINK}) 3265 * @return a delay in ms that the caller should wait before broadcasting 3266 * BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED intent. 3267 * {@hide} 3268 */ 3269 public int setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state, 3270 int profile) { 3271 IAudioService service = getService(); 3272 int delay = 0; 3273 try { 3274 delay = service.setBluetoothA2dpDeviceConnectionState(device, state, profile); 3275 } catch (RemoteException e) { 3276 throw e.rethrowFromSystemServer(); 3277 } 3278 return delay; 3279 } 3280 3281 /** {@hide} */ 3282 public IRingtonePlayer getRingtonePlayer() { 3283 try { 3284 return getService().getRingtonePlayer(); 3285 } catch (RemoteException e) { 3286 throw e.rethrowFromSystemServer(); 3287 } 3288 } 3289 3290 /** 3291 * Used as a key for {@link #getProperty} to request the native or optimal output sample rate 3292 * for this device's low latency output stream, in decimal Hz. Latency-sensitive apps 3293 * should use this value as a default, and offer the user the option to override it. 3294 * The low latency output stream is typically either the device's primary output stream, 3295 * or another output stream with smaller buffers. 3296 */ 3297 // FIXME Deprecate 3298 public static final String PROPERTY_OUTPUT_SAMPLE_RATE = 3299 "android.media.property.OUTPUT_SAMPLE_RATE"; 3300 3301 /** 3302 * Used as a key for {@link #getProperty} to request the native or optimal output buffer size 3303 * for this device's low latency output stream, in decimal PCM frames. Latency-sensitive apps 3304 * should use this value as a minimum, and offer the user the option to override it. 3305 * The low latency output stream is typically either the device's primary output stream, 3306 * or another output stream with smaller buffers. 3307 */ 3308 // FIXME Deprecate 3309 public static final String PROPERTY_OUTPUT_FRAMES_PER_BUFFER = 3310 "android.media.property.OUTPUT_FRAMES_PER_BUFFER"; 3311 3312 /** 3313 * Used as a key for {@link #getProperty} to determine if the default microphone audio source 3314 * supports near-ultrasound frequencies (range of 18 - 21 kHz). 3315 */ 3316 public static final String PROPERTY_SUPPORT_MIC_NEAR_ULTRASOUND = 3317 "android.media.property.SUPPORT_MIC_NEAR_ULTRASOUND"; 3318 3319 /** 3320 * Used as a key for {@link #getProperty} to determine if the default speaker audio path 3321 * supports near-ultrasound frequencies (range of 18 - 21 kHz). 3322 */ 3323 public static final String PROPERTY_SUPPORT_SPEAKER_NEAR_ULTRASOUND = 3324 "android.media.property.SUPPORT_SPEAKER_NEAR_ULTRASOUND"; 3325 3326 /** 3327 * Used as a key for {@link #getProperty} to determine if the unprocessed audio source is 3328 * available and supported with the expected frequency range and level response. 3329 */ 3330 public static final String PROPERTY_SUPPORT_AUDIO_SOURCE_UNPROCESSED = 3331 "android.media.property.SUPPORT_AUDIO_SOURCE_UNPROCESSED"; 3332 /** 3333 * Returns the value of the property with the specified key. 3334 * @param key One of the strings corresponding to a property key: either 3335 * {@link #PROPERTY_OUTPUT_SAMPLE_RATE}, 3336 * {@link #PROPERTY_OUTPUT_FRAMES_PER_BUFFER}, 3337 * {@link #PROPERTY_SUPPORT_MIC_NEAR_ULTRASOUND}, 3338 * {@link #PROPERTY_SUPPORT_SPEAKER_NEAR_ULTRASOUND}, or 3339 * {@link #PROPERTY_SUPPORT_AUDIO_SOURCE_UNPROCESSED}. 3340 * @return A string representing the associated value for that property key, 3341 * or null if there is no value for that key. 3342 */ 3343 public String getProperty(String key) { 3344 if (PROPERTY_OUTPUT_SAMPLE_RATE.equals(key)) { 3345 int outputSampleRate = AudioSystem.getPrimaryOutputSamplingRate(); 3346 return outputSampleRate > 0 ? Integer.toString(outputSampleRate) : null; 3347 } else if (PROPERTY_OUTPUT_FRAMES_PER_BUFFER.equals(key)) { 3348 int outputFramesPerBuffer = AudioSystem.getPrimaryOutputFrameCount(); 3349 return outputFramesPerBuffer > 0 ? Integer.toString(outputFramesPerBuffer) : null; 3350 } else if (PROPERTY_SUPPORT_MIC_NEAR_ULTRASOUND.equals(key)) { 3351 // Will throw a RuntimeException Resources.NotFoundException if this config value is 3352 // not found. 3353 return String.valueOf(getContext().getResources().getBoolean( 3354 com.android.internal.R.bool.config_supportMicNearUltrasound)); 3355 } else if (PROPERTY_SUPPORT_SPEAKER_NEAR_ULTRASOUND.equals(key)) { 3356 return String.valueOf(getContext().getResources().getBoolean( 3357 com.android.internal.R.bool.config_supportSpeakerNearUltrasound)); 3358 } else if (PROPERTY_SUPPORT_AUDIO_SOURCE_UNPROCESSED.equals(key)) { 3359 return String.valueOf(getContext().getResources().getBoolean( 3360 com.android.internal.R.bool.config_supportAudioSourceUnprocessed)); 3361 } else { 3362 // null or unknown key 3363 return null; 3364 } 3365 } 3366 3367 /** 3368 * Returns the estimated latency for the given stream type in milliseconds. 3369 * 3370 * DO NOT UNHIDE. The existing approach for doing A/V sync has too many problems. We need 3371 * a better solution. 3372 * @hide 3373 */ 3374 public int getOutputLatency(int streamType) { 3375 return AudioSystem.getOutputLatency(streamType); 3376 } 3377 3378 /** 3379 * Registers a global volume controller interface. Currently limited to SystemUI. 3380 * 3381 * @hide 3382 */ 3383 public void setVolumeController(IVolumeController controller) { 3384 try { 3385 getService().setVolumeController(controller); 3386 } catch (RemoteException e) { 3387 throw e.rethrowFromSystemServer(); 3388 } 3389 } 3390 3391 /** 3392 * Notify audio manager about volume controller visibility changes. 3393 * Currently limited to SystemUI. 3394 * 3395 * @hide 3396 */ 3397 public void notifyVolumeControllerVisible(IVolumeController controller, boolean visible) { 3398 try { 3399 getService().notifyVolumeControllerVisible(controller, visible); 3400 } catch (RemoteException e) { 3401 throw e.rethrowFromSystemServer(); 3402 } 3403 } 3404 3405 /** 3406 * Only useful for volume controllers. 3407 * @hide 3408 */ 3409 public boolean isStreamAffectedByRingerMode(int streamType) { 3410 try { 3411 return getService().isStreamAffectedByRingerMode(streamType); 3412 } catch (RemoteException e) { 3413 throw e.rethrowFromSystemServer(); 3414 } 3415 } 3416 3417 /** 3418 * Only useful for volume controllers. 3419 * @hide 3420 */ 3421 public boolean isStreamAffectedByMute(int streamType) { 3422 try { 3423 return getService().isStreamAffectedByMute(streamType); 3424 } catch (RemoteException e) { 3425 throw e.rethrowFromSystemServer(); 3426 } 3427 } 3428 3429 /** 3430 * Only useful for volume controllers. 3431 * @hide 3432 */ 3433 public void disableSafeMediaVolume() { 3434 try { 3435 getService().disableSafeMediaVolume(mApplicationContext.getOpPackageName()); 3436 } catch (RemoteException e) { 3437 throw e.rethrowFromSystemServer(); 3438 } 3439 } 3440 3441 /** 3442 * Only useful for volume controllers. 3443 * @hide 3444 */ 3445 public void setRingerModeInternal(int ringerMode) { 3446 try { 3447 getService().setRingerModeInternal(ringerMode, getContext().getOpPackageName()); 3448 } catch (RemoteException e) { 3449 throw e.rethrowFromSystemServer(); 3450 } 3451 } 3452 3453 /** 3454 * Only useful for volume controllers. 3455 * @hide 3456 */ 3457 public int getRingerModeInternal() { 3458 try { 3459 return getService().getRingerModeInternal(); 3460 } catch (RemoteException e) { 3461 throw e.rethrowFromSystemServer(); 3462 } 3463 } 3464 3465 /** 3466 * Only useful for volume controllers. 3467 * @hide 3468 */ 3469 public void setVolumePolicy(VolumePolicy policy) { 3470 try { 3471 getService().setVolumePolicy(policy); 3472 } catch (RemoteException e) { 3473 throw e.rethrowFromSystemServer(); 3474 } 3475 } 3476 3477 /** 3478 * Set Hdmi Cec system audio mode. 3479 * 3480 * @param on whether to be on system audio mode 3481 * @return output device type. 0 (DEVICE_NONE) if failed to set device. 3482 * @hide 3483 */ 3484 public int setHdmiSystemAudioSupported(boolean on) { 3485 try { 3486 return getService().setHdmiSystemAudioSupported(on); 3487 } catch (RemoteException e) { 3488 throw e.rethrowFromSystemServer(); 3489 } 3490 } 3491 3492 /** 3493 * Returns true if Hdmi Cec system audio mode is supported. 3494 * 3495 * @hide 3496 */ 3497 @SystemApi 3498 public boolean isHdmiSystemAudioSupported() { 3499 try { 3500 return getService().isHdmiSystemAudioSupported(); 3501 } catch (RemoteException e) { 3502 throw e.rethrowFromSystemServer(); 3503 } 3504 } 3505 3506 /** 3507 * Return codes for listAudioPorts(), createAudioPatch() ... 3508 */ 3509 3510 /** @hide 3511 * CANDIDATE FOR PUBLIC API 3512 */ 3513 public static final int SUCCESS = AudioSystem.SUCCESS; 3514 /** 3515 * A default error code. 3516 */ 3517 public static final int ERROR = AudioSystem.ERROR; 3518 /** @hide 3519 * CANDIDATE FOR PUBLIC API 3520 */ 3521 public static final int ERROR_BAD_VALUE = AudioSystem.BAD_VALUE; 3522 /** @hide 3523 */ 3524 public static final int ERROR_INVALID_OPERATION = AudioSystem.INVALID_OPERATION; 3525 /** @hide 3526 */ 3527 public static final int ERROR_PERMISSION_DENIED = AudioSystem.PERMISSION_DENIED; 3528 /** @hide 3529 */ 3530 public static final int ERROR_NO_INIT = AudioSystem.NO_INIT; 3531 /** 3532 * An error code indicating that the object reporting it is no longer valid and needs to 3533 * be recreated. 3534 */ 3535 public static final int ERROR_DEAD_OBJECT = AudioSystem.DEAD_OBJECT; 3536 3537 /** 3538 * Returns a list of descriptors for all audio ports managed by the audio framework. 3539 * Audio ports are nodes in the audio framework or audio hardware that can be configured 3540 * or connected and disconnected with createAudioPatch() or releaseAudioPatch(). 3541 * See AudioPort for a list of attributes of each audio port. 3542 * @param ports An AudioPort ArrayList where the list will be returned. 3543 * @hide 3544 */ 3545 public static int listAudioPorts(ArrayList<AudioPort> ports) { 3546 return updateAudioPortCache(ports, null, null); 3547 } 3548 3549 /** 3550 * Returns a list of descriptors for all audio ports managed by the audio framework as 3551 * it was before the last update calback. 3552 * @param ports An AudioPort ArrayList where the list will be returned. 3553 * @hide 3554 */ 3555 public static int listPreviousAudioPorts(ArrayList<AudioPort> ports) { 3556 return updateAudioPortCache(null, null, ports); 3557 } 3558 3559 /** 3560 * Specialized version of listAudioPorts() listing only audio devices (AudioDevicePort) 3561 * @see listAudioPorts(ArrayList<AudioPort>) 3562 * @hide 3563 */ 3564 public static int listAudioDevicePorts(ArrayList<AudioDevicePort> devices) { 3565 if (devices == null) { 3566 return ERROR_BAD_VALUE; 3567 } 3568 ArrayList<AudioPort> ports = new ArrayList<AudioPort>(); 3569 int status = updateAudioPortCache(ports, null, null); 3570 if (status == SUCCESS) { 3571 filterDevicePorts(ports, devices); 3572 } 3573 return status; 3574 } 3575 3576 /** 3577 * Specialized version of listPreviousAudioPorts() listing only audio devices (AudioDevicePort) 3578 * @see listPreviousAudioPorts(ArrayList<AudioPort>) 3579 * @hide 3580 */ 3581 public static int listPreviousAudioDevicePorts(ArrayList<AudioDevicePort> devices) { 3582 if (devices == null) { 3583 return ERROR_BAD_VALUE; 3584 } 3585 ArrayList<AudioPort> ports = new ArrayList<AudioPort>(); 3586 int status = updateAudioPortCache(null, null, ports); 3587 if (status == SUCCESS) { 3588 filterDevicePorts(ports, devices); 3589 } 3590 return status; 3591 } 3592 3593 private static void filterDevicePorts(ArrayList<AudioPort> ports, 3594 ArrayList<AudioDevicePort> devices) { 3595 devices.clear(); 3596 for (int i = 0; i < ports.size(); i++) { 3597 if (ports.get(i) instanceof AudioDevicePort) { 3598 devices.add((AudioDevicePort)ports.get(i)); 3599 } 3600 } 3601 } 3602 3603 /** 3604 * Create a connection between two or more devices. The framework will reject the request if 3605 * device types are not compatible or the implementation does not support the requested 3606 * configuration. 3607 * NOTE: current implementation is limited to one source and one sink per patch. 3608 * @param patch AudioPatch array where the newly created patch will be returned. 3609 * As input, if patch[0] is not null, the specified patch will be replaced by the 3610 * new patch created. This avoids calling releaseAudioPatch() when modifying a 3611 * patch and allows the implementation to optimize transitions. 3612 * @param sources List of source audio ports. All must be AudioPort.ROLE_SOURCE. 3613 * @param sinks List of sink audio ports. All must be AudioPort.ROLE_SINK. 3614 * 3615 * @return - {@link #SUCCESS} if connection is successful. 3616 * - {@link #ERROR_BAD_VALUE} if incompatible device types are passed. 3617 * - {@link #ERROR_INVALID_OPERATION} if the requested connection is not supported. 3618 * - {@link #ERROR_PERMISSION_DENIED} if the client does not have permission to create 3619 * a patch. 3620 * - {@link #ERROR_DEAD_OBJECT} if the server process is dead 3621 * - {@link #ERROR} if patch cannot be connected for any other reason. 3622 * 3623 * patch[0] contains the newly created patch 3624 * @hide 3625 */ 3626 public static int createAudioPatch(AudioPatch[] patch, 3627 AudioPortConfig[] sources, 3628 AudioPortConfig[] sinks) { 3629 return AudioSystem.createAudioPatch(patch, sources, sinks); 3630 } 3631 3632 /** 3633 * Releases an existing audio patch connection. 3634 * @param patch The audio patch to disconnect. 3635 * @return - {@link #SUCCESS} if disconnection is successful. 3636 * - {@link #ERROR_BAD_VALUE} if the specified patch does not exist. 3637 * - {@link #ERROR_PERMISSION_DENIED} if the client does not have permission to release 3638 * a patch. 3639 * - {@link #ERROR_DEAD_OBJECT} if the server process is dead 3640 * - {@link #ERROR} if patch cannot be released for any other reason. 3641 * @hide 3642 */ 3643 public static int releaseAudioPatch(AudioPatch patch) { 3644 return AudioSystem.releaseAudioPatch(patch); 3645 } 3646 3647 /** 3648 * List all existing connections between audio ports. 3649 * @param patches An AudioPatch array where the list will be returned. 3650 * @hide 3651 */ 3652 public static int listAudioPatches(ArrayList<AudioPatch> patches) { 3653 return updateAudioPortCache(null, patches, null); 3654 } 3655 3656 /** 3657 * Set the gain on the specified AudioPort. The AudioGainConfig config is build by 3658 * AudioGain.buildConfig() 3659 * @hide 3660 */ 3661 public static int setAudioPortGain(AudioPort port, AudioGainConfig gain) { 3662 if (port == null || gain == null) { 3663 return ERROR_BAD_VALUE; 3664 } 3665 AudioPortConfig activeConfig = port.activeConfig(); 3666 AudioPortConfig config = new AudioPortConfig(port, activeConfig.samplingRate(), 3667 activeConfig.channelMask(), activeConfig.format(), gain); 3668 config.mConfigMask = AudioPortConfig.GAIN; 3669 return AudioSystem.setAudioPortConfig(config); 3670 } 3671 3672 /** 3673 * Listener registered by client to be notified upon new audio port connections, 3674 * disconnections or attributes update. 3675 * @hide 3676 */ 3677 public interface OnAudioPortUpdateListener { 3678 /** 3679 * Callback method called upon audio port list update. 3680 * @param portList the updated list of audio ports 3681 */ 3682 public void onAudioPortListUpdate(AudioPort[] portList); 3683 3684 /** 3685 * Callback method called upon audio patch list update. 3686 * @param patchList the updated list of audio patches 3687 */ 3688 public void onAudioPatchListUpdate(AudioPatch[] patchList); 3689 3690 /** 3691 * Callback method called when the mediaserver dies 3692 */ 3693 public void onServiceDied(); 3694 } 3695 3696 /** 3697 * Register an audio port list update listener. 3698 * @hide 3699 */ 3700 public void registerAudioPortUpdateListener(OnAudioPortUpdateListener l) { 3701 sAudioPortEventHandler.init(); 3702 sAudioPortEventHandler.registerListener(l); 3703 } 3704 3705 /** 3706 * Unregister an audio port list update listener. 3707 * @hide 3708 */ 3709 public void unregisterAudioPortUpdateListener(OnAudioPortUpdateListener l) { 3710 sAudioPortEventHandler.unregisterListener(l); 3711 } 3712 3713 // 3714 // AudioPort implementation 3715 // 3716 3717 static final int AUDIOPORT_GENERATION_INIT = 0; 3718 static Integer sAudioPortGeneration = new Integer(AUDIOPORT_GENERATION_INIT); 3719 static ArrayList<AudioPort> sAudioPortsCached = new ArrayList<AudioPort>(); 3720 static ArrayList<AudioPort> sPreviousAudioPortsCached = new ArrayList<AudioPort>(); 3721 static ArrayList<AudioPatch> sAudioPatchesCached = new ArrayList<AudioPatch>(); 3722 3723 static int resetAudioPortGeneration() { 3724 int generation; 3725 synchronized (sAudioPortGeneration) { 3726 generation = sAudioPortGeneration; 3727 sAudioPortGeneration = AUDIOPORT_GENERATION_INIT; 3728 } 3729 return generation; 3730 } 3731 3732 static int updateAudioPortCache(ArrayList<AudioPort> ports, ArrayList<AudioPatch> patches, 3733 ArrayList<AudioPort> previousPorts) { 3734 sAudioPortEventHandler.init(); 3735 synchronized (sAudioPortGeneration) { 3736 3737 if (sAudioPortGeneration == AUDIOPORT_GENERATION_INIT) { 3738 int[] patchGeneration = new int[1]; 3739 int[] portGeneration = new int[1]; 3740 int status; 3741 ArrayList<AudioPort> newPorts = new ArrayList<AudioPort>(); 3742 ArrayList<AudioPatch> newPatches = new ArrayList<AudioPatch>(); 3743 3744 do { 3745 newPorts.clear(); 3746 status = AudioSystem.listAudioPorts(newPorts, portGeneration); 3747 if (status != SUCCESS) { 3748 Log.w(TAG, "updateAudioPortCache: listAudioPorts failed"); 3749 return status; 3750 } 3751 newPatches.clear(); 3752 status = AudioSystem.listAudioPatches(newPatches, patchGeneration); 3753 if (status != SUCCESS) { 3754 Log.w(TAG, "updateAudioPortCache: listAudioPatches failed"); 3755 return status; 3756 } 3757 } while (patchGeneration[0] != portGeneration[0]); 3758 3759 for (int i = 0; i < newPatches.size(); i++) { 3760 for (int j = 0; j < newPatches.get(i).sources().length; j++) { 3761 AudioPortConfig portCfg = updatePortConfig(newPatches.get(i).sources()[j], 3762 newPorts); 3763 newPatches.get(i).sources()[j] = portCfg; 3764 } 3765 for (int j = 0; j < newPatches.get(i).sinks().length; j++) { 3766 AudioPortConfig portCfg = updatePortConfig(newPatches.get(i).sinks()[j], 3767 newPorts); 3768 newPatches.get(i).sinks()[j] = portCfg; 3769 } 3770 } 3771 for (Iterator<AudioPatch> i = newPatches.iterator(); i.hasNext(); ) { 3772 AudioPatch newPatch = i.next(); 3773 boolean hasInvalidPort = false; 3774 for (AudioPortConfig portCfg : newPatch.sources()) { 3775 if (portCfg == null) { 3776 hasInvalidPort = true; 3777 break; 3778 } 3779 } 3780 for (AudioPortConfig portCfg : newPatch.sinks()) { 3781 if (portCfg == null) { 3782 hasInvalidPort = true; 3783 break; 3784 } 3785 } 3786 if (hasInvalidPort) { 3787 // Temporarily remove patches with invalid ports. One who created the patch 3788 // is responsible for dealing with the port change. 3789 i.remove(); 3790 } 3791 } 3792 3793 sPreviousAudioPortsCached = sAudioPortsCached; 3794 sAudioPortsCached = newPorts; 3795 sAudioPatchesCached = newPatches; 3796 sAudioPortGeneration = portGeneration[0]; 3797 } 3798 if (ports != null) { 3799 ports.clear(); 3800 ports.addAll(sAudioPortsCached); 3801 } 3802 if (patches != null) { 3803 patches.clear(); 3804 patches.addAll(sAudioPatchesCached); 3805 } 3806 if (previousPorts != null) { 3807 previousPorts.clear(); 3808 previousPorts.addAll(sPreviousAudioPortsCached); 3809 } 3810 } 3811 return SUCCESS; 3812 } 3813 3814 static AudioPortConfig updatePortConfig(AudioPortConfig portCfg, ArrayList<AudioPort> ports) { 3815 AudioPort port = portCfg.port(); 3816 int k; 3817 for (k = 0; k < ports.size(); k++) { 3818 // compare handles because the port returned by JNI is not of the correct 3819 // subclass 3820 if (ports.get(k).handle().equals(port.handle())) { 3821 port = ports.get(k); 3822 break; 3823 } 3824 } 3825 if (k == ports.size()) { 3826 // this hould never happen 3827 Log.e(TAG, "updatePortConfig port not found for handle: "+port.handle().id()); 3828 return null; 3829 } 3830 AudioGainConfig gainCfg = portCfg.gain(); 3831 if (gainCfg != null) { 3832 AudioGain gain = port.gain(gainCfg.index()); 3833 gainCfg = gain.buildConfig(gainCfg.mode(), 3834 gainCfg.channelMask(), 3835 gainCfg.values(), 3836 gainCfg.rampDurationMs()); 3837 } 3838 return port.buildConfig(portCfg.samplingRate(), 3839 portCfg.channelMask(), 3840 portCfg.format(), 3841 gainCfg); 3842 } 3843 3844 private OnAmPortUpdateListener mPortListener = null; 3845 3846 /** 3847 * The message sent to apps when the contents of the device list changes if they provide 3848 * a {#link Handler} object to addOnAudioDeviceConnectionListener(). 3849 */ 3850 private final static int MSG_DEVICES_CALLBACK_REGISTERED = 0; 3851 private final static int MSG_DEVICES_DEVICES_ADDED = 1; 3852 private final static int MSG_DEVICES_DEVICES_REMOVED = 2; 3853 3854 /** 3855 * The list of {@link AudioDeviceCallback} objects to receive add/remove notifications. 3856 */ 3857 private ArrayMap<AudioDeviceCallback, NativeEventHandlerDelegate> 3858 mDeviceCallbacks = 3859 new ArrayMap<AudioDeviceCallback, NativeEventHandlerDelegate>(); 3860 3861 /** 3862 * The following are flags to allow users of {@link AudioManager#getDevices(int)} to filter 3863 * the results list to only those device types they are interested in. 3864 */ 3865 /** 3866 * Specifies to the {@link AudioManager#getDevices(int)} method to include 3867 * source (i.e. input) audio devices. 3868 */ 3869 public static final int GET_DEVICES_INPUTS = 0x0001; 3870 3871 /** 3872 * Specifies to the {@link AudioManager#getDevices(int)} method to include 3873 * sink (i.e. output) audio devices. 3874 */ 3875 public static final int GET_DEVICES_OUTPUTS = 0x0002; 3876 3877 /** 3878 * Specifies to the {@link AudioManager#getDevices(int)} method to include both 3879 * source and sink devices. 3880 */ 3881 public static final int GET_DEVICES_ALL = GET_DEVICES_OUTPUTS | GET_DEVICES_INPUTS; 3882 3883 /** 3884 * Determines if a given AudioDevicePort meets the specified filter criteria. 3885 * @param port The port to test. 3886 * @param flags A set of bitflags specifying the criteria to test. 3887 * @see {@link GET_DEVICES_OUTPUTS} and {@link GET_DEVICES_INPUTS} 3888 **/ 3889 private static boolean checkFlags(AudioDevicePort port, int flags) { 3890 return port.role() == AudioPort.ROLE_SINK && (flags & GET_DEVICES_OUTPUTS) != 0 || 3891 port.role() == AudioPort.ROLE_SOURCE && (flags & GET_DEVICES_INPUTS) != 0; 3892 } 3893 3894 private static boolean checkTypes(AudioDevicePort port) { 3895 return AudioDeviceInfo.convertInternalDeviceToDeviceType(port.type()) != 3896 AudioDeviceInfo.TYPE_UNKNOWN && 3897 port.type() != AudioSystem.DEVICE_IN_BACK_MIC; 3898 } 3899 3900 /** 3901 * Returns an array of {@link AudioDeviceInfo} objects corresponding to the audio devices 3902 * currently connected to the system and meeting the criteria specified in the 3903 * <code>flags</code> parameter. 3904 * @param flags A set of bitflags specifying the criteria to test. 3905 * @see {@link GET_DEVICES_OUTPUTS}, {@link GET_DEVICES_INPUTS} and {@link GET_DEVICES_ALL}. 3906 * @return A (possibly zero-length) array of AudioDeviceInfo objects. 3907 */ 3908 public AudioDeviceInfo[] getDevices(int flags) { 3909 return getDevicesStatic(flags); 3910 } 3911 3912 /** 3913 * Does the actual computation to generate an array of (externally-visible) AudioDeviceInfo 3914 * objects from the current (internal) AudioDevicePort list. 3915 */ 3916 private static AudioDeviceInfo[] 3917 infoListFromPortList(ArrayList<AudioDevicePort> ports, int flags) { 3918 3919 // figure out how many AudioDeviceInfo we need space for... 3920 int numRecs = 0; 3921 for (AudioDevicePort port : ports) { 3922 if (checkTypes(port) && checkFlags(port, flags)) { 3923 numRecs++; 3924 } 3925 } 3926 3927 // Now load them up... 3928 AudioDeviceInfo[] deviceList = new AudioDeviceInfo[numRecs]; 3929 int slot = 0; 3930 for (AudioDevicePort port : ports) { 3931 if (checkTypes(port) && checkFlags(port, flags)) { 3932 deviceList[slot++] = new AudioDeviceInfo(port); 3933 } 3934 } 3935 3936 return deviceList; 3937 } 3938 3939 /* 3940 * Calculate the list of ports that are in ports_B, but not in ports_A. This is used by 3941 * the add/remove callback mechanism to provide a list of the newly added or removed devices 3942 * rather than the whole list and make the app figure it out. 3943 * Note that calling this method with: 3944 * ports_A == PREVIOUS_ports and ports_B == CURRENT_ports will calculated ADDED ports. 3945 * ports_A == CURRENT_ports and ports_B == PREVIOUS_ports will calculated REMOVED ports. 3946 */ 3947 private static AudioDeviceInfo[] calcListDeltas( 3948 ArrayList<AudioDevicePort> ports_A, ArrayList<AudioDevicePort> ports_B, int flags) { 3949 3950 ArrayList<AudioDevicePort> delta_ports = new ArrayList<AudioDevicePort>(); 3951 3952 AudioDevicePort cur_port = null; 3953 for (int cur_index = 0; cur_index < ports_B.size(); cur_index++) { 3954 boolean cur_port_found = false; 3955 cur_port = ports_B.get(cur_index); 3956 for (int prev_index = 0; 3957 prev_index < ports_A.size() && !cur_port_found; 3958 prev_index++) { 3959 cur_port_found = (cur_port.id() == ports_A.get(prev_index).id()); 3960 } 3961 3962 if (!cur_port_found) { 3963 delta_ports.add(cur_port); 3964 } 3965 } 3966 3967 return infoListFromPortList(delta_ports, flags); 3968 } 3969 3970 /** 3971 * Generates a list of AudioDeviceInfo objects corresponding to the audio devices currently 3972 * connected to the system and meeting the criteria specified in the <code>flags</code> 3973 * parameter. 3974 * This is an internal function. The public API front is getDevices(int). 3975 * @param flags A set of bitflags specifying the criteria to test. 3976 * @see {@link GET_DEVICES_OUTPUTS}, {@link GET_DEVICES_INPUTS} and {@link GET_DEVICES_ALL}. 3977 * @return A (possibly zero-length) array of AudioDeviceInfo objects. 3978 * @hide 3979 */ 3980 public static AudioDeviceInfo[] getDevicesStatic(int flags) { 3981 ArrayList<AudioDevicePort> ports = new ArrayList<AudioDevicePort>(); 3982 int status = AudioManager.listAudioDevicePorts(ports); 3983 if (status != AudioManager.SUCCESS) { 3984 // fail and bail! 3985 return new AudioDeviceInfo[0]; // Always return an array. 3986 } 3987 3988 return infoListFromPortList(ports, flags); 3989 } 3990 3991 /** 3992 * Registers an {@link AudioDeviceCallback} object to receive notifications of changes 3993 * to the set of connected audio devices. 3994 * @param callback The {@link AudioDeviceCallback} object to receive connect/disconnect 3995 * notifications. 3996 * @param handler Specifies the {@link Handler} object for the thread on which to execute 3997 * the callback. If <code>null</code>, the {@link Handler} associated with the main 3998 * {@link Looper} will be used. 3999 */ 4000 public void registerAudioDeviceCallback(AudioDeviceCallback callback, 4001 android.os.Handler handler) { 4002 synchronized (mDeviceCallbacks) { 4003 if (callback != null && !mDeviceCallbacks.containsKey(callback)) { 4004 if (mDeviceCallbacks.size() == 0) { 4005 if (mPortListener == null) { 4006 mPortListener = new OnAmPortUpdateListener(); 4007 } 4008 registerAudioPortUpdateListener(mPortListener); 4009 } 4010 NativeEventHandlerDelegate delegate = 4011 new NativeEventHandlerDelegate(callback, handler); 4012 mDeviceCallbacks.put(callback, delegate); 4013 broadcastDeviceListChange(delegate.getHandler()); 4014 } 4015 } 4016 } 4017 4018 /** 4019 * Unregisters an {@link AudioDeviceCallback} object which has been previously registered 4020 * to receive notifications of changes to the set of connected audio devices. 4021 * @param callback The {@link AudioDeviceCallback} object that was previously registered 4022 * with {@link AudioManager#registerAudioDeviceCallback) to be unregistered. 4023 */ 4024 public void unregisterAudioDeviceCallback(AudioDeviceCallback callback) { 4025 synchronized (mDeviceCallbacks) { 4026 if (mDeviceCallbacks.containsKey(callback)) { 4027 mDeviceCallbacks.remove(callback); 4028 if (mDeviceCallbacks.size() == 0) { 4029 unregisterAudioPortUpdateListener(mPortListener); 4030 } 4031 } 4032 } 4033 } 4034 4035 // Since we need to calculate the changes since THE LAST NOTIFICATION, and not since the 4036 // (unpredictable) last time updateAudioPortCache() was called by someone, keep a list 4037 // of the ports that exist at the time of the last notification. 4038 private ArrayList<AudioDevicePort> mPreviousPorts = new ArrayList<AudioDevicePort>(); 4039 4040 /** 4041 * Internal method to compute and generate add/remove messages and then send to any 4042 * registered callbacks. 4043 */ 4044 private void broadcastDeviceListChange(Handler handler) { 4045 int status; 4046 4047 // Get the new current set of ports 4048 ArrayList<AudioDevicePort> current_ports = new ArrayList<AudioDevicePort>(); 4049 status = AudioManager.listAudioDevicePorts(current_ports); 4050 if (status != AudioManager.SUCCESS) { 4051 return; 4052 } 4053 4054 if (handler != null) { 4055 // This is the callback for the registration, so send the current list 4056 AudioDeviceInfo[] deviceList = 4057 infoListFromPortList(current_ports, GET_DEVICES_ALL); 4058 handler.sendMessage( 4059 Message.obtain(handler, MSG_DEVICES_CALLBACK_REGISTERED, deviceList)); 4060 } else { 4061 AudioDeviceInfo[] added_devices = 4062 calcListDeltas(mPreviousPorts, current_ports, GET_DEVICES_ALL); 4063 AudioDeviceInfo[] removed_devices = 4064 calcListDeltas(current_ports, mPreviousPorts, GET_DEVICES_ALL); 4065 4066 if (added_devices.length != 0 || removed_devices.length != 0) { 4067 synchronized (mDeviceCallbacks) { 4068 for (int i = 0; i < mDeviceCallbacks.size(); i++) { 4069 handler = mDeviceCallbacks.valueAt(i).getHandler(); 4070 if (handler != null) { 4071 if (added_devices.length != 0) { 4072 handler.sendMessage(Message.obtain(handler, 4073 MSG_DEVICES_DEVICES_ADDED, 4074 added_devices)); 4075 } 4076 if (removed_devices.length != 0) { 4077 handler.sendMessage(Message.obtain(handler, 4078 MSG_DEVICES_DEVICES_REMOVED, 4079 removed_devices)); 4080 } 4081 } 4082 } 4083 } 4084 } 4085 } 4086 4087 mPreviousPorts = current_ports; 4088 } 4089 4090 /** 4091 * Handles Port list update notifications from the AudioManager 4092 */ 4093 private class OnAmPortUpdateListener implements AudioManager.OnAudioPortUpdateListener { 4094 static final String TAG = "OnAmPortUpdateListener"; 4095 public void onAudioPortListUpdate(AudioPort[] portList) { 4096 broadcastDeviceListChange(null); 4097 } 4098 4099 /** 4100 * Callback method called upon audio patch list update. 4101 * Note: We don't do anything with Patches at this time, so ignore this notification. 4102 * @param patchList the updated list of audio patches. 4103 */ 4104 public void onAudioPatchListUpdate(AudioPatch[] patchList) {} 4105 4106 /** 4107 * Callback method called when the mediaserver dies 4108 */ 4109 public void onServiceDied() { 4110 broadcastDeviceListChange(null); 4111 } 4112 } 4113 4114 //--------------------------------------------------------- 4115 // Inner classes 4116 //-------------------- 4117 /** 4118 * Helper class to handle the forwarding of native events to the appropriate listener 4119 * (potentially) handled in a different thread. 4120 */ 4121 private class NativeEventHandlerDelegate { 4122 private final Handler mHandler; 4123 4124 NativeEventHandlerDelegate(final AudioDeviceCallback callback, 4125 Handler handler) { 4126 // find the looper for our new event handler 4127 Looper looper; 4128 if (handler != null) { 4129 looper = handler.getLooper(); 4130 } else { 4131 // no given handler, use the looper the addListener call was called in 4132 looper = Looper.getMainLooper(); 4133 } 4134 4135 // construct the event handler with this looper 4136 if (looper != null) { 4137 // implement the event handler delegate 4138 mHandler = new Handler(looper) { 4139 @Override 4140 public void handleMessage(Message msg) { 4141 switch(msg.what) { 4142 case MSG_DEVICES_CALLBACK_REGISTERED: 4143 case MSG_DEVICES_DEVICES_ADDED: 4144 if (callback != null) { 4145 callback.onAudioDevicesAdded((AudioDeviceInfo[])msg.obj); 4146 } 4147 break; 4148 4149 case MSG_DEVICES_DEVICES_REMOVED: 4150 if (callback != null) { 4151 callback.onAudioDevicesRemoved((AudioDeviceInfo[])msg.obj); 4152 } 4153 break; 4154 4155 default: 4156 Log.e(TAG, "Unknown native event type: " + msg.what); 4157 break; 4158 } 4159 } 4160 }; 4161 } else { 4162 mHandler = null; 4163 } 4164 } 4165 4166 Handler getHandler() { 4167 return mHandler; 4168 } 4169 } 4170 } 4171