AudioManager.java revision b1fbaaccb656ef09a8770c28df15e3e91a452e64
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 17package android.media; 18 19import android.annotation.SdkConstant; 20import android.annotation.SdkConstant.SdkConstantType; 21import android.app.PendingIntent; 22import android.bluetooth.BluetoothDevice; 23import android.content.ComponentName; 24import android.content.Context; 25import android.content.Intent; 26import android.os.Binder; 27import android.os.Handler; 28import android.os.IBinder; 29import android.os.Looper; 30import android.os.Message; 31import android.os.RemoteException; 32import android.os.SystemClock; 33import android.os.ServiceManager; 34import android.provider.Settings; 35import android.util.Log; 36import android.view.KeyEvent; 37import android.view.VolumePanel; 38 39import java.util.HashMap; 40 41/** 42 * AudioManager provides access to volume and ringer mode control. 43 * <p> 44 * Use <code>Context.getSystemService(Context.AUDIO_SERVICE)</code> to get 45 * an instance of this class. 46 */ 47public class AudioManager { 48 49 private final Context mContext; 50 private long mVolumeKeyUpTime; 51 private final boolean mUseMasterVolume; 52 private static String TAG = "AudioManager"; 53 54 /** 55 * Broadcast intent, a hint for applications that audio is about to become 56 * 'noisy' due to a change in audio outputs. For example, this intent may 57 * be sent when a wired headset is unplugged, or when an A2DP audio 58 * sink is disconnected, and the audio system is about to automatically 59 * switch audio route to the speaker. Applications that are controlling 60 * audio streams may consider pausing, reducing volume or some other action 61 * on receipt of this intent so as not to surprise the user with audio 62 * from the speaker. 63 */ 64 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 65 public static final String ACTION_AUDIO_BECOMING_NOISY = "android.media.AUDIO_BECOMING_NOISY"; 66 67 /** 68 * Sticky broadcast intent action indicating that the ringer mode has 69 * changed. Includes the new ringer mode. 70 * 71 * @see #EXTRA_RINGER_MODE 72 */ 73 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 74 public static final String RINGER_MODE_CHANGED_ACTION = "android.media.RINGER_MODE_CHANGED"; 75 76 /** 77 * The new ringer mode. 78 * 79 * @see #RINGER_MODE_CHANGED_ACTION 80 * @see #RINGER_MODE_NORMAL 81 * @see #RINGER_MODE_SILENT 82 * @see #RINGER_MODE_VIBRATE 83 */ 84 public static final String EXTRA_RINGER_MODE = "android.media.EXTRA_RINGER_MODE"; 85 86 /** 87 * Broadcast intent action indicating that the vibrate setting has 88 * changed. Includes the vibrate type and its new setting. 89 * 90 * @see #EXTRA_VIBRATE_TYPE 91 * @see #EXTRA_VIBRATE_SETTING 92 * @deprecated Applications should maintain their own vibrate policy based on 93 * current ringer mode and listen to {@link #RINGER_MODE_CHANGED_ACTION} instead. 94 */ 95 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 96 public static final String VIBRATE_SETTING_CHANGED_ACTION = 97 "android.media.VIBRATE_SETTING_CHANGED"; 98 99 /** 100 * @hide Broadcast intent when the volume for a particular stream type changes. 101 * Includes the stream, the new volume and previous volumes 102 * 103 * @see #EXTRA_VOLUME_STREAM_TYPE 104 * @see #EXTRA_VOLUME_STREAM_VALUE 105 * @see #EXTRA_PREV_VOLUME_STREAM_VALUE 106 */ 107 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 108 public static final String VOLUME_CHANGED_ACTION = "android.media.VOLUME_CHANGED_ACTION"; 109 110 /** 111 * @hide Broadcast intent when the master volume changes. 112 * Includes the new volume 113 * 114 * @see #EXTRA_MASTER_VOLUME_VALUE 115 * @see #EXTRA_PREV_MASTER_VOLUME_VALUE 116 */ 117 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 118 public static final String MASTER_VOLUME_CHANGED_ACTION = 119 "android.media.MASTER_VOLUME_CHANGED_ACTION"; 120 121 /** 122 * @hide Broadcast intent when the master mute state changes. 123 * Includes the the new volume 124 * 125 * @see #EXTRA_MASTER_VOLUME_MUTED 126 */ 127 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 128 public static final String MASTER_MUTE_CHANGED_ACTION = 129 "android.media.MASTER_MUTE_CHANGED_ACTION"; 130 131 /** 132 * The new vibrate setting for a particular type. 133 * 134 * @see #VIBRATE_SETTING_CHANGED_ACTION 135 * @see #EXTRA_VIBRATE_TYPE 136 * @see #VIBRATE_SETTING_ON 137 * @see #VIBRATE_SETTING_OFF 138 * @see #VIBRATE_SETTING_ONLY_SILENT 139 * @deprecated Applications should maintain their own vibrate policy based on 140 * current ringer mode and listen to {@link #RINGER_MODE_CHANGED_ACTION} instead. 141 */ 142 public static final String EXTRA_VIBRATE_SETTING = "android.media.EXTRA_VIBRATE_SETTING"; 143 144 /** 145 * The vibrate type whose setting has changed. 146 * 147 * @see #VIBRATE_SETTING_CHANGED_ACTION 148 * @see #VIBRATE_TYPE_NOTIFICATION 149 * @see #VIBRATE_TYPE_RINGER 150 * @deprecated Applications should maintain their own vibrate policy based on 151 * current ringer mode and listen to {@link #RINGER_MODE_CHANGED_ACTION} instead. 152 */ 153 public static final String EXTRA_VIBRATE_TYPE = "android.media.EXTRA_VIBRATE_TYPE"; 154 155 /** 156 * @hide The stream type for the volume changed intent. 157 */ 158 public static final String EXTRA_VOLUME_STREAM_TYPE = "android.media.EXTRA_VOLUME_STREAM_TYPE"; 159 160 /** 161 * @hide The volume associated with the stream for the volume changed intent. 162 */ 163 public static final String EXTRA_VOLUME_STREAM_VALUE = 164 "android.media.EXTRA_VOLUME_STREAM_VALUE"; 165 166 /** 167 * @hide The previous volume associated with the stream for the volume changed intent. 168 */ 169 public static final String EXTRA_PREV_VOLUME_STREAM_VALUE = 170 "android.media.EXTRA_PREV_VOLUME_STREAM_VALUE"; 171 172 /** 173 * @hide The new master volume value for the master volume changed intent. 174 * Value is integer between 0 and 100 inclusive. 175 */ 176 public static final String EXTRA_MASTER_VOLUME_VALUE = 177 "android.media.EXTRA_MASTER_VOLUME_VALUE"; 178 179 /** 180 * @hide The previous master volume value for the master volume changed intent. 181 * Value is integer between 0 and 100 inclusive. 182 */ 183 public static final String EXTRA_PREV_MASTER_VOLUME_VALUE = 184 "android.media.EXTRA_PREV_MASTER_VOLUME_VALUE"; 185 186 /** 187 * @hide The new master volume mute state for the master mute changed intent. 188 * Value is boolean 189 */ 190 public static final String EXTRA_MASTER_VOLUME_MUTED = 191 "android.media.EXTRA_MASTER_VOLUME_MUTED"; 192 193 /** The audio stream for phone calls */ 194 public static final int STREAM_VOICE_CALL = AudioSystem.STREAM_VOICE_CALL; 195 /** The audio stream for system sounds */ 196 public static final int STREAM_SYSTEM = AudioSystem.STREAM_SYSTEM; 197 /** The audio stream for the phone ring */ 198 public static final int STREAM_RING = AudioSystem.STREAM_RING; 199 /** The audio stream for music playback */ 200 public static final int STREAM_MUSIC = AudioSystem.STREAM_MUSIC; 201 /** The audio stream for alarms */ 202 public static final int STREAM_ALARM = AudioSystem.STREAM_ALARM; 203 /** The audio stream for notifications */ 204 public static final int STREAM_NOTIFICATION = AudioSystem.STREAM_NOTIFICATION; 205 /** @hide The audio stream for phone calls when connected to bluetooth */ 206 public static final int STREAM_BLUETOOTH_SCO = AudioSystem.STREAM_BLUETOOTH_SCO; 207 /** @hide The audio stream for enforced system sounds in certain countries (e.g camera in Japan) */ 208 public static final int STREAM_SYSTEM_ENFORCED = AudioSystem.STREAM_SYSTEM_ENFORCED; 209 /** The audio stream for DTMF Tones */ 210 public static final int STREAM_DTMF = AudioSystem.STREAM_DTMF; 211 /** @hide The audio stream for text to speech (TTS) */ 212 public static final int STREAM_TTS = AudioSystem.STREAM_TTS; 213 /** Number of audio streams */ 214 /** 215 * @deprecated Use AudioSystem.getNumStreamTypes() instead 216 */ 217 @Deprecated public static final int NUM_STREAMS = AudioSystem.NUM_STREAMS; 218 219 220 /** @hide Default volume index values for audio streams */ 221 public static final int[] DEFAULT_STREAM_VOLUME = new int[] { 222 4, // STREAM_VOICE_CALL 223 7, // STREAM_SYSTEM 224 5, // STREAM_RING 225 11, // STREAM_MUSIC 226 6, // STREAM_ALARM 227 5, // STREAM_NOTIFICATION 228 7, // STREAM_BLUETOOTH_SCO 229 7, // STREAM_SYSTEM_ENFORCED 230 11, // STREAM_DTMF 231 11 // STREAM_TTS 232 }; 233 234 /** 235 * Increase the ringer volume. 236 * 237 * @see #adjustVolume(int, int) 238 * @see #adjustStreamVolume(int, int, int) 239 */ 240 public static final int ADJUST_RAISE = 1; 241 242 /** 243 * Decrease the ringer volume. 244 * 245 * @see #adjustVolume(int, int) 246 * @see #adjustStreamVolume(int, int, int) 247 */ 248 public static final int ADJUST_LOWER = -1; 249 250 /** 251 * Maintain the previous ringer volume. This may be useful when needing to 252 * show the volume toast without actually modifying the volume. 253 * 254 * @see #adjustVolume(int, int) 255 * @see #adjustStreamVolume(int, int, int) 256 */ 257 public static final int ADJUST_SAME = 0; 258 259 // Flags should be powers of 2! 260 261 /** 262 * Show a toast containing the current volume. 263 * 264 * @see #adjustStreamVolume(int, int, int) 265 * @see #adjustVolume(int, int) 266 * @see #setStreamVolume(int, int, int) 267 * @see #setRingerMode(int) 268 */ 269 public static final int FLAG_SHOW_UI = 1 << 0; 270 271 /** 272 * Whether to include ringer modes as possible options when changing volume. 273 * For example, if true and volume level is 0 and the volume is adjusted 274 * with {@link #ADJUST_LOWER}, then the ringer mode may switch the silent or 275 * vibrate mode. 276 * <p> 277 * By default this is on for the ring stream. If this flag is included, 278 * this behavior will be present regardless of the stream type being 279 * affected by the ringer mode. 280 * 281 * @see #adjustVolume(int, int) 282 * @see #adjustStreamVolume(int, int, int) 283 */ 284 public static final int FLAG_ALLOW_RINGER_MODES = 1 << 1; 285 286 /** 287 * Whether to play a sound when changing the volume. 288 * <p> 289 * If this is given to {@link #adjustVolume(int, int)} or 290 * {@link #adjustSuggestedStreamVolume(int, int, int)}, it may be ignored 291 * in some cases (for example, the decided stream type is not 292 * {@link AudioManager#STREAM_RING}, or the volume is being adjusted 293 * downward). 294 * 295 * @see #adjustStreamVolume(int, int, int) 296 * @see #adjustVolume(int, int) 297 * @see #setStreamVolume(int, int, int) 298 */ 299 public static final int FLAG_PLAY_SOUND = 1 << 2; 300 301 /** 302 * Removes any sounds/vibrate that may be in the queue, or are playing (related to 303 * changing volume). 304 */ 305 public static final int FLAG_REMOVE_SOUND_AND_VIBRATE = 1 << 3; 306 307 /** 308 * Whether to vibrate if going into the vibrate ringer mode. 309 */ 310 public static final int FLAG_VIBRATE = 1 << 4; 311 312 /** 313 * Ringer mode that will be silent and will not vibrate. (This overrides the 314 * vibrate setting.) 315 * 316 * @see #setRingerMode(int) 317 * @see #getRingerMode() 318 */ 319 public static final int RINGER_MODE_SILENT = 0; 320 321 /** 322 * Ringer mode that will be silent and will vibrate. (This will cause the 323 * phone ringer to always vibrate, but the notification vibrate to only 324 * vibrate if set.) 325 * 326 * @see #setRingerMode(int) 327 * @see #getRingerMode() 328 */ 329 public static final int RINGER_MODE_VIBRATE = 1; 330 331 /** 332 * Ringer mode that may be audible and may vibrate. It will be audible if 333 * the volume before changing out of this mode was audible. It will vibrate 334 * if the vibrate setting is on. 335 * 336 * @see #setRingerMode(int) 337 * @see #getRingerMode() 338 */ 339 public static final int RINGER_MODE_NORMAL = 2; 340 341 // maximum valid ringer mode value. Values must start from 0 and be contiguous. 342 private static final int RINGER_MODE_MAX = RINGER_MODE_NORMAL; 343 344 /** 345 * Vibrate type that corresponds to the ringer. 346 * 347 * @see #setVibrateSetting(int, int) 348 * @see #getVibrateSetting(int) 349 * @see #shouldVibrate(int) 350 * @deprecated Applications should maintain their own vibrate policy based on 351 * current ringer mode that can be queried via {@link #getRingerMode()}. 352 */ 353 public static final int VIBRATE_TYPE_RINGER = 0; 354 355 /** 356 * Vibrate type that corresponds to notifications. 357 * 358 * @see #setVibrateSetting(int, int) 359 * @see #getVibrateSetting(int) 360 * @see #shouldVibrate(int) 361 * @deprecated Applications should maintain their own vibrate policy based on 362 * current ringer mode that can be queried via {@link #getRingerMode()}. 363 */ 364 public static final int VIBRATE_TYPE_NOTIFICATION = 1; 365 366 /** 367 * Vibrate setting that suggests to never vibrate. 368 * 369 * @see #setVibrateSetting(int, int) 370 * @see #getVibrateSetting(int) 371 * @deprecated Applications should maintain their own vibrate policy based on 372 * current ringer mode that can be queried via {@link #getRingerMode()}. 373 */ 374 public static final int VIBRATE_SETTING_OFF = 0; 375 376 /** 377 * Vibrate setting that suggests to vibrate when possible. 378 * 379 * @see #setVibrateSetting(int, int) 380 * @see #getVibrateSetting(int) 381 * @deprecated Applications should maintain their own vibrate policy based on 382 * current ringer mode that can be queried via {@link #getRingerMode()}. 383 */ 384 public static final int VIBRATE_SETTING_ON = 1; 385 386 /** 387 * Vibrate setting that suggests to only vibrate when in the vibrate ringer 388 * mode. 389 * 390 * @see #setVibrateSetting(int, int) 391 * @see #getVibrateSetting(int) 392 * @deprecated Applications should maintain their own vibrate policy based on 393 * current ringer mode that can be queried via {@link #getRingerMode()}. 394 */ 395 public static final int VIBRATE_SETTING_ONLY_SILENT = 2; 396 397 /** 398 * Suggests using the default stream type. This may not be used in all 399 * places a stream type is needed. 400 */ 401 public static final int USE_DEFAULT_STREAM_TYPE = Integer.MIN_VALUE; 402 403 private static IAudioService sService; 404 405 /** 406 * @hide 407 */ 408 public AudioManager(Context context) { 409 mContext = context; 410 mUseMasterVolume = mContext.getResources().getBoolean( 411 com.android.internal.R.bool.config_useMasterVolume); 412 } 413 414 private static IAudioService getService() 415 { 416 if (sService != null) { 417 return sService; 418 } 419 IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE); 420 sService = IAudioService.Stub.asInterface(b); 421 return sService; 422 } 423 424 /** 425 * @hide 426 */ 427 public void preDispatchKeyEvent(KeyEvent event, int stream) { 428 /* 429 * If the user hits another key within the play sound delay, then 430 * cancel the sound 431 */ 432 int keyCode = event.getKeyCode(); 433 if (keyCode != KeyEvent.KEYCODE_VOLUME_DOWN && keyCode != KeyEvent.KEYCODE_VOLUME_UP 434 && keyCode != KeyEvent.KEYCODE_VOLUME_MUTE 435 && mVolumeKeyUpTime + VolumePanel.PLAY_SOUND_DELAY 436 > SystemClock.uptimeMillis()) { 437 /* 438 * The user has hit another key during the delay (e.g., 300ms) 439 * since the last volume key up, so cancel any sounds. 440 */ 441 if (mUseMasterVolume) { 442 adjustMasterVolume(ADJUST_SAME, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE); 443 } else { 444 adjustSuggestedStreamVolume(ADJUST_SAME, 445 stream, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE); 446 } 447 } 448 } 449 450 /** 451 * @hide 452 */ 453 public void handleKeyDown(KeyEvent event, int stream) { 454 int keyCode = event.getKeyCode(); 455 switch (keyCode) { 456 case KeyEvent.KEYCODE_VOLUME_UP: 457 case KeyEvent.KEYCODE_VOLUME_DOWN: 458 /* 459 * Adjust the volume in on key down since it is more 460 * responsive to the user. 461 */ 462 int flags = FLAG_SHOW_UI | FLAG_VIBRATE; 463 if (mUseMasterVolume) { 464 adjustMasterVolume( 465 keyCode == KeyEvent.KEYCODE_VOLUME_UP 466 ? ADJUST_RAISE 467 : ADJUST_LOWER, 468 flags); 469 } else { 470 adjustSuggestedStreamVolume( 471 keyCode == KeyEvent.KEYCODE_VOLUME_UP 472 ? ADJUST_RAISE 473 : ADJUST_LOWER, 474 stream, 475 flags); 476 } 477 break; 478 case KeyEvent.KEYCODE_VOLUME_MUTE: 479 if (event.getRepeatCount() == 0) { 480 if (mUseMasterVolume) { 481 setMasterMute(!isMasterMute()); 482 } else { 483 // TODO: Actually handle MUTE. 484 } 485 } 486 break; 487 } 488 } 489 490 /** 491 * @hide 492 */ 493 public void handleKeyUp(KeyEvent event, int stream) { 494 int keyCode = event.getKeyCode(); 495 switch (keyCode) { 496 case KeyEvent.KEYCODE_VOLUME_UP: 497 case KeyEvent.KEYCODE_VOLUME_DOWN: 498 /* 499 * Play a sound. This is done on key up since we don't want the 500 * sound to play when a user holds down volume down to mute. 501 */ 502 if (mUseMasterVolume) { 503 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { 504 adjustMasterVolume(ADJUST_SAME, FLAG_PLAY_SOUND); 505 } 506 } else { 507 int flags = FLAG_PLAY_SOUND; 508 adjustSuggestedStreamVolume( 509 ADJUST_SAME, 510 stream, 511 flags); 512 } 513 514 mVolumeKeyUpTime = SystemClock.uptimeMillis(); 515 break; 516 } 517 } 518 519 /** 520 * Adjusts the volume of a particular stream by one step in a direction. 521 * <p> 522 * This method should only be used by applications that replace the platform-wide 523 * management of audio settings or the main telephony application. 524 * 525 * @param streamType The stream type to adjust. One of {@link #STREAM_VOICE_CALL}, 526 * {@link #STREAM_SYSTEM}, {@link #STREAM_RING}, {@link #STREAM_MUSIC} or 527 * {@link #STREAM_ALARM} 528 * @param direction The direction to adjust the volume. One of 529 * {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, or 530 * {@link #ADJUST_SAME}. 531 * @param flags One or more flags. 532 * @see #adjustVolume(int, int) 533 * @see #setStreamVolume(int, int, int) 534 */ 535 public void adjustStreamVolume(int streamType, int direction, int flags) { 536 IAudioService service = getService(); 537 try { 538 if (mUseMasterVolume) { 539 service.adjustMasterVolume(direction, flags); 540 } else { 541 service.adjustStreamVolume(streamType, direction, flags); 542 } 543 } catch (RemoteException e) { 544 Log.e(TAG, "Dead object in adjustStreamVolume", e); 545 } 546 } 547 548 /** 549 * Adjusts the volume of the most relevant stream. For example, if a call is 550 * active, it will have the highest priority regardless of if the in-call 551 * screen is showing. Another example, if music is playing in the background 552 * and a call is not active, the music stream will be adjusted. 553 * <p> 554 * This method should only be used by applications that replace the platform-wide 555 * management of audio settings or the main telephony application. 556 * 557 * @param direction The direction to adjust the volume. One of 558 * {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, or 559 * {@link #ADJUST_SAME}. 560 * @param flags One or more flags. 561 * @see #adjustSuggestedStreamVolume(int, int, int) 562 * @see #adjustStreamVolume(int, int, int) 563 * @see #setStreamVolume(int, int, int) 564 */ 565 public void adjustVolume(int direction, int flags) { 566 IAudioService service = getService(); 567 try { 568 if (mUseMasterVolume) { 569 service.adjustMasterVolume(direction, flags); 570 } else { 571 service.adjustVolume(direction, flags); 572 } 573 } catch (RemoteException e) { 574 Log.e(TAG, "Dead object in adjustVolume", e); 575 } 576 } 577 578 /** 579 * Adjusts the volume of the most relevant stream, or the given fallback 580 * stream. 581 * <p> 582 * This method should only be used by applications that replace the platform-wide 583 * management of audio settings or the main telephony application. 584 * 585 * @param direction The direction to adjust the volume. One of 586 * {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, or 587 * {@link #ADJUST_SAME}. 588 * @param suggestedStreamType The stream type that will be used if there 589 * isn't a relevant stream. {@link #USE_DEFAULT_STREAM_TYPE} is valid here. 590 * @param flags One or more flags. 591 * @see #adjustVolume(int, int) 592 * @see #adjustStreamVolume(int, int, int) 593 * @see #setStreamVolume(int, int, int) 594 */ 595 public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags) { 596 IAudioService service = getService(); 597 try { 598 if (mUseMasterVolume) { 599 service.adjustMasterVolume(direction, flags); 600 } else { 601 service.adjustSuggestedStreamVolume(direction, suggestedStreamType, flags); 602 } 603 } catch (RemoteException e) { 604 Log.e(TAG, "Dead object in adjustSuggestedStreamVolume", e); 605 } 606 } 607 608 /** 609 * Adjusts the master volume for the device's audio amplifier. 610 * <p> 611 * 612 * @param steps The number of volume steps to adjust. A positive 613 * value will raise the volume. 614 * @param flags One or more flags. 615 * @hide 616 */ 617 public void adjustMasterVolume(int steps, int flags) { 618 IAudioService service = getService(); 619 try { 620 service.adjustMasterVolume(steps, flags); 621 } catch (RemoteException e) { 622 Log.e(TAG, "Dead object in adjustMasterVolume", e); 623 } 624 } 625 626 /** 627 * Returns the current ringtone mode. 628 * 629 * @return The current ringtone mode, one of {@link #RINGER_MODE_NORMAL}, 630 * {@link #RINGER_MODE_SILENT}, or {@link #RINGER_MODE_VIBRATE}. 631 * @see #setRingerMode(int) 632 */ 633 public int getRingerMode() { 634 IAudioService service = getService(); 635 try { 636 return service.getRingerMode(); 637 } catch (RemoteException e) { 638 Log.e(TAG, "Dead object in getRingerMode", e); 639 return RINGER_MODE_NORMAL; 640 } 641 } 642 643 /** 644 * Checks valid ringer mode values. 645 * 646 * @return true if the ringer mode indicated is valid, false otherwise. 647 * 648 * @see #setRingerMode(int) 649 * @hide 650 */ 651 public static boolean isValidRingerMode(int ringerMode) { 652 if (ringerMode < 0 || ringerMode > RINGER_MODE_MAX) { 653 return false; 654 } 655 return true; 656 } 657 658 /** 659 * Returns the maximum volume index for a particular stream. 660 * 661 * @param streamType The stream type whose maximum volume index is returned. 662 * @return The maximum valid volume index for the stream. 663 * @see #getStreamVolume(int) 664 */ 665 public int getStreamMaxVolume(int streamType) { 666 IAudioService service = getService(); 667 try { 668 if (mUseMasterVolume) { 669 return service.getMasterMaxVolume(); 670 } else { 671 return service.getStreamMaxVolume(streamType); 672 } 673 } catch (RemoteException e) { 674 Log.e(TAG, "Dead object in getStreamMaxVolume", e); 675 return 0; 676 } 677 } 678 679 /** 680 * Returns the current volume index for a particular stream. 681 * 682 * @param streamType The stream type whose volume index is returned. 683 * @return The current volume index for the stream. 684 * @see #getStreamMaxVolume(int) 685 * @see #setStreamVolume(int, int, int) 686 */ 687 public int getStreamVolume(int streamType) { 688 IAudioService service = getService(); 689 try { 690 if (mUseMasterVolume) { 691 return service.getMasterVolume(); 692 } else { 693 return service.getStreamVolume(streamType); 694 } 695 } catch (RemoteException e) { 696 Log.e(TAG, "Dead object in getStreamVolume", e); 697 return 0; 698 } 699 } 700 701 /** 702 * Get last audible volume before stream was muted. 703 * 704 * @hide 705 */ 706 public int getLastAudibleStreamVolume(int streamType) { 707 IAudioService service = getService(); 708 try { 709 if (mUseMasterVolume) { 710 return service.getLastAudibleMasterVolume(); 711 } else { 712 return service.getLastAudibleStreamVolume(streamType); 713 } 714 } catch (RemoteException e) { 715 Log.e(TAG, "Dead object in getLastAudibleStreamVolume", e); 716 return 0; 717 } 718 } 719 720 /** 721 * Get the stream type whose volume is driving the UI sounds volume. 722 * UI sounds are screen lock/unlock, camera shutter, key clicks... 723 * @hide 724 */ 725 public int getMasterStreamType() { 726 IAudioService service = getService(); 727 try { 728 return service.getMasterStreamType(); 729 } catch (RemoteException e) { 730 Log.e(TAG, "Dead object in getMasterStreamType", e); 731 return STREAM_RING; 732 } 733 } 734 735 /** 736 * Sets the ringer mode. 737 * <p> 738 * Silent mode will mute the volume and will not vibrate. Vibrate mode will 739 * mute the volume and vibrate. Normal mode will be audible and may vibrate 740 * according to user settings. 741 * 742 * @param ringerMode The ringer mode, one of {@link #RINGER_MODE_NORMAL}, 743 * {@link #RINGER_MODE_SILENT}, or {@link #RINGER_MODE_VIBRATE}. 744 * @see #getRingerMode() 745 */ 746 public void setRingerMode(int ringerMode) { 747 if (!isValidRingerMode(ringerMode)) { 748 return; 749 } 750 IAudioService service = getService(); 751 try { 752 service.setRingerMode(ringerMode); 753 } catch (RemoteException e) { 754 Log.e(TAG, "Dead object in setRingerMode", e); 755 } 756 } 757 758 /** 759 * Sets the volume index for a particular stream. 760 * 761 * @param streamType The stream whose volume index should be set. 762 * @param index The volume index to set. See 763 * {@link #getStreamMaxVolume(int)} for the largest valid value. 764 * @param flags One or more flags. 765 * @see #getStreamMaxVolume(int) 766 * @see #getStreamVolume(int) 767 */ 768 public void setStreamVolume(int streamType, int index, int flags) { 769 IAudioService service = getService(); 770 try { 771 if (mUseMasterVolume) { 772 service.setMasterVolume(index, flags); 773 } else { 774 service.setStreamVolume(streamType, index, flags); 775 } 776 } catch (RemoteException e) { 777 Log.e(TAG, "Dead object in setStreamVolume", e); 778 } 779 } 780 781 /** 782 * Returns the maximum volume index for master volume. 783 * 784 * @hide 785 */ 786 public int getMasterMaxVolume() { 787 IAudioService service = getService(); 788 try { 789 return service.getMasterMaxVolume(); 790 } catch (RemoteException e) { 791 Log.e(TAG, "Dead object in getMasterMaxVolume", e); 792 return 0; 793 } 794 } 795 796 /** 797 * Returns the current volume index for master volume. 798 * 799 * @return The current volume index for master volume. 800 * @hide 801 */ 802 public int getMasterVolume() { 803 IAudioService service = getService(); 804 try { 805 return service.getMasterVolume(); 806 } catch (RemoteException e) { 807 Log.e(TAG, "Dead object in getMasterVolume", e); 808 return 0; 809 } 810 } 811 812 /** 813 * Get last audible volume before master volume was muted. 814 * 815 * @hide 816 */ 817 public int getLastAudibleMasterVolume() { 818 IAudioService service = getService(); 819 try { 820 return service.getLastAudibleMasterVolume(); 821 } catch (RemoteException e) { 822 Log.e(TAG, "Dead object in getLastAudibleMasterVolume", e); 823 return 0; 824 } 825 } 826 827 /** 828 * Sets the volume index for master volume. 829 * 830 * @param index The volume index to set. See 831 * {@link #getMasterMaxVolume(int)} for the largest valid value. 832 * @param flags One or more flags. 833 * @see #getMasterMaxVolume(int) 834 * @see #getMasterVolume(int) 835 * @hide 836 */ 837 public void setMasterVolume(int index, int flags) { 838 IAudioService service = getService(); 839 try { 840 service.setMasterVolume(index, flags); 841 } catch (RemoteException e) { 842 Log.e(TAG, "Dead object in setMasterVolume", e); 843 } 844 } 845 846 /** 847 * Solo or unsolo a particular stream. All other streams are muted. 848 * <p> 849 * The solo command is protected against client process death: if a process 850 * with an active solo request on a stream dies, all streams that were muted 851 * because of this request will be unmuted automatically. 852 * <p> 853 * The solo requests for a given stream are cumulative: the AudioManager 854 * can receive several solo requests from one or more clients and the stream 855 * will be unsoloed only when the same number of unsolo requests are received. 856 * <p> 857 * For a better user experience, applications MUST unsolo a soloed stream 858 * in onPause() and solo is again in onResume() if appropriate. 859 * 860 * @param streamType The stream to be soloed/unsoloed. 861 * @param state The required solo state: true for solo ON, false for solo OFF 862 */ 863 public void setStreamSolo(int streamType, boolean state) { 864 IAudioService service = getService(); 865 try { 866 service.setStreamSolo(streamType, state, mICallBack); 867 } catch (RemoteException e) { 868 Log.e(TAG, "Dead object in setStreamSolo", e); 869 } 870 } 871 872 /** 873 * Mute or unmute an audio stream. 874 * <p> 875 * The mute command is protected against client process death: if a process 876 * with an active mute request on a stream dies, this stream will be unmuted 877 * automatically. 878 * <p> 879 * The mute requests for a given stream are cumulative: the AudioManager 880 * can receive several mute requests from one or more clients and the stream 881 * will be unmuted only when the same number of unmute requests are received. 882 * <p> 883 * For a better user experience, applications MUST unmute a muted stream 884 * in onPause() and mute is again in onResume() if appropriate. 885 * <p> 886 * This method should only be used by applications that replace the platform-wide 887 * management of audio settings or the main telephony application. 888 * 889 * @param streamType The stream to be muted/unmuted. 890 * @param state The required mute state: true for mute ON, false for mute OFF 891 */ 892 public void setStreamMute(int streamType, boolean state) { 893 IAudioService service = getService(); 894 try { 895 service.setStreamMute(streamType, state, mICallBack); 896 } catch (RemoteException e) { 897 Log.e(TAG, "Dead object in setStreamMute", e); 898 } 899 } 900 901 /** 902 * get stream mute state. 903 * 904 * @hide 905 */ 906 public boolean isStreamMute(int streamType) { 907 IAudioService service = getService(); 908 try { 909 return service.isStreamMute(streamType); 910 } catch (RemoteException e) { 911 Log.e(TAG, "Dead object in isStreamMute", e); 912 return false; 913 } 914 } 915 916 /** 917 * set master mute state. 918 * 919 * @hide 920 */ 921 public void setMasterMute(boolean state) { 922 setMasterMute(state, FLAG_SHOW_UI); 923 } 924 925 /** 926 * set master mute state with optional flags. 927 * 928 * @hide 929 */ 930 public void setMasterMute(boolean state, int flags) { 931 IAudioService service = getService(); 932 try { 933 service.setMasterMute(state, flags, mICallBack); 934 } catch (RemoteException e) { 935 Log.e(TAG, "Dead object in setMasterMute", e); 936 } 937 } 938 939 /** 940 * get master mute state. 941 * 942 * @hide 943 */ 944 public boolean isMasterMute() { 945 IAudioService service = getService(); 946 try { 947 return service.isMasterMute(); 948 } catch (RemoteException e) { 949 Log.e(TAG, "Dead object in isMasterMute", e); 950 return false; 951 } 952 } 953 954 /** 955 * forces the stream controlled by hard volume keys 956 * specifying streamType == -1 releases control to the 957 * logic. 958 * 959 * @hide 960 */ 961 public void forceVolumeControlStream(int streamType) { 962 IAudioService service = getService(); 963 try { 964 service.forceVolumeControlStream(streamType, mICallBack); 965 } catch (RemoteException e) { 966 Log.e(TAG, "Dead object in forceVolumeControlStream", e); 967 } 968 } 969 970 /** 971 * Returns whether a particular type should vibrate according to user 972 * settings and the current ringer mode. 973 * <p> 974 * This shouldn't be needed by most clients that use notifications to 975 * vibrate. The notification manager will not vibrate if the policy doesn't 976 * allow it, so the client should always set a vibrate pattern and let the 977 * notification manager control whether or not to actually vibrate. 978 * 979 * @param vibrateType The type of vibrate. One of 980 * {@link #VIBRATE_TYPE_NOTIFICATION} or 981 * {@link #VIBRATE_TYPE_RINGER}. 982 * @return Whether the type should vibrate at the instant this method is 983 * called. 984 * @see #setVibrateSetting(int, int) 985 * @see #getVibrateSetting(int) 986 * @deprecated Applications should maintain their own vibrate policy based on 987 * current ringer mode that can be queried via {@link #getRingerMode()}. 988 */ 989 public boolean shouldVibrate(int vibrateType) { 990 IAudioService service = getService(); 991 try { 992 return service.shouldVibrate(vibrateType); 993 } catch (RemoteException e) { 994 Log.e(TAG, "Dead object in shouldVibrate", e); 995 return false; 996 } 997 } 998 999 /** 1000 * Returns whether the user's vibrate setting for a vibrate type. 1001 * <p> 1002 * This shouldn't be needed by most clients that want to vibrate, instead 1003 * see {@link #shouldVibrate(int)}. 1004 * 1005 * @param vibrateType The type of vibrate. One of 1006 * {@link #VIBRATE_TYPE_NOTIFICATION} or 1007 * {@link #VIBRATE_TYPE_RINGER}. 1008 * @return The vibrate setting, one of {@link #VIBRATE_SETTING_ON}, 1009 * {@link #VIBRATE_SETTING_OFF}, or 1010 * {@link #VIBRATE_SETTING_ONLY_SILENT}. 1011 * @see #setVibrateSetting(int, int) 1012 * @see #shouldVibrate(int) 1013 * @deprecated Applications should maintain their own vibrate policy based on 1014 * current ringer mode that can be queried via {@link #getRingerMode()}. 1015 */ 1016 public int getVibrateSetting(int vibrateType) { 1017 IAudioService service = getService(); 1018 try { 1019 return service.getVibrateSetting(vibrateType); 1020 } catch (RemoteException e) { 1021 Log.e(TAG, "Dead object in getVibrateSetting", e); 1022 return VIBRATE_SETTING_OFF; 1023 } 1024 } 1025 1026 /** 1027 * Sets the setting for when the vibrate type should vibrate. 1028 * <p> 1029 * This method should only be used by applications that replace the platform-wide 1030 * management of audio settings or the main telephony application. 1031 * 1032 * @param vibrateType The type of vibrate. One of 1033 * {@link #VIBRATE_TYPE_NOTIFICATION} or 1034 * {@link #VIBRATE_TYPE_RINGER}. 1035 * @param vibrateSetting The vibrate setting, one of 1036 * {@link #VIBRATE_SETTING_ON}, 1037 * {@link #VIBRATE_SETTING_OFF}, or 1038 * {@link #VIBRATE_SETTING_ONLY_SILENT}. 1039 * @see #getVibrateSetting(int) 1040 * @see #shouldVibrate(int) 1041 * @deprecated Applications should maintain their own vibrate policy based on 1042 * current ringer mode that can be queried via {@link #getRingerMode()}. 1043 */ 1044 public void setVibrateSetting(int vibrateType, int vibrateSetting) { 1045 IAudioService service = getService(); 1046 try { 1047 service.setVibrateSetting(vibrateType, vibrateSetting); 1048 } catch (RemoteException e) { 1049 Log.e(TAG, "Dead object in setVibrateSetting", e); 1050 } 1051 } 1052 1053 /** 1054 * Sets the speakerphone on or off. 1055 * <p> 1056 * This method should only be used by applications that replace the platform-wide 1057 * management of audio settings or the main telephony application. 1058 * 1059 * @param on set <var>true</var> to turn on speakerphone; 1060 * <var>false</var> to turn it off 1061 */ 1062 public void setSpeakerphoneOn(boolean on){ 1063 IAudioService service = getService(); 1064 try { 1065 service.setSpeakerphoneOn(on); 1066 } catch (RemoteException e) { 1067 Log.e(TAG, "Dead object in setSpeakerphoneOn", e); 1068 } 1069 } 1070 1071 /** 1072 * Checks whether the speakerphone is on or off. 1073 * 1074 * @return true if speakerphone is on, false if it's off 1075 */ 1076 public boolean isSpeakerphoneOn() { 1077 IAudioService service = getService(); 1078 try { 1079 return service.isSpeakerphoneOn(); 1080 } catch (RemoteException e) { 1081 Log.e(TAG, "Dead object in isSpeakerphoneOn", e); 1082 return false; 1083 } 1084 } 1085 1086 //==================================================================== 1087 // Bluetooth SCO control 1088 /** 1089 * Sticky broadcast intent action indicating that the bluetoooth SCO audio 1090 * connection state has changed. The intent contains on extra {@link #EXTRA_SCO_AUDIO_STATE} 1091 * indicating the new state which is either {@link #SCO_AUDIO_STATE_DISCONNECTED} 1092 * or {@link #SCO_AUDIO_STATE_CONNECTED} 1093 * 1094 * @see #startBluetoothSco() 1095 * @deprecated Use {@link #ACTION_SCO_AUDIO_STATE_UPDATED} instead 1096 */ 1097 @Deprecated 1098 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1099 public static final String ACTION_SCO_AUDIO_STATE_CHANGED = 1100 "android.media.SCO_AUDIO_STATE_CHANGED"; 1101 1102 /** 1103 * Sticky broadcast intent action indicating that the bluetoooth SCO audio 1104 * connection state has been updated. 1105 * <p>This intent has two extras: 1106 * <ul> 1107 * <li> {@link #EXTRA_SCO_AUDIO_STATE} - The new SCO audio state. </li> 1108 * <li> {@link #EXTRA_SCO_AUDIO_PREVIOUS_STATE}- The previous SCO audio state. </li> 1109 * </ul> 1110 * <p> EXTRA_SCO_AUDIO_STATE or EXTRA_SCO_AUDIO_PREVIOUS_STATE can be any of: 1111 * <ul> 1112 * <li> {@link #SCO_AUDIO_STATE_DISCONNECTED}, </li> 1113 * <li> {@link #SCO_AUDIO_STATE_CONNECTING} or </li> 1114 * <li> {@link #SCO_AUDIO_STATE_CONNECTED}, </li> 1115 * </ul> 1116 * @see #startBluetoothSco() 1117 */ 1118 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1119 public static final String ACTION_SCO_AUDIO_STATE_UPDATED = 1120 "android.media.ACTION_SCO_AUDIO_STATE_UPDATED"; 1121 1122 /** 1123 * Extra for intent {@link #ACTION_SCO_AUDIO_STATE_CHANGED} or 1124 * {@link #ACTION_SCO_AUDIO_STATE_UPDATED} containing the new bluetooth SCO connection state. 1125 */ 1126 public static final String EXTRA_SCO_AUDIO_STATE = 1127 "android.media.extra.SCO_AUDIO_STATE"; 1128 1129 /** 1130 * Extra for intent {@link #ACTION_SCO_AUDIO_STATE_UPDATED} containing the previous 1131 * bluetooth SCO connection state. 1132 */ 1133 public static final String EXTRA_SCO_AUDIO_PREVIOUS_STATE = 1134 "android.media.extra.SCO_AUDIO_PREVIOUS_STATE"; 1135 1136 /** 1137 * Value for extra EXTRA_SCO_AUDIO_STATE or EXTRA_SCO_AUDIO_PREVIOUS_STATE 1138 * indicating that the SCO audio channel is not established 1139 */ 1140 public static final int SCO_AUDIO_STATE_DISCONNECTED = 0; 1141 /** 1142 * Value for extra {@link #EXTRA_SCO_AUDIO_STATE} or {@link #EXTRA_SCO_AUDIO_PREVIOUS_STATE} 1143 * indicating that the SCO audio channel is established 1144 */ 1145 public static final int SCO_AUDIO_STATE_CONNECTED = 1; 1146 /** 1147 * Value for extra EXTRA_SCO_AUDIO_STATE or EXTRA_SCO_AUDIO_PREVIOUS_STATE 1148 * indicating that the SCO audio channel is being established 1149 */ 1150 public static final int SCO_AUDIO_STATE_CONNECTING = 2; 1151 /** 1152 * Value for extra EXTRA_SCO_AUDIO_STATE indicating that 1153 * there was an error trying to obtain the state 1154 */ 1155 public static final int SCO_AUDIO_STATE_ERROR = -1; 1156 1157 1158 /** 1159 * Indicates if current platform supports use of SCO for off call use cases. 1160 * Application wanted to use bluetooth SCO audio when the phone is not in call 1161 * must first call thsi method to make sure that the platform supports this 1162 * feature. 1163 * @return true if bluetooth SCO can be used for audio when not in call 1164 * false otherwise 1165 * @see #startBluetoothSco() 1166 */ 1167 public boolean isBluetoothScoAvailableOffCall() { 1168 return mContext.getResources().getBoolean( 1169 com.android.internal.R.bool.config_bluetooth_sco_off_call); 1170 } 1171 1172 /** 1173 * Start bluetooth SCO audio connection. 1174 * <p>Requires Permission: 1175 * {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}. 1176 * <p>This method can be used by applications wanting to send and received audio 1177 * to/from a bluetooth SCO headset while the phone is not in call. 1178 * <p>As the SCO connection establishment can take several seconds, 1179 * applications should not rely on the connection to be available when the method 1180 * returns but instead register to receive the intent {@link #ACTION_SCO_AUDIO_STATE_UPDATED} 1181 * and wait for the state to be {@link #SCO_AUDIO_STATE_CONNECTED}. 1182 * <p>As the ACTION_SCO_AUDIO_STATE_UPDATED intent is sticky, the application can check the SCO 1183 * audio state before calling startBluetoothSco() by reading the intent returned by the receiver 1184 * registration. If the state is already CONNECTED, no state change will be received via the 1185 * intent after calling startBluetoothSco(). It is however useful to call startBluetoothSco() 1186 * so that the connection stays active in case the current initiator stops the connection. 1187 * <p>Unless the connection is already active as described above, the state will always 1188 * transition from DISCONNECTED to CONNECTING and then either to CONNECTED if the connection 1189 * succeeds or back to DISCONNECTED if the connection fails (e.g no headset is connected). 1190 * <p>When finished with the SCO connection or if the establishment fails, the application must 1191 * call {@link #stopBluetoothSco()} to clear the request and turn down the bluetooth connection. 1192 * <p>Even if a SCO connection is established, the following restrictions apply on audio 1193 * output streams so that they can be routed to SCO headset: 1194 * <ul> 1195 * <li> the stream type must be {@link #STREAM_VOICE_CALL} </li> 1196 * <li> the format must be mono </li> 1197 * <li> the sampling must be 16kHz or 8kHz </li> 1198 * </ul> 1199 * <p>The following restrictions apply on input streams: 1200 * <ul> 1201 * <li> the format must be mono </li> 1202 * <li> the sampling must be 8kHz </li> 1203 * </ul> 1204 * <p>Note that the phone application always has the priority on the usage of the SCO 1205 * connection for telephony. If this method is called while the phone is in call 1206 * it will be ignored. Similarly, if a call is received or sent while an application 1207 * is using the SCO connection, the connection will be lost for the application and NOT 1208 * returned automatically when the call ends. 1209 * @see #stopBluetoothSco() 1210 * @see #ACTION_SCO_AUDIO_STATE_UPDATED 1211 */ 1212 public void startBluetoothSco(){ 1213 IAudioService service = getService(); 1214 try { 1215 service.startBluetoothSco(mICallBack); 1216 } catch (RemoteException e) { 1217 Log.e(TAG, "Dead object in startBluetoothSco", e); 1218 } 1219 } 1220 1221 /** 1222 * Stop bluetooth SCO audio connection. 1223 * <p>Requires Permission: 1224 * {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}. 1225 * <p>This method must be called by applications having requested the use of 1226 * bluetooth SCO audio with {@link #startBluetoothSco()} 1227 * when finished with the SCO connection or if connection fails. 1228 * @see #startBluetoothSco() 1229 */ 1230 public void stopBluetoothSco(){ 1231 IAudioService service = getService(); 1232 try { 1233 service.stopBluetoothSco(mICallBack); 1234 } catch (RemoteException e) { 1235 Log.e(TAG, "Dead object in stopBluetoothSco", e); 1236 } 1237 } 1238 1239 /** 1240 * Request use of Bluetooth SCO headset for communications. 1241 * <p> 1242 * This method should only be used by applications that replace the platform-wide 1243 * management of audio settings or the main telephony application. 1244 * 1245 * @param on set <var>true</var> to use bluetooth SCO for communications; 1246 * <var>false</var> to not use bluetooth SCO for communications 1247 */ 1248 public void setBluetoothScoOn(boolean on){ 1249 IAudioService service = getService(); 1250 try { 1251 service.setBluetoothScoOn(on); 1252 } catch (RemoteException e) { 1253 Log.e(TAG, "Dead object in setBluetoothScoOn", e); 1254 } 1255 } 1256 1257 /** 1258 * Checks whether communications use Bluetooth SCO. 1259 * 1260 * @return true if SCO is used for communications; 1261 * false if otherwise 1262 */ 1263 public boolean isBluetoothScoOn() { 1264 IAudioService service = getService(); 1265 try { 1266 return service.isBluetoothScoOn(); 1267 } catch (RemoteException e) { 1268 Log.e(TAG, "Dead object in isBluetoothScoOn", e); 1269 return false; 1270 } 1271 } 1272 1273 /** 1274 * Allow or disallow use of Bluetooth A2DP for media. 1275 * <p>The default behavior of the system is to use A2DP for media playback whenever an A2DP sink 1276 * is connected. Applications can use this method to override this behavior. 1277 * Note that the request will not persist after a wired headset or an A2DP sink is connected or 1278 * disconnected: 1279 * - Connection of an A2DP sink automatically enables use of A2DP. 1280 * - Connection of a wired headset automatically disables use of A2DP. 1281 * - Disconnection of a wired headset automatically enables use of A2DP if an A2DP sink is 1282 * connected. 1283 * <p>Requires Permission: 1284 * {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}. 1285 * @param on set <var>true</var> to allow use of A2DP for media (default). 1286 * <var>false</var> to disallow use of A2DP for media. 1287 * @deprecated Do not use. 1288 */ 1289 @Deprecated public void setBluetoothA2dpOn(boolean on){ 1290 IAudioService service = getService(); 1291 try { 1292 service.setBluetoothA2dpOn(on); 1293 } catch (RemoteException e) { 1294 Log.e(TAG, "Dead object in setBluetoothA2dpOn", e); 1295 } 1296 } 1297 1298 /** 1299 * Checks whether use of A2DP sinks is enabled for media. 1300 * 1301 * @return true if use of A2DP is enabled for media, false otherwise. 1302 */ 1303 public boolean isBluetoothA2dpOn() { 1304 IAudioService service = getService(); 1305 try { 1306 return service.isBluetoothA2dpOn(); 1307 } catch (RemoteException e) { 1308 Log.e(TAG, "Dead object in isBluetoothA2dpOn", e); 1309 return false; 1310 } 1311 } 1312 1313 /** 1314 * Sets audio routing to the wired headset on or off. 1315 * 1316 * @param on set <var>true</var> to route audio to/from wired 1317 * headset; <var>false</var> disable wired headset audio 1318 * @deprecated Do not use. 1319 */ 1320 @Deprecated public void setWiredHeadsetOn(boolean on){ 1321 } 1322 1323 /** 1324 * Checks whether a wired headset is connected or not. 1325 * <p>This is not a valid indication that audio playback is 1326 * actually over the wired headset as audio routing depends on other conditions. 1327 * 1328 * @return true if a wired headset is connected. 1329 * false if otherwise 1330 * @deprecated Use only to check is a headset is connected or not. 1331 */ 1332 public boolean isWiredHeadsetOn() { 1333 if (AudioSystem.getDeviceConnectionState(DEVICE_OUT_WIRED_HEADSET,"") 1334 == AudioSystem.DEVICE_STATE_UNAVAILABLE && 1335 AudioSystem.getDeviceConnectionState(DEVICE_OUT_WIRED_HEADPHONE,"") 1336 == AudioSystem.DEVICE_STATE_UNAVAILABLE) { 1337 return false; 1338 } else { 1339 return true; 1340 } 1341 } 1342 1343 /** 1344 * Sets the microphone mute on or off. 1345 * <p> 1346 * This method should only be used by applications that replace the platform-wide 1347 * management of audio settings or the main telephony application. 1348 * 1349 * @param on set <var>true</var> to mute the microphone; 1350 * <var>false</var> to turn mute off 1351 */ 1352 public void setMicrophoneMute(boolean on){ 1353 AudioSystem.muteMicrophone(on); 1354 } 1355 1356 /** 1357 * Checks whether the microphone mute is on or off. 1358 * 1359 * @return true if microphone is muted, false if it's not 1360 */ 1361 public boolean isMicrophoneMute() { 1362 return AudioSystem.isMicrophoneMuted(); 1363 } 1364 1365 /** 1366 * Sets the audio mode. 1367 * <p> 1368 * The audio mode encompasses audio routing AND the behavior of 1369 * the telephony layer. Therefore this method should only be used by applications that 1370 * replace the platform-wide management of audio settings or the main telephony application. 1371 * In particular, the {@link #MODE_IN_CALL} mode should only be used by the telephony 1372 * application when it places a phone call, as it will cause signals from the radio layer 1373 * to feed the platform mixer. 1374 * 1375 * @param mode the requested audio mode ({@link #MODE_NORMAL}, {@link #MODE_RINGTONE}, 1376 * {@link #MODE_IN_CALL} or {@link #MODE_IN_COMMUNICATION}). 1377 * Informs the HAL about the current audio state so that 1378 * it can route the audio appropriately. 1379 */ 1380 public void setMode(int mode) { 1381 IAudioService service = getService(); 1382 try { 1383 service.setMode(mode, mICallBack); 1384 } catch (RemoteException e) { 1385 Log.e(TAG, "Dead object in setMode", e); 1386 } 1387 } 1388 1389 /** 1390 * Returns the current audio mode. 1391 * 1392 * @return the current audio mode ({@link #MODE_NORMAL}, {@link #MODE_RINGTONE}, 1393 * {@link #MODE_IN_CALL} or {@link #MODE_IN_COMMUNICATION}). 1394 * Returns the current current audio state from the HAL. 1395 */ 1396 public int getMode() { 1397 IAudioService service = getService(); 1398 try { 1399 return service.getMode(); 1400 } catch (RemoteException e) { 1401 Log.e(TAG, "Dead object in getMode", e); 1402 return MODE_INVALID; 1403 } 1404 } 1405 1406 /* modes for setMode/getMode/setRoute/getRoute */ 1407 /** 1408 * Audio harware modes. 1409 */ 1410 /** 1411 * Invalid audio mode. 1412 */ 1413 public static final int MODE_INVALID = AudioSystem.MODE_INVALID; 1414 /** 1415 * Current audio mode. Used to apply audio routing to current mode. 1416 */ 1417 public static final int MODE_CURRENT = AudioSystem.MODE_CURRENT; 1418 /** 1419 * Normal audio mode: not ringing and no call established. 1420 */ 1421 public static final int MODE_NORMAL = AudioSystem.MODE_NORMAL; 1422 /** 1423 * Ringing audio mode. An incoming is being signaled. 1424 */ 1425 public static final int MODE_RINGTONE = AudioSystem.MODE_RINGTONE; 1426 /** 1427 * In call audio mode. A telephony call is established. 1428 */ 1429 public static final int MODE_IN_CALL = AudioSystem.MODE_IN_CALL; 1430 /** 1431 * In communication audio mode. An audio/video chat or VoIP call is established. 1432 */ 1433 public static final int MODE_IN_COMMUNICATION = AudioSystem.MODE_IN_COMMUNICATION; 1434 1435 /* Routing bits for setRouting/getRouting API */ 1436 /** 1437 * Routing audio output to earpiece 1438 * @deprecated Do not set audio routing directly, use setSpeakerphoneOn(), 1439 * setBluetoothScoOn() methods instead. 1440 */ 1441 @Deprecated public static final int ROUTE_EARPIECE = AudioSystem.ROUTE_EARPIECE; 1442 /** 1443 * Routing audio output to speaker 1444 * @deprecated Do not set audio routing directly, use setSpeakerphoneOn(), 1445 * setBluetoothScoOn() methods instead. 1446 */ 1447 @Deprecated public static final int ROUTE_SPEAKER = AudioSystem.ROUTE_SPEAKER; 1448 /** 1449 * @deprecated use {@link #ROUTE_BLUETOOTH_SCO} 1450 * @deprecated Do not set audio routing directly, use setSpeakerphoneOn(), 1451 * setBluetoothScoOn() methods instead. 1452 */ 1453 @Deprecated public static final int ROUTE_BLUETOOTH = AudioSystem.ROUTE_BLUETOOTH_SCO; 1454 /** 1455 * Routing audio output to bluetooth SCO 1456 * @deprecated Do not set audio routing directly, use setSpeakerphoneOn(), 1457 * setBluetoothScoOn() methods instead. 1458 */ 1459 @Deprecated public static final int ROUTE_BLUETOOTH_SCO = AudioSystem.ROUTE_BLUETOOTH_SCO; 1460 /** 1461 * Routing audio output to headset 1462 * @deprecated Do not set audio routing directly, use setSpeakerphoneOn(), 1463 * setBluetoothScoOn() methods instead. 1464 */ 1465 @Deprecated public static final int ROUTE_HEADSET = AudioSystem.ROUTE_HEADSET; 1466 /** 1467 * Routing audio output to bluetooth A2DP 1468 * @deprecated Do not set audio routing directly, use setSpeakerphoneOn(), 1469 * setBluetoothScoOn() methods instead. 1470 */ 1471 @Deprecated public static final int ROUTE_BLUETOOTH_A2DP = AudioSystem.ROUTE_BLUETOOTH_A2DP; 1472 /** 1473 * Used for mask parameter of {@link #setRouting(int,int,int)}. 1474 * @deprecated Do not set audio routing directly, use setSpeakerphoneOn(), 1475 * setBluetoothScoOn() methods instead. 1476 */ 1477 @Deprecated public static final int ROUTE_ALL = AudioSystem.ROUTE_ALL; 1478 1479 /** 1480 * Sets the audio routing for a specified mode 1481 * 1482 * @param mode audio mode to change route. E.g., MODE_RINGTONE. 1483 * @param routes bit vector of routes requested, created from one or 1484 * more of ROUTE_xxx types. Set bits indicate that route should be on 1485 * @param mask bit vector of routes to change, created from one or more of 1486 * ROUTE_xxx types. Unset bits indicate the route should be left unchanged 1487 * 1488 * @deprecated Do not set audio routing directly, use setSpeakerphoneOn(), 1489 * setBluetoothScoOn() methods instead. 1490 */ 1491 @Deprecated 1492 public void setRouting(int mode, int routes, int mask) { 1493 } 1494 1495 /** 1496 * Returns the current audio routing bit vector for a specified mode. 1497 * 1498 * @param mode audio mode to get route (e.g., MODE_RINGTONE) 1499 * @return an audio route bit vector that can be compared with ROUTE_xxx 1500 * bits 1501 * @deprecated Do not query audio routing directly, use isSpeakerphoneOn(), 1502 * isBluetoothScoOn(), isBluetoothA2dpOn() and isWiredHeadsetOn() methods instead. 1503 */ 1504 @Deprecated 1505 public int getRouting(int mode) { 1506 return -1; 1507 } 1508 1509 /** 1510 * Checks whether any music is active. 1511 * 1512 * @return true if any music tracks are active. 1513 */ 1514 public boolean isMusicActive() { 1515 return AudioSystem.isStreamActive(STREAM_MUSIC, 0); 1516 } 1517 1518 /* 1519 * Sets a generic audio configuration parameter. The use of these parameters 1520 * are platform dependant, see libaudio 1521 * 1522 * ** Temporary interface - DO NOT USE 1523 * 1524 * TODO: Replace with a more generic key:value get/set mechanism 1525 * 1526 * param key name of parameter to set. Must not be null. 1527 * param value value of parameter. Must not be null. 1528 */ 1529 /** 1530 * @hide 1531 * @deprecated Use {@link #setPrameters(String)} instead 1532 */ 1533 @Deprecated public void setParameter(String key, String value) { 1534 setParameters(key+"="+value); 1535 } 1536 1537 /** 1538 * Sets a variable number of parameter values to audio hardware. 1539 * 1540 * @param keyValuePairs list of parameters key value pairs in the form: 1541 * key1=value1;key2=value2;... 1542 * 1543 */ 1544 public void setParameters(String keyValuePairs) { 1545 AudioSystem.setParameters(keyValuePairs); 1546 } 1547 1548 /** 1549 * Sets a varaible number of parameter values to audio hardware. 1550 * 1551 * @param keys list of parameters 1552 * @return list of parameters key value pairs in the form: 1553 * key1=value1;key2=value2;... 1554 */ 1555 public String getParameters(String keys) { 1556 return AudioSystem.getParameters(keys); 1557 } 1558 1559 /* Sound effect identifiers */ 1560 /** 1561 * Keyboard and direction pad click sound 1562 * @see #playSoundEffect(int) 1563 */ 1564 public static final int FX_KEY_CLICK = 0; 1565 /** 1566 * Focus has moved up 1567 * @see #playSoundEffect(int) 1568 */ 1569 public static final int FX_FOCUS_NAVIGATION_UP = 1; 1570 /** 1571 * Focus has moved down 1572 * @see #playSoundEffect(int) 1573 */ 1574 public static final int FX_FOCUS_NAVIGATION_DOWN = 2; 1575 /** 1576 * Focus has moved left 1577 * @see #playSoundEffect(int) 1578 */ 1579 public static final int FX_FOCUS_NAVIGATION_LEFT = 3; 1580 /** 1581 * Focus has moved right 1582 * @see #playSoundEffect(int) 1583 */ 1584 public static final int FX_FOCUS_NAVIGATION_RIGHT = 4; 1585 /** 1586 * IME standard keypress sound 1587 * @see #playSoundEffect(int) 1588 */ 1589 public static final int FX_KEYPRESS_STANDARD = 5; 1590 /** 1591 * IME spacebar keypress sound 1592 * @see #playSoundEffect(int) 1593 */ 1594 public static final int FX_KEYPRESS_SPACEBAR = 6; 1595 /** 1596 * IME delete keypress sound 1597 * @see #playSoundEffect(int) 1598 */ 1599 public static final int FX_KEYPRESS_DELETE = 7; 1600 /** 1601 * IME return_keypress sound 1602 * @see #playSoundEffect(int) 1603 */ 1604 public static final int FX_KEYPRESS_RETURN = 8; 1605 /** 1606 * @hide Number of sound effects 1607 */ 1608 public static final int NUM_SOUND_EFFECTS = 9; 1609 1610 /** 1611 * Plays a sound effect (Key clicks, lid open/close...) 1612 * @param effectType The type of sound effect. One of 1613 * {@link #FX_KEY_CLICK}, 1614 * {@link #FX_FOCUS_NAVIGATION_UP}, 1615 * {@link #FX_FOCUS_NAVIGATION_DOWN}, 1616 * {@link #FX_FOCUS_NAVIGATION_LEFT}, 1617 * {@link #FX_FOCUS_NAVIGATION_RIGHT}, 1618 * {@link #FX_KEYPRESS_STANDARD}, 1619 * {@link #FX_KEYPRESS_SPACEBAR}, 1620 * {@link #FX_KEYPRESS_DELETE}, 1621 * {@link #FX_KEYPRESS_RETURN}, 1622 * NOTE: This version uses the UI settings to determine 1623 * whether sounds are heard or not. 1624 */ 1625 public void playSoundEffect(int effectType) { 1626 if (effectType < 0 || effectType >= NUM_SOUND_EFFECTS) { 1627 return; 1628 } 1629 1630 if (!querySoundEffectsEnabled()) { 1631 return; 1632 } 1633 1634 IAudioService service = getService(); 1635 try { 1636 service.playSoundEffect(effectType); 1637 } catch (RemoteException e) { 1638 Log.e(TAG, "Dead object in playSoundEffect"+e); 1639 } 1640 } 1641 1642 /** 1643 * Plays a sound effect (Key clicks, lid open/close...) 1644 * @param effectType The type of sound effect. One of 1645 * {@link #FX_KEY_CLICK}, 1646 * {@link #FX_FOCUS_NAVIGATION_UP}, 1647 * {@link #FX_FOCUS_NAVIGATION_DOWN}, 1648 * {@link #FX_FOCUS_NAVIGATION_LEFT}, 1649 * {@link #FX_FOCUS_NAVIGATION_RIGHT}, 1650 * {@link #FX_KEYPRESS_STANDARD}, 1651 * {@link #FX_KEYPRESS_SPACEBAR}, 1652 * {@link #FX_KEYPRESS_DELETE}, 1653 * {@link #FX_KEYPRESS_RETURN}, 1654 * @param volume Sound effect volume. 1655 * The volume value is a raw scalar so UI controls should be scaled logarithmically. 1656 * If a volume of -1 is specified, the AudioManager.STREAM_MUSIC stream volume minus 3dB will be used. 1657 * NOTE: This version is for applications that have their own 1658 * settings panel for enabling and controlling volume. 1659 */ 1660 public void playSoundEffect(int effectType, float volume) { 1661 if (effectType < 0 || effectType >= NUM_SOUND_EFFECTS) { 1662 return; 1663 } 1664 1665 IAudioService service = getService(); 1666 try { 1667 service.playSoundEffectVolume(effectType, volume); 1668 } catch (RemoteException e) { 1669 Log.e(TAG, "Dead object in playSoundEffect"+e); 1670 } 1671 } 1672 1673 /** 1674 * Settings has an in memory cache, so this is fast. 1675 */ 1676 private boolean querySoundEffectsEnabled() { 1677 return Settings.System.getInt(mContext.getContentResolver(), Settings.System.SOUND_EFFECTS_ENABLED, 0) != 0; 1678 } 1679 1680 1681 /** 1682 * Load Sound effects. 1683 * This method must be called when sound effects are enabled. 1684 */ 1685 public void loadSoundEffects() { 1686 IAudioService service = getService(); 1687 try { 1688 service.loadSoundEffects(); 1689 } catch (RemoteException e) { 1690 Log.e(TAG, "Dead object in loadSoundEffects"+e); 1691 } 1692 } 1693 1694 /** 1695 * Unload Sound effects. 1696 * This method can be called to free some memory when 1697 * sound effects are disabled. 1698 */ 1699 public void unloadSoundEffects() { 1700 IAudioService service = getService(); 1701 try { 1702 service.unloadSoundEffects(); 1703 } catch (RemoteException e) { 1704 Log.e(TAG, "Dead object in unloadSoundEffects"+e); 1705 } 1706 } 1707 1708 /** 1709 * Used to indicate a gain of audio focus, or a request of audio focus, of unknown duration. 1710 * @see OnAudioFocusChangeListener#onAudioFocusChange(int) 1711 * @see #requestAudioFocus(OnAudioFocusChangeListener, int, int) 1712 */ 1713 public static final int AUDIOFOCUS_GAIN = 1; 1714 /** 1715 * Used to indicate a temporary gain or request of audio focus, anticipated to last a short 1716 * amount of time. Examples of temporary changes are the playback of driving directions, or an 1717 * event notification. 1718 * @see OnAudioFocusChangeListener#onAudioFocusChange(int) 1719 * @see #requestAudioFocus(OnAudioFocusChangeListener, int, int) 1720 */ 1721 public static final int AUDIOFOCUS_GAIN_TRANSIENT = 2; 1722 /** 1723 * Used to indicate a temporary request of audio focus, anticipated to last a short 1724 * amount of time, and where it is acceptable for other audio applications to keep playing 1725 * after having lowered their output level (also referred to as "ducking"). 1726 * Examples of temporary changes are the playback of driving directions where playback of music 1727 * in the background is acceptable. 1728 * @see OnAudioFocusChangeListener#onAudioFocusChange(int) 1729 * @see #requestAudioFocus(OnAudioFocusChangeListener, int, int) 1730 */ 1731 public static final int AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK = 3; 1732 /** 1733 * Used to indicate a loss of audio focus of unknown duration. 1734 * @see OnAudioFocusChangeListener#onAudioFocusChange(int) 1735 */ 1736 public static final int AUDIOFOCUS_LOSS = -1 * AUDIOFOCUS_GAIN; 1737 /** 1738 * Used to indicate a transient loss of audio focus. 1739 * @see OnAudioFocusChangeListener#onAudioFocusChange(int) 1740 */ 1741 public static final int AUDIOFOCUS_LOSS_TRANSIENT = -1 * AUDIOFOCUS_GAIN_TRANSIENT; 1742 /** 1743 * Used to indicate a transient loss of audio focus where the loser of the audio focus can 1744 * lower its output volume if it wants to continue playing (also referred to as "ducking"), as 1745 * the new focus owner doesn't require others to be silent. 1746 * @see OnAudioFocusChangeListener#onAudioFocusChange(int) 1747 */ 1748 public static final int AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK = 1749 -1 * AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK; 1750 1751 /** 1752 * Interface definition for a callback to be invoked when the audio focus of the system is 1753 * updated. 1754 */ 1755 public interface OnAudioFocusChangeListener { 1756 /** 1757 * Called on the listener to notify it the audio focus for this listener has been changed. 1758 * The focusChange value indicates whether the focus was gained, 1759 * whether the focus was lost, and whether that loss is transient, or whether the new focus 1760 * holder will hold it for an unknown amount of time. 1761 * When losing focus, listeners can use the focus change information to decide what 1762 * behavior to adopt when losing focus. A music player could for instance elect to lower 1763 * the volume of its music stream (duck) for transient focus losses, and pause otherwise. 1764 * @param focusChange the type of focus change, one of {@link AudioManager#AUDIOFOCUS_GAIN}, 1765 * {@link AudioManager#AUDIOFOCUS_LOSS}, {@link AudioManager#AUDIOFOCUS_LOSS_TRANSIENT} 1766 * and {@link AudioManager#AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK}. 1767 */ 1768 public void onAudioFocusChange(int focusChange); 1769 } 1770 1771 /** 1772 * Map to convert focus event listener IDs, as used in the AudioService audio focus stack, 1773 * to actual listener objects. 1774 */ 1775 private final HashMap<String, OnAudioFocusChangeListener> mAudioFocusIdListenerMap = 1776 new HashMap<String, OnAudioFocusChangeListener>(); 1777 /** 1778 * Lock to prevent concurrent changes to the list of focus listeners for this AudioManager 1779 * instance. 1780 */ 1781 private final Object mFocusListenerLock = new Object(); 1782 1783 private OnAudioFocusChangeListener findFocusListener(String id) { 1784 return mAudioFocusIdListenerMap.get(id); 1785 } 1786 1787 /** 1788 * Handler for audio focus events coming from the audio service. 1789 */ 1790 private final FocusEventHandlerDelegate mAudioFocusEventHandlerDelegate = 1791 new FocusEventHandlerDelegate(); 1792 1793 /** 1794 * Helper class to handle the forwarding of audio focus events to the appropriate listener 1795 */ 1796 private class FocusEventHandlerDelegate { 1797 private final Handler mHandler; 1798 1799 FocusEventHandlerDelegate() { 1800 Looper looper; 1801 if ((looper = Looper.myLooper()) == null) { 1802 looper = Looper.getMainLooper(); 1803 } 1804 1805 if (looper != null) { 1806 // implement the event handler delegate to receive audio focus events 1807 mHandler = new Handler(looper) { 1808 @Override 1809 public void handleMessage(Message msg) { 1810 OnAudioFocusChangeListener listener = null; 1811 synchronized(mFocusListenerLock) { 1812 listener = findFocusListener((String)msg.obj); 1813 } 1814 if (listener != null) { 1815 listener.onAudioFocusChange(msg.what); 1816 } 1817 } 1818 }; 1819 } else { 1820 mHandler = null; 1821 } 1822 } 1823 1824 Handler getHandler() { 1825 return mHandler; 1826 } 1827 } 1828 1829 private final IAudioFocusDispatcher mAudioFocusDispatcher = new IAudioFocusDispatcher.Stub() { 1830 1831 public void dispatchAudioFocusChange(int focusChange, String id) { 1832 Message m = mAudioFocusEventHandlerDelegate.getHandler().obtainMessage(focusChange, id); 1833 mAudioFocusEventHandlerDelegate.getHandler().sendMessage(m); 1834 } 1835 1836 }; 1837 1838 private String getIdForAudioFocusListener(OnAudioFocusChangeListener l) { 1839 if (l == null) { 1840 return new String(this.toString()); 1841 } else { 1842 return new String(this.toString() + l.toString()); 1843 } 1844 } 1845 1846 /** 1847 * @hide 1848 * Registers a listener to be called when audio focus changes. Calling this method is optional 1849 * before calling {@link #requestAudioFocus(OnAudioFocusChangeListener, int, int)}, as it 1850 * will register the listener as well if it wasn't registered already. 1851 * @param l the listener to be notified of audio focus changes. 1852 */ 1853 public void registerAudioFocusListener(OnAudioFocusChangeListener l) { 1854 synchronized(mFocusListenerLock) { 1855 if (mAudioFocusIdListenerMap.containsKey(getIdForAudioFocusListener(l))) { 1856 return; 1857 } 1858 mAudioFocusIdListenerMap.put(getIdForAudioFocusListener(l), l); 1859 } 1860 } 1861 1862 /** 1863 * @hide 1864 * Causes the specified listener to not be called anymore when focus is gained or lost. 1865 * @param l the listener to unregister. 1866 */ 1867 public void unregisterAudioFocusListener(OnAudioFocusChangeListener l) { 1868 1869 // remove locally 1870 synchronized(mFocusListenerLock) { 1871 mAudioFocusIdListenerMap.remove(getIdForAudioFocusListener(l)); 1872 } 1873 } 1874 1875 1876 /** 1877 * A failed focus change request. 1878 */ 1879 public static final int AUDIOFOCUS_REQUEST_FAILED = 0; 1880 /** 1881 * A successful focus change request. 1882 */ 1883 public static final int AUDIOFOCUS_REQUEST_GRANTED = 1; 1884 1885 1886 /** 1887 * Request audio focus. 1888 * Send a request to obtain the audio focus 1889 * @param l the listener to be notified of audio focus changes 1890 * @param streamType the main audio stream type affected by the focus request 1891 * @param durationHint use {@link #AUDIOFOCUS_GAIN_TRANSIENT} to indicate this focus request 1892 * is temporary, and focus will be abandonned shortly. Examples of transient requests are 1893 * for the playback of driving directions, or notifications sounds. 1894 * Use {@link #AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK} to indicate also that it's ok for 1895 * the previous focus owner to keep playing if it ducks its audio output. 1896 * Use {@link #AUDIOFOCUS_GAIN} for a focus request of unknown duration such 1897 * as the playback of a song or a video. 1898 * @return {@link #AUDIOFOCUS_REQUEST_FAILED} or {@link #AUDIOFOCUS_REQUEST_GRANTED} 1899 */ 1900 public int requestAudioFocus(OnAudioFocusChangeListener l, int streamType, int durationHint) { 1901 int status = AUDIOFOCUS_REQUEST_FAILED; 1902 if ((durationHint < AUDIOFOCUS_GAIN) || (durationHint > AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK)) 1903 { 1904 Log.e(TAG, "Invalid duration hint, audio focus request denied"); 1905 return status; 1906 } 1907 registerAudioFocusListener(l); 1908 //TODO protect request by permission check? 1909 IAudioService service = getService(); 1910 try { 1911 status = service.requestAudioFocus(streamType, durationHint, mICallBack, 1912 mAudioFocusDispatcher, getIdForAudioFocusListener(l), 1913 mContext.getPackageName() /* package name */); 1914 } catch (RemoteException e) { 1915 Log.e(TAG, "Can't call requestAudioFocus() on AudioService due to "+e); 1916 } 1917 return status; 1918 } 1919 1920 /** 1921 * @hide 1922 * Used internally by telephony package to request audio focus. Will cause the focus request 1923 * to be associated with the "voice communication" identifier only used in AudioService 1924 * to identify this use case. 1925 * @param streamType use STREAM_RING for focus requests when ringing, VOICE_CALL for 1926 * the establishment of the call 1927 * @param durationHint the type of focus request. AUDIOFOCUS_GAIN_TRANSIENT is recommended so 1928 * media applications resume after a call 1929 */ 1930 public void requestAudioFocusForCall(int streamType, int durationHint) { 1931 IAudioService service = getService(); 1932 try { 1933 service.requestAudioFocus(streamType, durationHint, mICallBack, null, 1934 AudioService.IN_VOICE_COMM_FOCUS_ID, 1935 "system" /* dump-friendly package name */); 1936 } catch (RemoteException e) { 1937 Log.e(TAG, "Can't call requestAudioFocusForCall() on AudioService due to "+e); 1938 } 1939 } 1940 1941 /** 1942 * @hide 1943 * Used internally by telephony package to abandon audio focus, typically after a call or 1944 * when ringing ends and the call is rejected or not answered. 1945 * Should match one or more calls to {@link #requestAudioFocusForCall(int, int)}. 1946 */ 1947 public void abandonAudioFocusForCall() { 1948 IAudioService service = getService(); 1949 try { 1950 service.abandonAudioFocus(null, AudioService.IN_VOICE_COMM_FOCUS_ID); 1951 } catch (RemoteException e) { 1952 Log.e(TAG, "Can't call abandonAudioFocusForCall() on AudioService due to "+e); 1953 } 1954 } 1955 1956 /** 1957 * Abandon audio focus. Causes the previous focus owner, if any, to receive focus. 1958 * @param l the listener with which focus was requested. 1959 * @return {@link #AUDIOFOCUS_REQUEST_FAILED} or {@link #AUDIOFOCUS_REQUEST_GRANTED} 1960 */ 1961 public int abandonAudioFocus(OnAudioFocusChangeListener l) { 1962 int status = AUDIOFOCUS_REQUEST_FAILED; 1963 unregisterAudioFocusListener(l); 1964 IAudioService service = getService(); 1965 try { 1966 status = service.abandonAudioFocus(mAudioFocusDispatcher, 1967 getIdForAudioFocusListener(l)); 1968 } catch (RemoteException e) { 1969 Log.e(TAG, "Can't call abandonAudioFocus() on AudioService due to "+e); 1970 } 1971 return status; 1972 } 1973 1974 1975 //==================================================================== 1976 // Remote Control 1977 /** 1978 * Register a component to be the sole receiver of MEDIA_BUTTON intents. 1979 * @param eventReceiver identifier of a {@link android.content.BroadcastReceiver} 1980 * that will receive the media button intent. This broadcast receiver must be declared 1981 * in the application manifest. The package of the component must match that of 1982 * the context you're registering from. 1983 */ 1984 public void registerMediaButtonEventReceiver(ComponentName eventReceiver) { 1985 if (eventReceiver == null) { 1986 return; 1987 } 1988 if (!eventReceiver.getPackageName().equals(mContext.getPackageName())) { 1989 Log.e(TAG, "registerMediaButtonEventReceiver() error: " + 1990 "receiver and context package names don't match"); 1991 return; 1992 } 1993 // construct a PendingIntent for the media button and register it 1994 Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON); 1995 // the associated intent will be handled by the component being registered 1996 mediaButtonIntent.setComponent(eventReceiver); 1997 PendingIntent pi = PendingIntent.getBroadcast(mContext, 1998 0/*requestCode, ignored*/, mediaButtonIntent, 0/*flags*/); 1999 registerMediaButtonIntent(pi, eventReceiver); 2000 } 2001 2002 /** 2003 * @hide 2004 * no-op if (pi == null) or (eventReceiver == null) 2005 */ 2006 public void registerMediaButtonIntent(PendingIntent pi, ComponentName eventReceiver) { 2007 if ((pi == null) || (eventReceiver == null)) { 2008 Log.e(TAG, "Cannot call registerMediaButtonIntent() with a null parameter"); 2009 return; 2010 } 2011 IAudioService service = getService(); 2012 try { 2013 // pi != null 2014 service.registerMediaButtonIntent(pi, eventReceiver); 2015 } catch (RemoteException e) { 2016 Log.e(TAG, "Dead object in registerMediaButtonIntent"+e); 2017 } 2018 } 2019 2020 /** 2021 * @hide 2022 * Used internally by telephony package to register an intent receiver for ACTION_MEDIA_BUTTON. 2023 * @param eventReceiver the component that will receive the media button key events, 2024 * no-op if eventReceiver is null 2025 */ 2026 public void registerMediaButtonEventReceiverForCalls(ComponentName eventReceiver) { 2027 if (eventReceiver == null) { 2028 return; 2029 } 2030 IAudioService service = getService(); 2031 try { 2032 // eventReceiver != null 2033 service.registerMediaButtonEventReceiverForCalls(eventReceiver); 2034 } catch (RemoteException e) { 2035 Log.e(TAG, "Dead object in registerMediaButtonEventReceiverForCalls", e); 2036 } 2037 } 2038 2039 /** 2040 * @hide 2041 */ 2042 public void unregisterMediaButtonEventReceiverForCalls() { 2043 IAudioService service = getService(); 2044 try { 2045 service.unregisterMediaButtonEventReceiverForCalls(); 2046 } catch (RemoteException e) { 2047 Log.e(TAG, "Dead object in unregisterMediaButtonEventReceiverForCalls", e); 2048 } 2049 } 2050 2051 /** 2052 * Unregister the receiver of MEDIA_BUTTON intents. 2053 * @param eventReceiver identifier of a {@link android.content.BroadcastReceiver} 2054 * that was registered with {@link #registerMediaButtonEventReceiver(ComponentName)}. 2055 */ 2056 public void unregisterMediaButtonEventReceiver(ComponentName eventReceiver) { 2057 if (eventReceiver == null) { 2058 return; 2059 } 2060 // construct a PendingIntent for the media button and unregister it 2061 Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON); 2062 // the associated intent will be handled by the component being registered 2063 mediaButtonIntent.setComponent(eventReceiver); 2064 PendingIntent pi = PendingIntent.getBroadcast(mContext, 2065 0/*requestCode, ignored*/, mediaButtonIntent, 0/*flags*/); 2066 unregisterMediaButtonIntent(pi, eventReceiver); 2067 } 2068 2069 /** 2070 * @hide 2071 */ 2072 public void unregisterMediaButtonIntent(PendingIntent pi, ComponentName eventReceiver) { 2073 IAudioService service = getService(); 2074 try { 2075 service.unregisterMediaButtonIntent(pi, eventReceiver); 2076 } catch (RemoteException e) { 2077 Log.e(TAG, "Dead object in unregisterMediaButtonIntent"+e); 2078 } 2079 } 2080 2081 /** 2082 * Registers the remote control client for providing information to display on the remote 2083 * controls. 2084 * @param rcClient The remote control client from which remote controls will receive 2085 * information to display. 2086 * @see RemoteControlClient 2087 */ 2088 public void registerRemoteControlClient(RemoteControlClient rcClient) { 2089 if ((rcClient == null) || (rcClient.getRcMediaIntent() == null)) { 2090 return; 2091 } 2092 IAudioService service = getService(); 2093 try { 2094 service.registerRemoteControlClient(rcClient.getRcMediaIntent(), /* mediaIntent */ 2095 rcClient.getIRemoteControlClient(), /* rcClient */ 2096 // used to match media button event receiver and audio focus 2097 mContext.getPackageName()); /* packageName */ 2098 } catch (RemoteException e) { 2099 Log.e(TAG, "Dead object in registerRemoteControlClient"+e); 2100 } 2101 } 2102 2103 /** 2104 * Unregisters the remote control client that was providing information to display on the 2105 * remote controls. 2106 * @param rcClient The remote control client to unregister. 2107 * @see #registerRemoteControlClient(RemoteControlClient) 2108 */ 2109 public void unregisterRemoteControlClient(RemoteControlClient rcClient) { 2110 if ((rcClient == null) || (rcClient.getRcMediaIntent() == null)) { 2111 return; 2112 } 2113 IAudioService service = getService(); 2114 try { 2115 service.unregisterRemoteControlClient(rcClient.getRcMediaIntent(), /* mediaIntent */ 2116 rcClient.getIRemoteControlClient()); /* rcClient */ 2117 } catch (RemoteException e) { 2118 Log.e(TAG, "Dead object in unregisterRemoteControlClient"+e); 2119 } 2120 } 2121 2122 /** 2123 * @hide 2124 * Registers a remote control display that will be sent information by remote control clients. 2125 * @param rcd 2126 */ 2127 public void registerRemoteControlDisplay(IRemoteControlDisplay rcd) { 2128 if (rcd == null) { 2129 return; 2130 } 2131 IAudioService service = getService(); 2132 try { 2133 service.registerRemoteControlDisplay(rcd); 2134 } catch (RemoteException e) { 2135 Log.e(TAG, "Dead object in registerRemoteControlDisplay " + e); 2136 } 2137 } 2138 2139 /** 2140 * @hide 2141 * Unregisters a remote control display that was sent information by remote control clients. 2142 * @param rcd 2143 */ 2144 public void unregisterRemoteControlDisplay(IRemoteControlDisplay rcd) { 2145 if (rcd == null) { 2146 return; 2147 } 2148 IAudioService service = getService(); 2149 try { 2150 service.unregisterRemoteControlDisplay(rcd); 2151 } catch (RemoteException e) { 2152 Log.e(TAG, "Dead object in unregisterRemoteControlDisplay " + e); 2153 } 2154 } 2155 2156 /** 2157 * @hide 2158 * Sets the artwork size a remote control display expects when receiving bitmaps. 2159 * @param rcd 2160 * @param w the maximum width of the expected bitmap. Negative values indicate it is 2161 * useless to send artwork. 2162 * @param h the maximum height of the expected bitmap. Negative values indicate it is 2163 * useless to send artwork. 2164 */ 2165 public void remoteControlDisplayUsesBitmapSize(IRemoteControlDisplay rcd, int w, int h) { 2166 if (rcd == null) { 2167 return; 2168 } 2169 IAudioService service = getService(); 2170 try { 2171 service.remoteControlDisplayUsesBitmapSize(rcd, w, h); 2172 } catch (RemoteException e) { 2173 Log.e(TAG, "Dead object in remoteControlDisplayUsesBitmapSize " + e); 2174 } 2175 } 2176 2177 // FIXME remove because we are not using intents anymore between AudioService and RcDisplay 2178 /** 2179 * @hide 2180 * Broadcast intent action indicating that the displays on the remote controls 2181 * should be updated because a new remote control client is now active. If there is no 2182 * {@link #EXTRA_REMOTE_CONTROL_CLIENT}, the remote control display should be cleared 2183 * because there is no valid client to supply it with information. 2184 * 2185 * @see #EXTRA_REMOTE_CONTROL_CLIENT 2186 */ 2187 public static final String REMOTE_CONTROL_CLIENT_CHANGED = 2188 "android.media.REMOTE_CONTROL_CLIENT_CHANGED"; 2189 2190 // FIXME remove because we are not using intents anymore between AudioService and RcDisplay 2191 /** 2192 * @hide 2193 * The IRemoteControlClientDispatcher monotonically increasing generation counter. 2194 * 2195 * @see #REMOTE_CONTROL_CLIENT_CHANGED_ACTION 2196 */ 2197 public static final String EXTRA_REMOTE_CONTROL_CLIENT_GENERATION = 2198 "android.media.EXTRA_REMOTE_CONTROL_CLIENT_GENERATION"; 2199 2200 // FIXME remove because we are not using intents anymore between AudioService and RcDisplay 2201 /** 2202 * @hide 2203 * The name of the RemoteControlClient. 2204 * This String is passed as the client name when calling methods from the 2205 * IRemoteControlClientDispatcher interface. 2206 * 2207 * @see #REMOTE_CONTROL_CLIENT_CHANGED_ACTION 2208 */ 2209 public static final String EXTRA_REMOTE_CONTROL_CLIENT_NAME = 2210 "android.media.EXTRA_REMOTE_CONTROL_CLIENT_NAME"; 2211 2212 // FIXME remove because we are not using intents anymore between AudioService and RcDisplay 2213 /** 2214 * @hide 2215 * The media button event receiver associated with the RemoteControlClient. 2216 * The {@link android.content.ComponentName} value of the event receiver can be retrieved with 2217 * {@link android.content.ComponentName#unflattenFromString(String)} 2218 * 2219 * @see #REMOTE_CONTROL_CLIENT_CHANGED_ACTION 2220 */ 2221 public static final String EXTRA_REMOTE_CONTROL_EVENT_RECEIVER = 2222 "android.media.EXTRA_REMOTE_CONTROL_EVENT_RECEIVER"; 2223 2224 // FIXME remove because we are not using intents anymore between AudioService and RcDisplay 2225 /** 2226 * @hide 2227 * The flags describing what information has changed in the current remote control client. 2228 * 2229 * @see #REMOTE_CONTROL_CLIENT_CHANGED_ACTION 2230 */ 2231 public static final String EXTRA_REMOTE_CONTROL_CLIENT_INFO_CHANGED = 2232 "android.media.EXTRA_REMOTE_CONTROL_CLIENT_INFO_CHANGED"; 2233 2234 /** 2235 * @hide 2236 * Reload audio settings. This method is called by Settings backup 2237 * agent when audio settings are restored and causes the AudioService 2238 * to read and apply restored settings. 2239 */ 2240 public void reloadAudioSettings() { 2241 IAudioService service = getService(); 2242 try { 2243 service.reloadAudioSettings(); 2244 } catch (RemoteException e) { 2245 Log.e(TAG, "Dead object in reloadAudioSettings"+e); 2246 } 2247 } 2248 2249 /** 2250 * {@hide} 2251 */ 2252 private final IBinder mICallBack = new Binder(); 2253 2254 /** 2255 * Checks whether the phone is in silent mode, with or without vibrate. 2256 * 2257 * @return true if phone is in silent mode, with or without vibrate. 2258 * 2259 * @see #getRingerMode() 2260 * 2261 * @hide pending API Council approval 2262 */ 2263 public boolean isSilentMode() { 2264 int ringerMode = getRingerMode(); 2265 boolean silentMode = 2266 (ringerMode == RINGER_MODE_SILENT) || 2267 (ringerMode == RINGER_MODE_VIBRATE); 2268 return silentMode; 2269 } 2270 2271 // This section re-defines new output device constants from AudioSystem, because the AudioSystem 2272 // class is not used by other parts of the framework, which instead use definitions and methods 2273 // from AudioManager. AudioSystem is an internal class used by AudioManager and AudioService. 2274 2275 /** {@hide} The audio output device code for the small speaker at the front of the device used 2276 * when placing calls. Does not refer to an in-ear headphone without attached microphone, 2277 * such as earbuds, earphones, or in-ear monitors (IEM). Those would be handled as a 2278 * {@link #DEVICE_OUT_WIRED_HEADPHONE}. 2279 */ 2280 public static final int DEVICE_OUT_EARPIECE = AudioSystem.DEVICE_OUT_EARPIECE; 2281 /** {@hide} The audio output device code for the built-in speaker */ 2282 public static final int DEVICE_OUT_SPEAKER = AudioSystem.DEVICE_OUT_SPEAKER; 2283 /** {@hide} The audio output device code for a wired headset with attached microphone */ 2284 public static final int DEVICE_OUT_WIRED_HEADSET = AudioSystem.DEVICE_OUT_WIRED_HEADSET; 2285 /** {@hide} The audio output device code for a wired headphone without attached microphone */ 2286 public static final int DEVICE_OUT_WIRED_HEADPHONE = AudioSystem.DEVICE_OUT_WIRED_HEADPHONE; 2287 /** {@hide} The audio output device code for generic Bluetooth SCO, for voice */ 2288 public static final int DEVICE_OUT_BLUETOOTH_SCO = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO; 2289 /** {@hide} The audio output device code for Bluetooth SCO Headset Profile (HSP) and 2290 * Hands-Free Profile (HFP), for voice 2291 */ 2292 public static final int DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 2293 AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET; 2294 /** {@hide} The audio output device code for Bluetooth SCO car audio, for voice */ 2295 public static final int DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 2296 AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT; 2297 /** {@hide} The audio output device code for generic Bluetooth A2DP, for music */ 2298 public static final int DEVICE_OUT_BLUETOOTH_A2DP = AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP; 2299 /** {@hide} The audio output device code for Bluetooth A2DP headphones, for music */ 2300 public static final int DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 2301 AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES; 2302 /** {@hide} The audio output device code for Bluetooth A2DP external speaker, for music */ 2303 public static final int DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 2304 AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER; 2305 /** {@hide} The audio output device code for S/PDIF or HDMI */ 2306 public static final int DEVICE_OUT_AUX_DIGITAL = AudioSystem.DEVICE_OUT_AUX_DIGITAL; 2307 /** {@hide} The audio output device code for an analog wired headset attached via a 2308 * docking station 2309 */ 2310 public static final int DEVICE_OUT_ANLG_DOCK_HEADSET = AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET; 2311 /** {@hide} The audio output device code for a digital wired headset attached via a 2312 * docking station 2313 */ 2314 public static final int DEVICE_OUT_DGTL_DOCK_HEADSET = AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET; 2315 /** {@hide} The audio output device code for a USB audio accessory. The accessory is in USB host 2316 * mode and the Android device in USB device mode 2317 */ 2318 public static final int DEVICE_OUT_USB_ACCESSORY = AudioSystem.DEVICE_OUT_USB_ACCESSORY; 2319 /** {@hide} The audio output device code for a USB audio device. The device is in USB device 2320 * mode and the Android device in USB host mode 2321 */ 2322 public static final int DEVICE_OUT_USB_DEVICE = AudioSystem.DEVICE_OUT_USB_DEVICE; 2323 /** {@hide} This is not used as a returned value from {@link #getDevicesForStream}, but could be 2324 * used in the future in a set method to select whatever default device is chosen by the 2325 * platform-specific implementation. 2326 */ 2327 public static final int DEVICE_OUT_DEFAULT = AudioSystem.DEVICE_OUT_DEFAULT; 2328 2329 /** 2330 * Return the enabled devices for the specified output stream type. 2331 * 2332 * @param streamType The stream type to query. One of 2333 * {@link #STREAM_VOICE_CALL}, 2334 * {@link #STREAM_SYSTEM}, 2335 * {@link #STREAM_RING}, 2336 * {@link #STREAM_MUSIC}, 2337 * {@link #STREAM_ALARM}, 2338 * {@link #STREAM_NOTIFICATION}, 2339 * {@link #STREAM_DTMF}. 2340 * 2341 * @return The bit-mask "or" of audio output device codes for all enabled devices on this 2342 * stream. Zero or more of 2343 * {@link #DEVICE_OUT_EARPIECE}, 2344 * {@link #DEVICE_OUT_SPEAKER}, 2345 * {@link #DEVICE_OUT_WIRED_HEADSET}, 2346 * {@link #DEVICE_OUT_WIRED_HEADPHONE}, 2347 * {@link #DEVICE_OUT_BLUETOOTH_SCO}, 2348 * {@link #DEVICE_OUT_BLUETOOTH_SCO_HEADSET}, 2349 * {@link #DEVICE_OUT_BLUETOOTH_SCO_CARKIT}, 2350 * {@link #DEVICE_OUT_BLUETOOTH_A2DP}, 2351 * {@link #DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES}, 2352 * {@link #DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER}, 2353 * {@link #DEVICE_OUT_AUX_DIGITAL}, 2354 * {@link #DEVICE_OUT_ANLG_DOCK_HEADSET}, 2355 * {@link #DEVICE_OUT_DGTL_DOCK_HEADSET}. 2356 * {@link #DEVICE_OUT_DEFAULT} is not used here. 2357 * 2358 * The implementation may support additional device codes beyond those listed, so 2359 * the application should ignore any bits which it does not recognize. 2360 * Note that the information may be imprecise when the implementation 2361 * cannot distinguish whether a particular device is enabled. 2362 * 2363 * {@hide} 2364 */ 2365 public int getDevicesForStream(int streamType) { 2366 switch (streamType) { 2367 case STREAM_VOICE_CALL: 2368 case STREAM_SYSTEM: 2369 case STREAM_RING: 2370 case STREAM_MUSIC: 2371 case STREAM_ALARM: 2372 case STREAM_NOTIFICATION: 2373 case STREAM_DTMF: 2374 return AudioSystem.getDevicesForStream(streamType); 2375 default: 2376 return 0; 2377 } 2378 } 2379 2380 /** 2381 * Indicate wired accessory connection state change. 2382 * @param device type of device connected/disconnected (AudioManager.DEVICE_OUT_xxx) 2383 * @param state new connection state: 1 connected, 0 disconnected 2384 * @param name device name 2385 * {@hide} 2386 */ 2387 public void setWiredDeviceConnectionState(int device, int state, String name) { 2388 IAudioService service = getService(); 2389 try { 2390 service.setWiredDeviceConnectionState(device, state, name); 2391 } catch (RemoteException e) { 2392 Log.e(TAG, "Dead object in setWiredDeviceConnectionState "+e); 2393 } 2394 } 2395 2396 /** 2397 * Indicate A2DP sink connection state change. 2398 * @param device Bluetooth device connected/disconnected 2399 * @param state new connection state (BluetoothProfile.STATE_xxx) 2400 * @return a delay in ms that the caller should wait before broadcasting 2401 * BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED intent. 2402 * {@hide} 2403 */ 2404 public int setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state) { 2405 IAudioService service = getService(); 2406 int delay = 0; 2407 try { 2408 delay = service.setBluetoothA2dpDeviceConnectionState(device, state); 2409 } catch (RemoteException e) { 2410 Log.e(TAG, "Dead object in setBluetoothA2dpDeviceConnectionState "+e); 2411 } finally { 2412 return delay; 2413 } 2414 } 2415 2416 /** {@hide} */ 2417 public IRingtonePlayer getRingtonePlayer() { 2418 try { 2419 return getService().getRingtonePlayer(); 2420 } catch (RemoteException e) { 2421 return null; 2422 } 2423 } 2424} 2425