1 /* 2 * Copyright (C) 2009 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.audio.cts; 18 19 import static android.media.AudioManager.ADJUST_LOWER; 20 import static android.media.AudioManager.ADJUST_RAISE; 21 import static android.media.AudioManager.ADJUST_SAME; 22 import static android.media.AudioManager.MODE_IN_CALL; 23 import static android.media.AudioManager.MODE_IN_COMMUNICATION; 24 import static android.media.AudioManager.MODE_NORMAL; 25 import static android.media.AudioManager.MODE_RINGTONE; 26 import static android.media.AudioManager.RINGER_MODE_NORMAL; 27 import static android.media.AudioManager.RINGER_MODE_SILENT; 28 import static android.media.AudioManager.RINGER_MODE_VIBRATE; 29 import static android.media.AudioManager.STREAM_ACCESSIBILITY; 30 import static android.media.AudioManager.STREAM_ALARM; 31 import static android.media.AudioManager.STREAM_DTMF; 32 import static android.media.AudioManager.STREAM_MUSIC; 33 import static android.media.AudioManager.STREAM_NOTIFICATION; 34 import static android.media.AudioManager.STREAM_RING; 35 import static android.media.AudioManager.STREAM_SYSTEM; 36 import static android.media.AudioManager.STREAM_VOICE_CALL; 37 import static android.media.AudioManager.VIBRATE_SETTING_OFF; 38 import static android.media.AudioManager.VIBRATE_SETTING_ON; 39 import static android.media.AudioManager.VIBRATE_SETTING_ONLY_SILENT; 40 import static android.media.AudioManager.VIBRATE_TYPE_NOTIFICATION; 41 import static android.media.AudioManager.VIBRATE_TYPE_RINGER; 42 import static android.media.audio.cts.AudioTestUtil.resetVolumeIndex; 43 import static android.provider.Settings.Global.APPLY_RAMPING_RINGER; 44 import static android.provider.Settings.System.SOUND_EFFECTS_ENABLED; 45 46 import static com.android.media.mediatestutils.TestUtils.getFutureForIntent; 47 import static com.android.media.mediatestutils.TestUtils.getFutureForListener; 48 49 import static com.google.common.truth.Truth.assertThat; 50 import static com.google.common.truth.Truth.assertWithMessage; 51 52 import static org.junit.Assert.assertEquals; 53 import static org.junit.Assert.assertFalse; 54 import static org.junit.Assert.assertNotEquals; 55 import static org.junit.Assert.assertNotNull; 56 import static org.junit.Assert.assertNull; 57 import static org.junit.Assert.assertThrows; 58 import static org.junit.Assert.assertTrue; 59 import static org.junit.Assert.fail; 60 import static org.junit.Assume.assumeFalse; 61 import static org.junit.Assume.assumeTrue; 62 63 import android.Manifest; 64 import android.app.AutomaticZenRule; 65 import android.app.Instrumentation; 66 import android.app.NotificationChannel; 67 import android.app.NotificationManager; 68 import android.content.Context; 69 import android.content.Intent; 70 import android.content.pm.PackageManager; 71 import android.content.res.Resources; 72 import android.media.AudioAttributes; 73 import android.media.AudioDescriptor; 74 import android.media.AudioDeviceAttributes; 75 import android.media.AudioDeviceInfo; 76 import android.media.AudioFormat; 77 import android.media.AudioHalVersionInfo; 78 import android.media.AudioManager; 79 import android.media.AudioMixerAttributes; 80 import android.media.AudioProfile; 81 import android.media.AudioTrack; 82 import android.media.MediaPlayer; 83 import android.media.MediaRecorder; 84 import android.media.MicrophoneInfo; 85 import android.media.audio.Flags; 86 import android.media.audiopolicy.AudioProductStrategy; 87 import android.media.audiopolicy.AudioVolumeGroup; 88 import android.media.cts.Utils; 89 import android.os.Build; 90 import android.os.SystemClock; 91 import android.os.Vibrator; 92 import android.platform.test.annotations.AppModeFull; 93 import android.platform.test.annotations.AppModeSdkSandbox; 94 import android.platform.test.annotations.RequiresFlagsEnabled; 95 import android.provider.Settings; 96 import android.provider.Settings.System; 97 import android.util.Log; 98 import android.view.SoundEffectConstants; 99 100 import androidx.test.InstrumentationRegistry; 101 import androidx.test.runner.AndroidJUnit4; 102 103 import com.android.compatibility.common.util.AmUtils; 104 import com.android.compatibility.common.util.ApiLevelUtil; 105 import com.android.compatibility.common.util.CddTest; 106 import com.android.compatibility.common.util.MediaUtils; 107 import com.android.compatibility.common.util.NonMainlineTest; 108 import com.android.compatibility.common.util.SettingsStateKeeperRule; 109 import com.android.compatibility.common.util.SystemUtil; 110 import com.android.compatibility.common.util.UserSettings.Namespace; 111 import com.android.internal.annotations.GuardedBy; 112 import com.android.media.mediatestutils.CancelAllFuturesRule; 113 114 import com.google.common.util.concurrent.Futures; 115 import com.google.common.util.concurrent.ListenableFuture; 116 import com.google.common.util.concurrent.MoreExecutors; 117 118 import org.junit.After; 119 import org.junit.Before; 120 import org.junit.ClassRule; 121 import org.junit.Rule; 122 import org.junit.Test; 123 import org.junit.runner.RunWith; 124 125 import java.util.ArrayList; 126 import java.util.Arrays; 127 import java.util.HashMap; 128 import java.util.HashSet; 129 import java.util.List; 130 import java.util.Map; 131 import java.util.Objects; 132 import java.util.Set; 133 import java.util.concurrent.Executors; 134 import java.util.concurrent.TimeUnit; 135 import java.util.function.BooleanSupplier; 136 import java.util.function.Predicate; 137 import java.util.stream.Collectors; 138 import java.util.stream.IntStream; 139 140 @NonMainlineTest 141 @AppModeFull(reason = "Waiting for volume/zen mode changes requires receiving intents. " + 142 "Several API calls require MODIFY_AUDIO_SETTINGS.") 143 @AppModeSdkSandbox(reason = "Allow test in the SDK sandbox (does not prevent other modes).") 144 @RunWith(AndroidJUnit4.class) 145 public class AudioManagerTest { 146 private static final String TAG = "AudioManagerTest"; 147 148 private static final int INIT_VOL = 1; 149 private static final int MP3_TO_PLAY = R.raw.testmp3; // ~ 5 second mp3 150 private static final long POLL_TIME_PLAY_MUSIC = 2000; 151 private static final long TIME_TO_PLAY = 2000; 152 private static final long TIME_TO_WAIT_CALLBACK_MS = 1000; 153 private static final String APPOPS_OP_STR = "android:write_settings"; 154 private static final Set<Integer> ALL_KNOWN_ENCAPSULATION_TYPES = Set.of( 155 AudioProfile.AUDIO_ENCAPSULATION_TYPE_IEC61937, 156 AudioProfile.AUDIO_ENCAPSULATION_TYPE_PCM); 157 private static final Set<Integer> ALL_ENCAPSULATION_TYPES = Set.of( 158 AudioProfile.AUDIO_ENCAPSULATION_TYPE_NONE, 159 AudioProfile.AUDIO_ENCAPSULATION_TYPE_IEC61937, 160 AudioProfile.AUDIO_ENCAPSULATION_TYPE_PCM); 161 private static final Set<Integer> ALL_AUDIO_STANDARDS = Set.of( 162 AudioDescriptor.STANDARD_NONE, 163 AudioDescriptor.STANDARD_EDID, 164 AudioDescriptor.STANDARD_SADB, 165 AudioDescriptor.STANDARD_VSADB); 166 private static final Map<Integer, Integer> DIRECT_OFFLOAD_MAP = Map.of( 167 AudioManager.PLAYBACK_OFFLOAD_NOT_SUPPORTED, 168 AudioManager.DIRECT_PLAYBACK_NOT_SUPPORTED, 169 AudioManager.PLAYBACK_OFFLOAD_SUPPORTED, 170 AudioManager.DIRECT_PLAYBACK_OFFLOAD_SUPPORTED, 171 AudioManager.PLAYBACK_OFFLOAD_GAPLESS_SUPPORTED, 172 AudioManager.DIRECT_PLAYBACK_OFFLOAD_GAPLESS_SUPPORTED); 173 private static final Set<Integer> ALL_MIXER_BEHAVIORS = Set.of( 174 AudioMixerAttributes.MIXER_BEHAVIOR_DEFAULT, 175 AudioMixerAttributes.MIXER_BEHAVIOR_BIT_PERFECT); 176 private static final int[] PUBLIC_STREAM_TYPES = { STREAM_VOICE_CALL, 177 STREAM_SYSTEM, STREAM_RING, STREAM_MUSIC, 178 STREAM_ALARM, STREAM_NOTIFICATION, 179 STREAM_DTMF, STREAM_ACCESSIBILITY }; 180 181 private static final int FUTURE_WAIT_SECS = 5; // Should never timeout; early fail 182 // How long to wait to verify that something that shouldn't happen doesn't happen 183 private static final int PROVE_NEGATIVE_DURATION_MS = 300; 184 185 private static final int INVALID_DIRECT_PLAYBACK_MODE = -1; 186 private AudioManager mAudioManager; 187 private NotificationManager mNm; 188 private boolean mHasVibrator; 189 private boolean mUseFixedVolume; 190 private boolean mIsTelevision; 191 private boolean mIsSingleVolume; 192 private boolean mSkipRingerTests; 193 private boolean mSkipAutoVolumeTests = false; 194 // From N onwards, ringer mode adjustments that toggle DND are not allowed unless 195 // package has DND access. Many tests in this package toggle DND access in order 196 // to get device out of the DND state for the test to proceed correctly. 197 // But DND access is disabled completely on low ram devices, 198 // so completely skip those tests here. 199 // These tests are migrated to CTS verifier tests to ensure test coverage. 200 private Context mContext; 201 private int mOriginalRingerMode; 202 private Map<Integer, Integer> mOriginalStreamVolumes = new HashMap<>(); 203 private NotificationManager.Policy mOriginalNotificationPolicy; 204 private int mOriginalZen; 205 private boolean mDoNotCheckUnmute; 206 private boolean mAppsBypassingDnd; 207 208 @ClassRule 209 public static final SettingsStateKeeperRule mSurroundSoundFormatsSettingsKeeper = 210 new SettingsStateKeeperRule(InstrumentationRegistry.getTargetContext(), 211 Namespace.GLOBAL, Settings.Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS); 212 213 @ClassRule 214 public static final SettingsStateKeeperRule mSurroundSoundModeSettingsKeeper = 215 new SettingsStateKeeperRule(InstrumentationRegistry.getTargetContext(), 216 Namespace.GLOBAL, Settings.Global.ENCODED_SURROUND_OUTPUT); 217 218 @Rule 219 public final CancelAllFuturesRule mCancelRule = new CancelAllFuturesRule(); 220 getInstrumentation()221 private static Instrumentation getInstrumentation() { 222 return InstrumentationRegistry.getInstrumentation(); 223 } 224 225 @Before setUp()226 public void setUp() throws Exception { 227 mContext = getInstrumentation().getContext(); 228 Utils.enableAppOps(mContext.getPackageName(), APPOPS_OP_STR, getInstrumentation()); 229 mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); 230 Vibrator vibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE); 231 mNm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); 232 mAppsBypassingDnd = NotificationManager.getService().areChannelsBypassingDnd(); 233 mHasVibrator = (vibrator != null) && vibrator.hasVibrator(); 234 mUseFixedVolume = mContext.getResources().getBoolean( 235 Resources.getSystem().getIdentifier("config_useFixedVolume", "bool", "android")); 236 PackageManager packageManager = mContext.getPackageManager(); 237 mIsTelevision = packageManager != null 238 && (packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK) 239 || packageManager.hasSystemFeature(PackageManager.FEATURE_TELEVISION)); 240 mIsSingleVolume = mContext.getResources().getBoolean( 241 Resources.getSystem().getIdentifier("config_single_volume", "bool", "android")); 242 mSkipRingerTests = mUseFixedVolume || mIsTelevision || mIsSingleVolume; 243 if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) { 244 // setRingerMode is a no-op 245 mSkipRingerTests = true; 246 // volume SDK APIs are no-ops 247 mSkipAutoVolumeTests = true; 248 } 249 250 // TODO (b/294941969) pull out volume/ringer/zen state setting/resetting into test rule 251 // Store the original volumes that that they can be recovered in tearDown(). 252 final int[] streamTypes = { 253 STREAM_VOICE_CALL, 254 STREAM_SYSTEM, 255 STREAM_RING, 256 STREAM_MUSIC, 257 STREAM_ALARM, 258 STREAM_NOTIFICATION, 259 STREAM_DTMF, 260 STREAM_ACCESSIBILITY, 261 }; 262 mOriginalRingerMode = mAudioManager.getRingerMode(); 263 for (int streamType : streamTypes) { 264 mOriginalStreamVolumes.put(streamType, mAudioManager.getStreamVolume(streamType)); 265 } 266 267 // Tests require the known state of volumes set to INIT_VOL and zen mode 268 // turned off. 269 try { 270 Utils.toggleNotificationPolicyAccess( 271 mContext.getPackageName(), getInstrumentation(), true); 272 273 SystemUtil.runWithShellPermissionIdentity( 274 () -> { 275 mOriginalNotificationPolicy = mNm.getNotificationPolicy(); 276 mOriginalZen = mNm.getCurrentInterruptionFilter(); 277 mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL); 278 setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL); 279 }, 280 Manifest.permission.STATUS_BAR_SERVICE); 281 } finally { 282 Utils.toggleNotificationPolicyAccess( 283 mContext.getPackageName(), getInstrumentation(), false); 284 } 285 286 for (int streamType : streamTypes) { 287 mAudioManager.setStreamVolume(streamType, INIT_VOL, 0 /* flags */); 288 } 289 290 // Check original microphone mute/unmute status 291 mDoNotCheckUnmute = false; 292 if (mAudioManager.isMicrophoneMute()) { 293 mAudioManager.setMicrophoneMute(false); 294 if (mAudioManager.isMicrophoneMute()) { 295 Log.w(TAG, "Mic seems muted by hardware! Please unmute and rerrun the test."); 296 mDoNotCheckUnmute = true; 297 } 298 } 299 // Reduce flake due to late intent delivery 300 AmUtils.waitForBroadcastIdle(); 301 } 302 303 @After tearDown()304 public void tearDown() throws Exception { 305 try { 306 Utils.toggleNotificationPolicyAccess( 307 mContext.getPackageName(), getInstrumentation(), true); 308 mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL); 309 310 SystemUtil.runWithShellPermissionIdentity( 311 () -> { 312 mNm.setNotificationPolicy(mOriginalNotificationPolicy); 313 setInterruptionFilter(mOriginalZen); 314 }, 315 Manifest.permission.STATUS_BAR_SERVICE); 316 317 Map<String, AutomaticZenRule> rules = mNm.getAutomaticZenRules(); 318 for (String ruleId : rules.keySet()) { 319 mNm.removeAutomaticZenRule(ruleId); 320 } 321 322 // Recover the volume and the ringer mode that the test may have overwritten. 323 for (Map.Entry<Integer, Integer> e : mOriginalStreamVolumes.entrySet()) { 324 mAudioManager.setStreamVolume(e.getKey(), e.getValue(), 325 AudioManager.FLAG_ALLOW_RINGER_MODES); 326 } 327 mAudioManager.setRingerMode(mOriginalRingerMode); 328 } finally { 329 Utils.toggleNotificationPolicyAccess( 330 mContext.getPackageName(), getInstrumentation(), false); 331 } 332 } 333 334 @AppModeFull(reason = "Instant apps cannot hold android.permission.MODIFY_AUDIO_SETTINGS") 335 @Test testMicrophoneMute()336 public void testMicrophoneMute() throws Exception { 337 mAudioManager.setMicrophoneMute(true); 338 assertTrue(mAudioManager.isMicrophoneMute()); 339 mAudioManager.setMicrophoneMute(false); 340 assertFalse(mAudioManager.isMicrophoneMute() && !mDoNotCheckUnmute); 341 } 342 343 @AppModeFull(reason = "Instant apps cannot hold android.permission.MODIFY_AUDIO_SETTINGS") 344 @Test testMicrophoneMuteIntent()345 public void testMicrophoneMuteIntent() throws Exception { 346 assumeFalse(mDoNotCheckUnmute); 347 348 final boolean initialMicMute = mAudioManager.isMicrophoneMute(); 349 var future = mCancelRule.registerFuture(getFutureForIntent( 350 mContext, 351 AudioManager.ACTION_MICROPHONE_MUTE_CHANGED, 352 i -> true)); 353 try { 354 // change the mic mute state 355 mAudioManager.setMicrophoneMute(!initialMicMute); 356 // verify a change was reported 357 future.get(FUTURE_WAIT_SECS, TimeUnit.SECONDS); 358 // verify the mic mute state is expected 359 assertWithMessage("New mic mute should be changed after intent") 360 .that(mAudioManager.isMicrophoneMute()) 361 .isNotEqualTo(initialMicMute); 362 } finally { 363 mAudioManager.setMicrophoneMute(initialMicMute); 364 } 365 } 366 367 @AppModeFull(reason = "Instant apps cannot hold android.permission.MODIFY_AUDIO_SETTINGS") 368 @Test testSpeakerphoneIntent()369 public void testSpeakerphoneIntent() throws Exception { 370 // Speaker Phone Not supported in Automotive 371 assumeFalse(mContext.getPackageManager().hasSystemFeature( 372 PackageManager.FEATURE_AUTOMOTIVE)); 373 374 assumeTrue(hasBuiltinSpeaker()); 375 376 var future = mCancelRule.registerFuture(getFutureForIntent( 377 mContext, 378 AudioManager.ACTION_SPEAKERPHONE_STATE_CHANGED, 379 i -> true)); 380 381 final boolean initialSpeakerphoneState = mAudioManager.isSpeakerphoneOn(); 382 try { 383 getInstrumentation().getUiAutomation().adoptShellPermissionIdentity( 384 Manifest.permission.MODIFY_PHONE_STATE); 385 386 // change the speakerphone state 387 mAudioManager.setSpeakerphoneOn(!initialSpeakerphoneState); 388 future.get(FUTURE_WAIT_SECS, TimeUnit.SECONDS); 389 390 // verify the speakerphone state is expected 391 assertWithMessage("New speakerphone state should be changed after intent") 392 .that(mAudioManager.isSpeakerphoneOn()) 393 .isNotEqualTo(initialSpeakerphoneState); 394 } finally { 395 mAudioManager.setSpeakerphoneOn(initialSpeakerphoneState); 396 getInstrumentation().getUiAutomation().dropShellPermissionIdentity(); 397 } 398 } 399 hasBuiltinSpeaker()400 private boolean hasBuiltinSpeaker() { 401 AudioDeviceInfo[] devices = mAudioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS); 402 for (AudioDeviceInfo device : devices) { 403 final int type = device.getType(); 404 if (type == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER 405 || type == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER_SAFE) { 406 return true; 407 } 408 } 409 return false; 410 } 411 412 @AppModeFull( 413 reason = 414 "ACTION_VOLUME_CHANGED is not sent to Instant apps (no" 415 + " FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS)") 416 @Test testVolumeChangedIntent()417 public void testVolumeChangedIntent() throws Exception { 418 if (mAudioManager.isVolumeFixed()) { 419 return; 420 } 421 if (mSkipAutoVolumeTests) { 422 // setStreamVolume is a no-op 423 return; 424 } 425 // safe media can block the raising the volume, disable it 426 getInstrumentation().getUiAutomation() 427 .adoptShellPermissionIdentity(Manifest.permission.STATUS_BAR_SERVICE); 428 mAudioManager.disableSafeMediaVolume(); 429 getInstrumentation().getUiAutomation().dropShellPermissionIdentity(); 430 431 var future = mCancelRule.registerFuture(getFutureForIntent( 432 mContext, 433 AudioManager.ACTION_VOLUME_CHANGED, 434 i -> (i != null) 435 && (i.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, 436 Integer.MIN_VALUE) == STREAM_MUSIC))); 437 438 int mediaVol = mAudioManager.getStreamVolume(STREAM_MUSIC); 439 final int origVol = mediaVol; 440 final int maxMediaVol = mAudioManager.getStreamMaxVolume(STREAM_MUSIC); 441 // change media volume from current value 442 mAudioManager.setStreamVolume(STREAM_MUSIC, 443 mediaVol == maxMediaVol ? --mediaVol : ++mediaVol, 444 0 /*flags*/); 445 // verify a change was reported 446 final Intent intent = future.get(FUTURE_WAIT_SECS, TimeUnit.SECONDS); 447 448 assertWithMessage("Not an intent for STREAM_MUSIC") 449 .that(intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1)) 450 .isEqualTo(STREAM_MUSIC); 451 assertWithMessage("New STREAM_MUSIC volume not as expected") 452 .that(intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, -1)) 453 .isEqualTo(mediaVol); 454 assertWithMessage("Previous STREAM_MUSIC volume not as expected") 455 .that(intent.getIntExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, -1)) 456 .isEqualTo(origVol); 457 } 458 459 private static final class MyBlockingRunnableListener { 460 private final SafeWaitObject mLock = new SafeWaitObject(); 461 @GuardedBy("mLock") 462 private boolean mEventReceived = false; 463 onSomeEventThatsExpected()464 public void onSomeEventThatsExpected() { 465 synchronized (mLock) { 466 mEventReceived = true; 467 mLock.notify(); 468 } 469 } 470 waitForExpectedEvent(long timeOutMs)471 public boolean waitForExpectedEvent(long timeOutMs) { 472 synchronized (mLock) { 473 return mLock.waitFor(timeOutMs, () -> mEventReceived); 474 } 475 } 476 } 477 478 @Test testSoundEffects()479 public void testSoundEffects() throws Exception { 480 Settings.System.putInt(mContext.getContentResolver(), SOUND_EFFECTS_ENABLED, 1); 481 482 // should hear sound after loadSoundEffects() called. 483 mAudioManager.loadSoundEffects(); 484 Thread.sleep(TIME_TO_PLAY); 485 float volume = 0.5f; // volume should be between 0.f to 1.f (or -1). 486 mAudioManager.playSoundEffect(SoundEffectConstants.CLICK); 487 mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_UP); 488 mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_DOWN); 489 mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_LEFT); 490 mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_RIGHT); 491 492 mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_UP, volume); 493 mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_DOWN, volume); 494 mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_LEFT, volume); 495 mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_RIGHT, volume); 496 497 // won't hear sound after unloadSoundEffects() called(); 498 mAudioManager.unloadSoundEffects(); 499 mAudioManager.playSoundEffect(AudioManager.FX_KEY_CLICK); 500 mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_UP); 501 mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_DOWN); 502 mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_LEFT); 503 mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_RIGHT); 504 505 mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_UP, volume); 506 mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_DOWN, volume); 507 mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_LEFT, volume); 508 mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_RIGHT, volume); 509 } 510 511 @Test testCheckingZenModeBlockDoesNotRequireNotificationPolicyAccess()512 public void testCheckingZenModeBlockDoesNotRequireNotificationPolicyAccess() throws Exception { 513 // set zen mode to priority only, so playSoundEffect will check notification policy 514 assumeFalse("Skipping zen mode test", mSkipRingerTests); 515 Utils.toggleNotificationPolicyAccess(mContext.getPackageName(), getInstrumentation(), 516 true); 517 setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY); 518 Settings.System.putInt(mContext.getContentResolver(), SOUND_EFFECTS_ENABLED, 1); 519 520 // take away write-notification policy access from the package 521 Utils.toggleNotificationPolicyAccess(mContext.getPackageName(), getInstrumentation(), 522 false); 523 524 // playSoundEffect should NOT throw a security exception; all apps have read-access 525 mAudioManager.playSoundEffect(SoundEffectConstants.CLICK); 526 } 527 528 @Test testMusicActive()529 public void testMusicActive() throws Exception { 530 if (mAudioManager.isMusicActive()) { 531 return; 532 } 533 MediaPlayer mp = MediaPlayer.create(mContext, MP3_TO_PLAY); 534 assertNotNull(mp); 535 mp.setAudioStreamType(STREAM_MUSIC); 536 mp.start(); 537 assertMusicActive(true); 538 mp.stop(); 539 mp.release(); 540 assertMusicActive(false); 541 } 542 543 @AppModeFull(reason = "Instant apps cannot hold android.permission.MODIFY_AUDIO_SETTINGS") 544 @Test testAccessMode()545 public void testAccessMode() throws Exception { 546 mAudioManager.setMode(MODE_RINGTONE); 547 assertEquals(MODE_RINGTONE, mAudioManager.getMode()); 548 mAudioManager.setMode(MODE_IN_COMMUNICATION); 549 assertEquals(MODE_IN_COMMUNICATION, mAudioManager.getMode()); 550 mAudioManager.setMode(MODE_NORMAL); 551 assertEquals(MODE_NORMAL, mAudioManager.getMode()); 552 } 553 554 @Test testSetSurroundFormatEnabled()555 public void testSetSurroundFormatEnabled() throws Exception { 556 getInstrumentation().getUiAutomation().adoptShellPermissionIdentity( 557 Manifest.permission.WRITE_SETTINGS); 558 559 int audioFormat = AudioFormat.ENCODING_DTS; 560 561 mAudioManager.setSurroundFormatEnabled(audioFormat, true /*enabled*/); 562 assertTrue(mAudioManager.isSurroundFormatEnabled(audioFormat)); 563 564 mAudioManager.setSurroundFormatEnabled(audioFormat, false /*enabled*/); 565 assertFalse(mAudioManager.isSurroundFormatEnabled(audioFormat)); 566 567 getInstrumentation().getUiAutomation().dropShellPermissionIdentity(); 568 } 569 570 @AppModeFull(reason = "Instant apps cannot hold android.permission.WRITE_SETTINGS") 571 @Test testSetEncodedSurroundMode()572 public void testSetEncodedSurroundMode() throws Exception { 573 getInstrumentation().getUiAutomation().adoptShellPermissionIdentity( 574 Manifest.permission.WRITE_SETTINGS); 575 576 int expectedSurroundFormatsMode = Settings.Global.ENCODED_SURROUND_OUTPUT_MANUAL; 577 mAudioManager.setEncodedSurroundMode(expectedSurroundFormatsMode); 578 assertEquals(expectedSurroundFormatsMode, mAudioManager.getEncodedSurroundMode()); 579 580 expectedSurroundFormatsMode = Settings.Global.ENCODED_SURROUND_OUTPUT_NEVER; 581 mAudioManager.setEncodedSurroundMode(expectedSurroundFormatsMode); 582 assertEquals(expectedSurroundFormatsMode, mAudioManager.getEncodedSurroundMode()); 583 584 getInstrumentation().getUiAutomation().dropShellPermissionIdentity(); 585 } 586 587 @SuppressWarnings("deprecation") 588 @AppModeFull(reason = "Instant apps cannot hold android.permission.MODIFY_AUDIO_SETTINGS") 589 @Test testRouting()590 public void testRouting() throws Exception { 591 // setBluetoothA2dpOn is a no-op, and getRouting should always return -1 592 boolean oldA2DP = mAudioManager.isBluetoothA2dpOn(); 593 mAudioManager.setBluetoothA2dpOn(true); 594 assertEquals(oldA2DP, mAudioManager.isBluetoothA2dpOn()); 595 mAudioManager.setBluetoothA2dpOn(false); 596 assertEquals(oldA2DP, mAudioManager.isBluetoothA2dpOn()); 597 598 assertEquals(-1, mAudioManager.getRouting(MODE_RINGTONE)); 599 assertEquals(-1, mAudioManager.getRouting(MODE_NORMAL)); 600 assertEquals(-1, mAudioManager.getRouting(MODE_IN_CALL)); 601 assertEquals(-1, mAudioManager.getRouting(MODE_IN_COMMUNICATION)); 602 603 mAudioManager.setBluetoothScoOn(true); 604 assertTrueCheckTimeout(mAudioManager, p -> p.isBluetoothScoOn(), 605 DEFAULT_ASYNC_CALL_TIMEOUT_MS, "isBluetoothScoOn returned false"); 606 607 mAudioManager.setBluetoothScoOn(false); 608 assertTrueCheckTimeout(mAudioManager, p -> !p.isBluetoothScoOn(), 609 DEFAULT_ASYNC_CALL_TIMEOUT_MS, "isBluetoothScoOn returned true"); 610 611 // Speaker Phone Not supported in Automotive 612 if (isAutomotive()) { 613 return; 614 } 615 616 try { 617 getInstrumentation().getUiAutomation().adoptShellPermissionIdentity( 618 Manifest.permission.MODIFY_PHONE_STATE); 619 620 mAudioManager.setSpeakerphoneOn(true); 621 assertTrueCheckTimeout(mAudioManager, p -> p.isSpeakerphoneOn(), 622 DEFAULT_ASYNC_CALL_TIMEOUT_MS, "isSpeakerPhoneOn() returned false"); 623 624 mAudioManager.setSpeakerphoneOn(false); 625 assertTrueCheckTimeout(mAudioManager, p -> !p.isSpeakerphoneOn(), 626 DEFAULT_ASYNC_CALL_TIMEOUT_MS, "isSpeakerPhoneOn() returned true"); 627 628 } finally { 629 getInstrumentation().getUiAutomation().dropShellPermissionIdentity(); 630 } 631 } 632 633 @Test testVibrateNotification()634 public void testVibrateNotification() throws Exception { 635 if (mUseFixedVolume || !mHasVibrator) { 636 return; 637 } 638 if (mSkipAutoVolumeTests) { 639 // setRingerMode is a no-op 640 return; 641 } 642 Utils.toggleNotificationPolicyAccess( 643 mContext.getPackageName(), getInstrumentation(), true); 644 // VIBRATE_SETTING_ON 645 mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ON); 646 assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF, 647 mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION)); 648 mAudioManager.setRingerMode(RINGER_MODE_NORMAL); 649 assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION)); 650 651 mAudioManager.setRingerMode(RINGER_MODE_SILENT); 652 assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION)); 653 654 mAudioManager.setRingerMode(RINGER_MODE_VIBRATE); 655 assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT, 656 mAudioManager.getRingerMode()); 657 assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION)); 658 659 // VIBRATE_SETTING_OFF 660 mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_OFF); 661 assertEquals(VIBRATE_SETTING_OFF, 662 mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION)); 663 mAudioManager.setRingerMode(RINGER_MODE_NORMAL); 664 assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION)); 665 666 mAudioManager.setRingerMode(RINGER_MODE_SILENT); 667 assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION)); 668 669 mAudioManager.setRingerMode(RINGER_MODE_VIBRATE); 670 assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT, 671 mAudioManager.getRingerMode()); 672 assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION)); 673 674 // VIBRATE_SETTING_ONLY_SILENT 675 mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ONLY_SILENT); 676 assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF, 677 mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION)); 678 mAudioManager.setRingerMode(RINGER_MODE_NORMAL); 679 assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION)); 680 681 mAudioManager.setRingerMode(RINGER_MODE_SILENT); 682 assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION)); 683 684 mAudioManager.setRingerMode(RINGER_MODE_VIBRATE); 685 assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT, 686 mAudioManager.getRingerMode()); 687 assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION)); 688 689 // VIBRATE_TYPE_NOTIFICATION 690 mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ON); 691 assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF, 692 mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION)); 693 mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_OFF); 694 assertEquals(VIBRATE_SETTING_OFF, mAudioManager 695 .getVibrateSetting(VIBRATE_TYPE_NOTIFICATION)); 696 mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ONLY_SILENT); 697 assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF, 698 mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION)); 699 } 700 701 @Test testVibrateRinger()702 public void testVibrateRinger() throws Exception { 703 if (mUseFixedVolume || !mHasVibrator) { 704 return; 705 } 706 if (mSkipAutoVolumeTests) { 707 // setRingerMode is a no-op 708 return; 709 } 710 Utils.toggleNotificationPolicyAccess( 711 mContext.getPackageName(), getInstrumentation(), true); 712 // VIBRATE_TYPE_RINGER 713 mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ON); 714 assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF, 715 mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER)); 716 mAudioManager.setRingerMode(RINGER_MODE_NORMAL); 717 assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER)); 718 719 mAudioManager.setRingerMode(RINGER_MODE_SILENT); 720 assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER)); 721 722 mAudioManager.setRingerMode(RINGER_MODE_VIBRATE); 723 assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT, 724 mAudioManager.getRingerMode()); 725 assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER)); 726 727 // VIBRATE_SETTING_OFF 728 mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_OFF); 729 assertEquals(VIBRATE_SETTING_OFF, mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER)); 730 mAudioManager.setRingerMode(RINGER_MODE_NORMAL); 731 assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER)); 732 733 mAudioManager.setRingerMode(RINGER_MODE_SILENT); 734 assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER)); 735 736 mAudioManager.setRingerMode(RINGER_MODE_VIBRATE); 737 assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT, 738 mAudioManager.getRingerMode()); 739 // Note: as of Froyo, if VIBRATE_TYPE_RINGER is set to OFF, it will 740 // not vibrate, even in RINGER_MODE_VIBRATE. This allows users to 741 // disable the vibration for incoming calls only. 742 assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER)); 743 744 // VIBRATE_SETTING_ONLY_SILENT 745 mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ONLY_SILENT); 746 assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF, 747 mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER)); 748 mAudioManager.setRingerMode(RINGER_MODE_NORMAL); 749 assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER)); 750 751 mAudioManager.setRingerMode(RINGER_MODE_SILENT); 752 assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER)); 753 754 mAudioManager.setRingerMode(RINGER_MODE_VIBRATE); 755 assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT, 756 mAudioManager.getRingerMode()); 757 assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER)); 758 759 // VIBRATE_TYPE_NOTIFICATION 760 mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ON); 761 assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF, 762 mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER)); 763 mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_OFF); 764 assertEquals(VIBRATE_SETTING_OFF, mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER)); 765 mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ONLY_SILENT); 766 assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF, 767 mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER)); 768 } 769 770 @Test testAccessRingMode()771 public void testAccessRingMode() throws Exception { 772 Utils.toggleNotificationPolicyAccess( 773 mContext.getPackageName(), getInstrumentation(), true); 774 mAudioManager.setRingerMode(RINGER_MODE_NORMAL); 775 assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode()); 776 777 mAudioManager.setRingerMode(RINGER_MODE_SILENT); 778 // AudioService#setRingerMode() has: 779 // if (isTelevision) return; 780 if (mSkipRingerTests) { 781 assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode()); 782 } else { 783 assertEquals(RINGER_MODE_SILENT, mAudioManager.getRingerMode()); 784 } 785 786 mAudioManager.setRingerMode(RINGER_MODE_VIBRATE); 787 if (mSkipRingerTests) { 788 assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode()); 789 } else { 790 assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT, 791 mAudioManager.getRingerMode()); 792 } 793 } 794 795 // TODO explain the intended behavior in this test 796 /** 797 * Test that in RINGER_MODE_VIBRATE we observe: 798 * if NOTIFICATION & RING are not aliased: 799 * ADJUST_UNMUTE NOTIFICATION -> no change (no mode change, NOTIF still muted) 800 * ADJUST_UNMUTE NOTIFICATION + FLAG_ALLOW_RINGER_MODES -> MODE_NORMAL 801 * if NOTIFICATION & RING are aliased: 802 * ADJUST_UNMUTE NOTIFICATION -> MODE_NORMAL 803 * ADJUST_UNMUTE NOTIFICATION + FLAG_ALLOW_RINGER_MODES -> MODE_NORMAL 804 * @throws Exception 805 */ 806 @Test testAdjustUnmuteNotificationInVibrate()807 public void testAdjustUnmuteNotificationInVibrate() throws Exception { 808 Log.i(TAG, "starting testAdjustUnmuteNotificationInVibrate"); 809 if (mSkipRingerTests) { 810 Log.i(TAG, "skipping testAdjustUnmuteNotificationInVibrate"); 811 return; 812 } 813 if (!mHasVibrator) { 814 Log.i(TAG, "skipping testAdjustUnmuteNotificationInVibrate, no vibrator"); 815 return; 816 } 817 // set mode to VIBRATE 818 Utils.toggleNotificationPolicyAccess( 819 mContext.getPackageName(), getInstrumentation(), true); 820 821 Map<Integer, MuteStateTransition> expectedVibrateTransitions = Map.of( 822 STREAM_MUSIC, new MuteStateTransition(false, false), 823 STREAM_RING, new MuteStateTransition(false, true), 824 STREAM_NOTIFICATION, new MuteStateTransition(false, true), 825 STREAM_ALARM, new MuteStateTransition(false, false)); 826 827 assertStreamMuteStateChange(() -> mAudioManager.setRingerMode(RINGER_MODE_VIBRATE), 828 expectedVibrateTransitions, 829 "RING and NOTIF should be muted in MODE_VIBRATE"); 830 831 assertEquals(RINGER_MODE_VIBRATE, mAudioManager.getRingerMode()); 832 Utils.toggleNotificationPolicyAccess( 833 mContext.getPackageName(), getInstrumentation(), false); 834 835 getInstrumentation().getUiAutomation() 836 .adoptShellPermissionIdentity(Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED); 837 final int notifiAliasedStream = mAudioManager.getStreamTypeAlias(STREAM_NOTIFICATION); 838 getInstrumentation().getUiAutomation().dropShellPermissionIdentity(); 839 840 Map<Integer, MuteStateTransition> unmuteRingerTransitions = Map.of( 841 STREAM_MUSIC, new MuteStateTransition(false, false), 842 STREAM_RING, new MuteStateTransition(true , false), 843 STREAM_NOTIFICATION, new MuteStateTransition(true, false), 844 STREAM_ALARM, new MuteStateTransition(false, false)); 845 846 if (notifiAliasedStream == STREAM_NOTIFICATION) { 847 Log.i(TAG, "testAdjustUnmuteNotificationInVibrate: NOTIF independent"); 848 849 Map<Integer, MuteStateTransition> noMuteTransitions = Map.of( 850 STREAM_MUSIC, new MuteStateTransition(false, false), 851 STREAM_RING, new MuteStateTransition(true , true), 852 STREAM_NOTIFICATION, new MuteStateTransition(true, true), 853 STREAM_ALARM, new MuteStateTransition(false, false)); 854 855 // unmute NOTIFICATION 856 assertStreamMuteStateChange(() -> mAudioManager.adjustStreamVolume( 857 STREAM_NOTIFICATION, AudioManager.ADJUST_UNMUTE, 0), 858 noMuteTransitions, 859 "NOTIFICATION should not unmute"); 860 // unmuting NOTIFICATION should not have exited RINGER_MODE_VIBRATE 861 assertEquals(RINGER_MODE_VIBRATE, mAudioManager.getRingerMode()); 862 863 864 assertStreamMuteStateChange(() -> mAudioManager.adjustStreamVolume( 865 STREAM_NOTIFICATION, 866 AudioManager.ADJUST_UNMUTE, AudioManager.FLAG_ALLOW_RINGER_MODES), 867 unmuteRingerTransitions, 868 "NOTIFICATION(+FLAG_ALLOW_RINGER_MODES) should unmute RING/NOTIF"); 869 // unmuting NOTIFICATION w/ FLAG_ALLOW_RINGER_MODES should have exited MODE_VIBRATE 870 assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode()); 871 } else if (notifiAliasedStream == STREAM_RING) { 872 Log.i(TAG, "testAdjustUnmuteNotificationInVibrate: NOTIF/RING aliased"); 873 // unmute NOTIFICATION (should be just like unmuting RING) 874 assertStreamMuteStateChange(() -> mAudioManager.adjustStreamVolume( 875 STREAM_NOTIFICATION, AudioManager.ADJUST_UNMUTE, 0), 876 unmuteRingerTransitions, 877 "when aliased NOTIF/RING should be unmuted"); 878 879 assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode()); 880 881 // test again with FLAG_ALLOW_RINGER_MODES 882 Utils.toggleNotificationPolicyAccess( 883 mContext.getPackageName(), getInstrumentation(), true); 884 mAudioManager.setRingerMode(RINGER_MODE_VIBRATE); 885 assertEquals(RINGER_MODE_VIBRATE, mAudioManager.getRingerMode()); 886 Utils.toggleNotificationPolicyAccess( 887 mContext.getPackageName(), getInstrumentation(), false); 888 889 // unmute NOTIFICATION (should be just like unmuting RING) 890 assertStreamMuteStateChange(() -> mAudioManager.adjustStreamVolume( 891 STREAM_NOTIFICATION, 892 AudioManager.ADJUST_UNMUTE, AudioManager.FLAG_ALLOW_RINGER_MODES), 893 unmuteRingerTransitions, 894 "when aliased NOTIF/RING should be unmuted"); 895 896 // unmuting NOTIFICATION should have exited RINGER_MODE_VIBRATE 897 assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode()); 898 } 899 } 900 901 /** 902 * Test that in RINGER_MODE_SILENT we observe: 903 * ADJUST_UNMUTE NOTIFICATION -> no change (no mode change, NOTIF still muted) 904 * 905 * Note that in SILENT we cannot test ADJUST_UNMUTE NOTIFICATION + FLAG_ALLOW_RINGER_MODES 906 * because it depends on VolumePolicy.volumeUpToExitSilent. 907 * TODO add test API to query VolumePolicy, expected in MODE_SILENT: 908 * ADJUST_UNMUTE NOTIFICATION + FLAG_ALLOW_RINGER_MODE -> 909 * no change if VolumePolicy.volumeUpToExitSilent false (default?) 910 * ADJUST_UNMUTE NOTIFICATION + FLAG_ALLOW_RINGER_MODE -> 911 * MODE_NORMAL if VolumePolicy.volumeUpToExitSilent true 912 * @throws Exception 913 */ 914 @Test testAdjustUnmuteNotificationInSilent()915 public void testAdjustUnmuteNotificationInSilent() throws Exception { 916 assumeFalse(mSkipRingerTests); 917 918 Map<Integer, MuteStateTransition> expectedTransitionsSilentMode = Map.of( 919 STREAM_MUSIC, new MuteStateTransition(false, false), 920 STREAM_NOTIFICATION, new MuteStateTransition(false, true), 921 STREAM_RING, new MuteStateTransition(false, true), 922 STREAM_ALARM, new MuteStateTransition(false, false)); 923 924 925 // set mode to SILENT 926 Utils.toggleNotificationPolicyAccess( 927 mContext.getPackageName(), getInstrumentation(), true); 928 assertStreamMuteStateChange(() -> mAudioManager.setRingerMode(RINGER_MODE_SILENT), 929 expectedTransitionsSilentMode, 930 "RING/NOTIF should mute in SILENT"); 931 assertEquals(RINGER_MODE_SILENT, mAudioManager.getRingerMode()); 932 Utils.toggleNotificationPolicyAccess( 933 mContext.getPackageName(), getInstrumentation(), false); 934 935 Map<Integer, MuteStateTransition> expectedTransitionsRemainSilentMode = Map.of( 936 STREAM_MUSIC, new MuteStateTransition(false, false), 937 STREAM_NOTIFICATION, new MuteStateTransition(true, true), 938 STREAM_RING, new MuteStateTransition(true, true), 939 STREAM_ALARM, new MuteStateTransition(false, false)); 940 941 942 // unmute NOTIFICATION 943 assertStreamMuteStateChange(() -> mAudioManager.adjustStreamVolume( 944 STREAM_NOTIFICATION, AudioManager.ADJUST_UNMUTE, 0), 945 expectedTransitionsRemainSilentMode, 946 "Unmute NOTIF should have no effect in SILENT"); 947 948 // unmuting NOTIFICATION should not have exited RINGER_MODE_SILENT 949 assertEquals(RINGER_MODE_SILENT, mAudioManager.getRingerMode()); 950 } 951 952 @Test testSetRingerModePolicyAccess()953 public void testSetRingerModePolicyAccess() throws Exception { 954 assumeFalse(mSkipRingerTests); 955 // Apps without policy access cannot change silent -> normal or silent -> vibrate. 956 Utils.toggleNotificationPolicyAccess( 957 mContext.getPackageName(), getInstrumentation(), true); 958 mAudioManager.setRingerMode(RINGER_MODE_SILENT); 959 assertEquals(RINGER_MODE_SILENT, mAudioManager.getRingerMode()); 960 Utils.toggleNotificationPolicyAccess( 961 mContext.getPackageName(), getInstrumentation(), false); 962 963 try { 964 mAudioManager.setRingerMode(RINGER_MODE_NORMAL); 965 fail("Apps without notification policy access cannot change ringer mode"); 966 } catch (SecurityException e) { 967 } 968 969 try { 970 mAudioManager.setRingerMode(RINGER_MODE_VIBRATE); 971 fail("Apps without notification policy access cannot change ringer mode"); 972 } catch (SecurityException e) { 973 } 974 975 // Apps without policy access cannot change normal -> silent. 976 Utils.toggleNotificationPolicyAccess( 977 mContext.getPackageName(), getInstrumentation(), true); 978 mAudioManager.setRingerMode(RINGER_MODE_NORMAL); 979 assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode()); 980 Utils.toggleNotificationPolicyAccess( 981 mContext.getPackageName(), getInstrumentation(), false); 982 983 try { 984 mAudioManager.setRingerMode(RINGER_MODE_SILENT); 985 fail("Apps without notification policy access cannot change ringer mode"); 986 } catch (SecurityException e) { 987 } 988 assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode()); 989 990 if (mHasVibrator) { 991 // Apps without policy access cannot change vibrate -> silent. 992 Utils.toggleNotificationPolicyAccess( 993 mContext.getPackageName(), getInstrumentation(), true); 994 mAudioManager.setRingerMode(RINGER_MODE_VIBRATE); 995 assertEquals(RINGER_MODE_VIBRATE, mAudioManager.getRingerMode()); 996 Utils.toggleNotificationPolicyAccess( 997 mContext.getPackageName(), getInstrumentation(), false); 998 999 try { 1000 mAudioManager.setRingerMode(RINGER_MODE_SILENT); 1001 fail("Apps without notification policy access cannot change ringer mode"); 1002 } catch (SecurityException e) { 1003 } 1004 1005 // Apps without policy access can change vibrate -> normal and vice versa. 1006 assertEquals(RINGER_MODE_VIBRATE, mAudioManager.getRingerMode()); 1007 mAudioManager.setRingerMode(RINGER_MODE_NORMAL); 1008 assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode()); 1009 mAudioManager.setRingerMode(RINGER_MODE_VIBRATE); 1010 assertEquals(RINGER_MODE_VIBRATE, mAudioManager.getRingerMode()); 1011 } 1012 } 1013 1014 @Test testAccessRampingRinger()1015 public void testAccessRampingRinger() { 1016 boolean originalEnabledState = mAudioManager.isRampingRingerEnabled(); 1017 try { 1018 mAudioManager.setRampingRingerEnabled(false); 1019 assertFalse(mAudioManager.isRampingRingerEnabled()); 1020 1021 mAudioManager.setRampingRingerEnabled(true); 1022 assertTrue(mAudioManager.isRampingRingerEnabled()); 1023 } finally { 1024 mAudioManager.setRampingRingerEnabled(originalEnabledState); 1025 } 1026 } 1027 1028 @Test testRampingRingerSetting()1029 public void testRampingRingerSetting() { 1030 boolean originalEnabledState = mAudioManager.isRampingRingerEnabled(); 1031 try { 1032 // Deprecated public setting should still be supported and affect the setting getter. 1033 Settings.Global.putInt(mContext.getContentResolver(), APPLY_RAMPING_RINGER, 0); 1034 assertFalse(mAudioManager.isRampingRingerEnabled()); 1035 1036 Settings.Global.putInt(mContext.getContentResolver(), APPLY_RAMPING_RINGER, 1); 1037 assertTrue(mAudioManager.isRampingRingerEnabled()); 1038 } finally { 1039 mAudioManager.setRampingRingerEnabled(originalEnabledState); 1040 } 1041 } 1042 1043 @Test testVolume()1044 public void testVolume() throws Exception { 1045 if (MediaUtils.check(mIsTelevision, "No volume test due to fixed/full vol devices")) 1046 return; 1047 if (mSkipAutoVolumeTests) { 1048 // setStreamVolume/adjustVolume are no-op 1049 return; 1050 } 1051 Utils.toggleNotificationPolicyAccess( 1052 mContext.getPackageName(), getInstrumentation(), true); 1053 int volume, volumeDelta; 1054 int[] streams = {STREAM_ALARM, 1055 STREAM_MUSIC, 1056 STREAM_VOICE_CALL, 1057 STREAM_RING}; 1058 1059 int maxMusicVolume = mAudioManager.getStreamMaxVolume(STREAM_MUSIC); 1060 1061 for (int stream : streams) { 1062 if (mIsSingleVolume && stream != STREAM_MUSIC) { 1063 continue; 1064 } 1065 1066 // set ringer mode to back normal to not interfere with volume tests 1067 mAudioManager.setRingerMode(RINGER_MODE_NORMAL); 1068 1069 int maxVolume = mAudioManager.getStreamMaxVolume(stream); 1070 int minVolume = mAudioManager.getStreamMinVolume(stream); 1071 1072 // validate min 1073 assertTrue(String.format("minVolume(%d) must be >= 0", minVolume), minVolume >= 0); 1074 assertTrue(String.format("minVolume(%d) must be < maxVolume(%d)", minVolume, 1075 maxVolume), 1076 minVolume < maxVolume); 1077 1078 final int minNonZeroVolume = Math.max(minVolume, 1); 1079 mAudioManager.setStreamVolume(stream, minNonZeroVolume, 0); 1080 if (mUseFixedVolume) { 1081 assertEquals(maxVolume, mAudioManager.getStreamVolume(stream)); 1082 continue; 1083 } 1084 assertEquals(String.format("stream=%d", stream), 1085 minNonZeroVolume, mAudioManager.getStreamVolume(stream)); 1086 1087 if (stream == STREAM_MUSIC && mAudioManager.isWiredHeadsetOn()) { 1088 // due to new regulations, music sent over a wired headset may be volume limited 1089 // until the user explicitly increases the limit, so we can't rely on being able 1090 // to set the volume to getStreamMaxVolume(). Instead, determine the current limit 1091 // by increasing the volume until it won't go any higher, then use that volume as 1092 // the maximum for the purposes of this test 1093 int curvol = 0; 1094 int prevvol = 0; 1095 do { 1096 prevvol = curvol; 1097 mAudioManager.adjustStreamVolume(stream, ADJUST_RAISE, 0); 1098 curvol = mAudioManager.getStreamVolume(stream); 1099 } while (curvol != prevvol); 1100 maxVolume = maxMusicVolume = curvol; 1101 } 1102 waitForStreamVolumeSet(stream, maxVolume); 1103 assertCallDoesNotChangeStreamVolume( 1104 () -> mAudioManager.adjustStreamVolume(stream, ADJUST_RAISE, 0), 1105 stream, 1106 "No change expected at max volume"); 1107 1108 volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(stream)); 1109 assertCallChangesStreamVolume( 1110 () -> mAudioManager.adjustSuggestedStreamVolume(ADJUST_LOWER, stream, 0), 1111 stream, maxVolume - volumeDelta, 1112 "Vol ADJUST_LOWER suggested stream:" + stream + " maxVol:" + maxVolume); 1113 1114 // volume lower 1115 mAudioManager.setStreamVolume(stream, maxVolume, 0); 1116 volume = mAudioManager.getStreamVolume(stream); 1117 while (volume > minVolume) { 1118 volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(stream)); 1119 assertCallChangesStreamVolume( 1120 () -> mAudioManager.adjustStreamVolume(stream, ADJUST_LOWER, 0), 1121 stream, Math.max(0, volume - volumeDelta), 1122 "Vol ADJUST_LOWER on stream:" + stream + " vol:" + volume 1123 + " minVol:" + minVolume + " volDelta:" + volumeDelta); 1124 volume = mAudioManager.getStreamVolume(stream); 1125 } 1126 1127 mAudioManager.adjustStreamVolume(stream, ADJUST_SAME, 0); 1128 1129 // volume raise 1130 mAudioManager.setStreamVolume(stream, minNonZeroVolume, 0); 1131 volume = mAudioManager.getStreamVolume(stream); 1132 while (volume < maxVolume) { 1133 volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(stream)); 1134 assertCallChangesStreamVolume( 1135 () -> mAudioManager.adjustStreamVolume(stream, ADJUST_RAISE, 0), 1136 stream, Math.min(volume + volumeDelta, maxVolume), 1137 "Vol ADJUST_RAISE on stream:" + stream + " vol:" + volume 1138 + " maxVol:" + maxVolume + " volDelta:" + volumeDelta); 1139 volume = mAudioManager.getStreamVolume(stream); 1140 } 1141 1142 // volume same 1143 waitForStreamVolumeSet(stream, maxVolume); 1144 assertCallDoesNotChangeStreamVolume( 1145 () -> mAudioManager.adjustStreamVolume(stream, ADJUST_SAME, 0), 1146 stream, 1147 "Vol ADJUST_RAISE onADJUST_SAME stream:" + stream); 1148 mAudioManager.setStreamVolume(stream, maxVolume, 0); 1149 } 1150 1151 if (mUseFixedVolume) { 1152 return; 1153 } 1154 1155 boolean isMusicPlayingBeforeTest = false; 1156 if (mAudioManager.isMusicActive()) { 1157 isMusicPlayingBeforeTest = true; 1158 } 1159 1160 // TODO this doesn't test anything now that STREAM_MUSIC is the default 1161 MediaPlayer mp = MediaPlayer.create(mContext, MP3_TO_PLAY); 1162 assertNotNull(mp); 1163 mp.setAudioStreamType(STREAM_MUSIC); 1164 mp.setLooping(true); 1165 mp.start(); 1166 assertMusicActive(true); 1167 1168 waitForStreamVolumeSet(STREAM_MUSIC, maxMusicVolume - 1); 1169 // adjust volume as ADJUST_SAME 1170 assertCallDoesNotChangeStreamVolume( 1171 () -> mAudioManager.adjustVolume(ADJUST_SAME, 0), 1172 STREAM_MUSIC); 1173 1174 // adjust volume as ADJUST_RAISE 1175 waitForStreamVolumeSet(STREAM_MUSIC, 0); 1176 volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(STREAM_MUSIC)); 1177 assertCallChangesStreamVolume( 1178 () -> mAudioManager.adjustVolume(ADJUST_RAISE, 0), 1179 STREAM_MUSIC, 1180 volumeDelta); 1181 1182 // adjust volume as ADJUST_LOWER 1183 waitForStreamVolumeSet(STREAM_MUSIC, maxMusicVolume); 1184 volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(STREAM_MUSIC)); 1185 assertCallChangesStreamVolume( 1186 () -> mAudioManager.adjustVolume(ADJUST_LOWER, 0), 1187 STREAM_MUSIC, 1188 maxMusicVolume - volumeDelta); 1189 1190 mp.stop(); 1191 mp.release(); 1192 if (!isMusicPlayingBeforeTest) { 1193 assertMusicActive(false); 1194 } 1195 } 1196 1197 @Test testAccessibilityVolume()1198 public void testAccessibilityVolume() throws Exception { 1199 // TODO this does not test the positive case (having permissions) 1200 assumeFalse("AudioManagerTest testAccessibilityVolume() skipped: fixed volume", 1201 mUseFixedVolume); 1202 1203 final int maxA11yVol = mAudioManager.getStreamMaxVolume(STREAM_ACCESSIBILITY); 1204 assertWithMessage("Max a11yVol must be strictly positive") 1205 .that(maxA11yVol) 1206 .isGreaterThan(0); 1207 1208 // changing STREAM_ACCESSIBILITY is subject to permission 1209 assertCallDoesNotChangeStreamVolume( 1210 () -> mAudioManager.setStreamVolume(STREAM_ACCESSIBILITY, INIT_VOL + 1, 0), 1211 STREAM_ACCESSIBILITY, 1212 "Setting accessibility vol requires perms"); 1213 assertCallDoesNotChangeStreamVolume( 1214 () -> mAudioManager.adjustStreamVolume(STREAM_ACCESSIBILITY, ADJUST_LOWER, 0), 1215 STREAM_ACCESSIBILITY, 1216 "Setting accessibility vol requires perms"); 1217 1218 assertCallDoesNotChangeStreamVolume( 1219 () -> mAudioManager.adjustStreamVolume(STREAM_ACCESSIBILITY, ADJUST_RAISE, 0), 1220 STREAM_ACCESSIBILITY, 1221 "Setting accessibility vol requires perms"); 1222 } 1223 1224 @Test testSetVoiceCallVolumeToZeroPermission()1225 public void testSetVoiceCallVolumeToZeroPermission() { 1226 // Verify that only apps with MODIFY_PHONE_STATE can set VOICE_CALL_STREAM to 0 1227 mAudioManager.setStreamVolume(STREAM_VOICE_CALL, 0, 0); 1228 assertTrue("MODIFY_PHONE_STATE is required in order to set voice call volume to 0", 1229 mAudioManager.getStreamVolume(STREAM_VOICE_CALL) != 0); 1230 } 1231 1232 @Test testMuteFixedVolume()1233 public void testMuteFixedVolume() throws Exception { 1234 if (mSkipAutoVolumeTests) { 1235 // adjustStreamVolume is a no-op 1236 return; 1237 } 1238 int[] streams = { 1239 STREAM_VOICE_CALL, 1240 STREAM_MUSIC, 1241 STREAM_RING, 1242 STREAM_ALARM, 1243 STREAM_NOTIFICATION, 1244 STREAM_SYSTEM}; 1245 if (mUseFixedVolume) { 1246 for (int stream : streams) { 1247 mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_MUTE, 0); 1248 assertFalse("Muting should not affect a fixed volume device.", 1249 mAudioManager.isStreamMute(stream)); 1250 1251 mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_TOGGLE_MUTE, 0); 1252 assertFalse("Toggling mute should not affect a fixed volume device.", 1253 mAudioManager.isStreamMute(stream)); 1254 1255 mAudioManager.setStreamMute(stream, true); 1256 assertFalse("Muting should not affect a fixed volume device.", 1257 mAudioManager.isStreamMute(stream)); 1258 } 1259 } 1260 } 1261 1262 @Test testMuteDndAffectedStreams()1263 public void testMuteDndAffectedStreams() throws Exception { 1264 assumeFalse(mSkipRingerTests); 1265 int[] streams = { STREAM_RING }; 1266 // Mute streams 1267 Utils.toggleNotificationPolicyAccess( 1268 mContext.getPackageName(), getInstrumentation(), true); 1269 mAudioManager.setRingerMode(RINGER_MODE_SILENT); 1270 Utils.toggleNotificationPolicyAccess( 1271 mContext.getPackageName(), getInstrumentation(), false); 1272 // Verify streams cannot be unmuted without policy access. 1273 for (int stream : streams) { 1274 try { 1275 mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_UNMUTE, 0); 1276 assertEquals("Apps without Notification policy access can't change ringer mode", 1277 RINGER_MODE_SILENT, mAudioManager.getRingerMode()); 1278 } catch (SecurityException e) { 1279 } 1280 1281 try { 1282 mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_TOGGLE_MUTE, 1283 0); 1284 assertEquals("Apps without Notification policy access can't change ringer mode", 1285 RINGER_MODE_SILENT, mAudioManager.getRingerMode()); 1286 } catch (SecurityException e) { 1287 } 1288 1289 try { 1290 mAudioManager.setStreamMute(stream, false); 1291 assertEquals("Apps without Notification policy access can't change ringer mode", 1292 RINGER_MODE_SILENT, mAudioManager.getRingerMode()); 1293 } catch (SecurityException e) { 1294 } 1295 } 1296 1297 // This ensures we're out of vibrate or silent modes. 1298 Utils.toggleNotificationPolicyAccess( 1299 mContext.getPackageName(), getInstrumentation(), true); 1300 mAudioManager.setRingerMode(RINGER_MODE_NORMAL); 1301 for (int stream : streams) { 1302 // ensure each stream is on and turned up. 1303 mAudioManager.setStreamVolume(stream, 1304 mAudioManager.getStreamMaxVolume(stream), 1305 0); 1306 1307 Utils.toggleNotificationPolicyAccess( 1308 mContext.getPackageName(), getInstrumentation(), false); 1309 try { 1310 mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_MUTE, 0); 1311 assertEquals("Apps without Notification policy access can't change ringer mode", 1312 RINGER_MODE_NORMAL, mAudioManager.getRingerMode()); 1313 } catch (SecurityException e) { 1314 } 1315 try { 1316 mAudioManager.adjustStreamVolume( 1317 stream, AudioManager.ADJUST_TOGGLE_MUTE, 0); 1318 assertEquals("Apps without Notification policy access can't change ringer mode", 1319 RINGER_MODE_NORMAL, mAudioManager.getRingerMode()); 1320 } catch (SecurityException e) { 1321 } 1322 1323 try { 1324 mAudioManager.setStreamMute(stream, true); 1325 assertEquals("Apps without Notification policy access can't change ringer mode", 1326 RINGER_MODE_NORMAL, mAudioManager.getRingerMode()); 1327 } catch (SecurityException e) { 1328 } 1329 Utils.toggleNotificationPolicyAccess( 1330 mContext.getPackageName(), getInstrumentation(), true); 1331 testStreamMuting(stream); 1332 } 1333 } 1334 1335 @Test testMuteDndUnaffectedStreams()1336 public void testMuteDndUnaffectedStreams() throws Exception { 1337 assumeFalse(mSkipRingerTests); 1338 int[] streams = { 1339 STREAM_VOICE_CALL, 1340 STREAM_MUSIC, 1341 STREAM_ALARM 1342 }; 1343 1344 int muteAffectedStreams = System.getInt(mContext.getContentResolver(), 1345 System.MUTE_STREAMS_AFFECTED, 1346 // same defaults as in AudioService. Should be kept in sync. 1347 (1 << STREAM_MUSIC) | 1348 (1 << STREAM_RING) | 1349 (1 << STREAM_NOTIFICATION) | 1350 (1 << STREAM_SYSTEM) | 1351 (1 << STREAM_VOICE_CALL)); 1352 1353 Utils.toggleNotificationPolicyAccess( 1354 mContext.getPackageName(), getInstrumentation(), true); 1355 // This ensures we're out of vibrate or silent modes. 1356 mAudioManager.setRingerMode(RINGER_MODE_NORMAL); 1357 Utils.toggleNotificationPolicyAccess( 1358 mContext.getPackageName(), getInstrumentation(), false); 1359 for (int stream : streams) { 1360 // ensure each stream is on and turned up. 1361 mAudioManager.setStreamVolume(stream, 1362 mAudioManager.getStreamMaxVolume(stream), 1363 0); 1364 if (((1 << stream) & muteAffectedStreams) == 0) { 1365 mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_MUTE, 0); 1366 assertFalse("Stream " + stream + " should not be affected by mute.", 1367 mAudioManager.isStreamMute(stream)); 1368 mAudioManager.setStreamMute(stream, true); 1369 assertFalse("Stream " + stream + " should not be affected by mute.", 1370 mAudioManager.isStreamMute(stream)); 1371 mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_TOGGLE_MUTE, 1372 0); 1373 assertFalse("Stream " + stream + " should not be affected by mute.", 1374 mAudioManager.isStreamMute(stream)); 1375 continue; 1376 } 1377 testStreamMuting(stream); 1378 } 1379 } 1380 testStreamMuting(int stream)1381 private void testStreamMuting(int stream) { 1382 if (mSkipAutoVolumeTests) { 1383 // adjustStreamVolume is a no-op 1384 return; 1385 } 1386 getInstrumentation().getUiAutomation() 1387 .adoptShellPermissionIdentity(Manifest.permission.QUERY_AUDIO_STATE); 1388 1389 final int streamVolume = mAudioManager.getLastAudibleStreamVolume(stream); 1390 1391 // Voice call requires MODIFY_PHONE_STATE, so we should not be able to mute 1392 if (stream == STREAM_VOICE_CALL) { 1393 mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_MUTE, 0); 1394 assertFalse("Muting voice call stream (" + stream + ") should require " 1395 + "MODIFY_PHONE_STATE.", mAudioManager.isStreamMute(stream)); 1396 } else { 1397 mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_MUTE, 0); 1398 assertTrue("Muting stream " + stream + " failed.", 1399 mAudioManager.isStreamMute(stream)); 1400 1401 assertEquals(streamVolume, mAudioManager.getLastAudibleStreamVolume(stream)); 1402 1403 mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_UNMUTE, 0); 1404 assertFalse("Unmuting stream " + stream + " failed.", 1405 mAudioManager.isStreamMute(stream)); 1406 1407 assertEquals(streamVolume, mAudioManager.getLastAudibleStreamVolume(stream)); 1408 1409 mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_TOGGLE_MUTE, 0); 1410 assertTrue("Toggling mute on stream " + stream + " failed.", 1411 mAudioManager.isStreamMute(stream)); 1412 1413 assertEquals(streamVolume, mAudioManager.getLastAudibleStreamVolume(stream)); 1414 1415 mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_TOGGLE_MUTE, 0); 1416 assertFalse("Toggling mute on stream " + stream + " failed.", 1417 mAudioManager.isStreamMute(stream)); 1418 1419 assertEquals(streamVolume, mAudioManager.getLastAudibleStreamVolume(stream)); 1420 1421 mAudioManager.setStreamMute(stream, true); 1422 assertTrue("Muting stream " + stream + " using setStreamMute failed", 1423 mAudioManager.isStreamMute(stream)); 1424 1425 assertEquals(streamVolume, mAudioManager.getLastAudibleStreamVolume(stream)); 1426 1427 // mute it three more times to verify the ref counting is gone. 1428 mAudioManager.setStreamMute(stream, true); 1429 mAudioManager.setStreamMute(stream, true); 1430 mAudioManager.setStreamMute(stream, true); 1431 1432 mAudioManager.setStreamMute(stream, false); 1433 assertFalse("Unmuting stream " + stream + " using setStreamMute failed.", 1434 mAudioManager.isStreamMute(stream)); 1435 } 1436 assertEquals(streamVolume, mAudioManager.getLastAudibleStreamVolume(stream)); 1437 1438 getInstrumentation().getUiAutomation().dropShellPermissionIdentity(); 1439 } 1440 1441 @Test testSetInvalidRingerMode()1442 public void testSetInvalidRingerMode() { 1443 int ringerMode = mAudioManager.getRingerMode(); 1444 mAudioManager.setRingerMode(-1337); 1445 assertEquals(ringerMode, mAudioManager.getRingerMode()); 1446 1447 mAudioManager.setRingerMode(-3007); 1448 assertEquals(ringerMode, mAudioManager.getRingerMode()); 1449 } 1450 1451 /** 1452 * Ensure adjusting volume when total silence zen mode is enabled does not affect 1453 * stream volumes. 1454 */ 1455 @Test testAdjustVolumeInTotalSilenceMode()1456 public void testAdjustVolumeInTotalSilenceMode() throws Exception { 1457 if (mSkipAutoVolumeTests) { 1458 // adjustStreamVolume is a no-op 1459 return; 1460 } 1461 assumeFalse(mSkipRingerTests); 1462 1463 final int SILENCE_VOL = 0; 1464 final int prevVol = mAudioManager.getStreamVolume(STREAM_MUSIC); 1465 Utils.toggleNotificationPolicyAccess(mContext.getPackageName(), getInstrumentation(), true); 1466 1467 // Set to silence 1468 setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_NONE); 1469 assertThat(mAudioManager.getStreamVolume(STREAM_MUSIC)).isEqualTo(SILENCE_VOL); 1470 1471 // Raise shouldn't work when silenced 1472 assertCallDoesNotChangeStreamVolume( 1473 () -> mAudioManager.adjustStreamVolume(STREAM_MUSIC, ADJUST_RAISE, 0 /* flags */), 1474 STREAM_MUSIC); 1475 1476 // Set the mode out of silence 1477 setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL); 1478 1479 // Volume should be back to normal 1480 assertThat(mAudioManager.getStreamVolume(STREAM_MUSIC)).isEqualTo(INIT_VOL); 1481 1482 final int MEDIA_DELTA = getVolumeDelta(mAudioManager.getStreamVolume(STREAM_MUSIC)); 1483 assertCallChangesStreamVolume( 1484 () -> mAudioManager.adjustStreamVolume(STREAM_MUSIC, ADJUST_RAISE, 0 /* flags */), 1485 STREAM_MUSIC, 1486 INIT_VOL + MEDIA_DELTA); 1487 } 1488 1489 @Test testAdjustVolumeInAlarmsOnlyMode()1490 public void testAdjustVolumeInAlarmsOnlyMode() throws Exception { 1491 assumeFalse(mSkipRingerTests); 1492 1493 Utils.toggleNotificationPolicyAccess( 1494 mContext.getPackageName(), getInstrumentation(), true); 1495 1496 setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALARMS); 1497 1498 int volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(STREAM_MUSIC)); 1499 1500 // Why should this go through? This call doesn't exit zen mode, for reasons... 1501 assertCallChangesStreamVolume( 1502 () -> mAudioManager.adjustStreamVolume(STREAM_MUSIC, ADJUST_RAISE, 0), 1503 STREAM_MUSIC, 1504 INIT_VOL + volumeDelta, 1505 "Changing music volume should work when in alarm only mode"); 1506 } 1507 1508 @Test testSetStreamVolumeInTotalSilenceMode()1509 public void testSetStreamVolumeInTotalSilenceMode() throws Exception { 1510 assumeFalse(mSkipRingerTests); 1511 Utils.toggleNotificationPolicyAccess( 1512 mContext.getPackageName(), getInstrumentation(), true); 1513 1514 setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_NONE); 1515 1516 // cannot adjust music, can adjust ringer since it could exit DND 1517 assertCallDoesNotChangeStreamVolume( 1518 () -> mAudioManager.setStreamVolume(STREAM_MUSIC, 7, 0), 1519 STREAM_MUSIC, 1520 "Should not be able to adjust media volume in Zen mode"); 1521 assertCallChangesStreamVolume( 1522 () -> mAudioManager.setStreamVolume(STREAM_RING, 7, 0), 1523 STREAM_RING, 1524 7, 1525 "Should be able to adjust ring volume in Zen mode"); 1526 } 1527 1528 @Test testSetStreamVolumeInAlarmsOnlyMode()1529 public void testSetStreamVolumeInAlarmsOnlyMode() throws Exception { 1530 assumeFalse(mSkipRingerTests); 1531 Utils.toggleNotificationPolicyAccess( 1532 mContext.getPackageName(), getInstrumentation(), true); 1533 1534 setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALARMS); 1535 1536 // can still adjust music and ring volume 1537 assertCallChangesStreamVolume( 1538 () -> mAudioManager.setStreamVolume(STREAM_MUSIC, 3, 0), 1539 STREAM_MUSIC, 1540 3, 1541 "Stream volume settable in alarm only zen"); 1542 assertCallChangesStreamVolume( 1543 () -> mAudioManager.setStreamVolume(STREAM_RING, 7, 0), 1544 STREAM_RING, 1545 7, 1546 "Stream volume settable in alarm only zen"); 1547 1548 } 1549 1550 @Test testSetStreamVolumeInPriorityOnlyMode()1551 public void testSetStreamVolumeInPriorityOnlyMode() throws Exception { 1552 assumeFalse(mSkipRingerTests); 1553 Utils.toggleNotificationPolicyAccess( 1554 mContext.getPackageName(), getInstrumentation(), true); 1555 1556 final int testRingerVol = getTestRingerVol(); 1557 1558 // disallow all sounds in priority only, turn on priority only DND 1559 mNm.setNotificationPolicy(new NotificationManager.Policy(0, 0 , 0)); 1560 setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY); 1561 1562 // attempt to change volume 1563 assertCallDoesNotChangeStreamVolume( 1564 () -> mAudioManager.setStreamVolume(STREAM_MUSIC, 3, 0), 1565 STREAM_MUSIC, 1566 "Should not be able to change MUSIC volume in priority zen"); 1567 assertCallDoesNotChangeStreamVolume( 1568 () -> mAudioManager.setStreamVolume(STREAM_ALARM, 5, 0), 1569 STREAM_ALARM, 1570 "Should not be able to change ALARM volume in priority zen"); 1571 1572 assertCallChangesStreamVolume( 1573 () -> mAudioManager.setStreamVolume(STREAM_RING, testRingerVol, 0), 1574 STREAM_RING, 1575 testRingerVol, 1576 "Should be able to set ring volume in zen"); 1577 1578 1579 // Turn off zen to evaluate stream vols following zen 1580 setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL); 1581 1582 assertEquals(INIT_VOL, mAudioManager.getStreamVolume(STREAM_MUSIC)); 1583 assertEquals(INIT_VOL, mAudioManager.getStreamVolume(STREAM_ALARM)); 1584 assertEquals(testRingerVol, mAudioManager.getStreamVolume(STREAM_RING)); 1585 } 1586 1587 @Test testAdjustVolumeInPriorityOnly()1588 public void testAdjustVolumeInPriorityOnly() throws Exception { 1589 assumeFalse(mSkipRingerTests); 1590 Utils.toggleNotificationPolicyAccess( 1591 mContext.getPackageName(), getInstrumentation(), true); 1592 1593 // disallow all sounds in priority only, turn on priority only DND, try to change volume 1594 mNm.setNotificationPolicy(new NotificationManager.Policy(0, 0, 0)); 1595 setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY); 1596 1597 1598 int volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(STREAM_RING)); 1599 assertCallDoesNotChangeStreamVolume( 1600 () -> mAudioManager.adjustStreamVolume(STREAM_MUSIC, ADJUST_RAISE, 0), 1601 STREAM_MUSIC, 1602 "Should not be able to set music vol in zen"); 1603 1604 assertCallDoesNotChangeStreamVolume( 1605 () -> mAudioManager.adjustStreamVolume(STREAM_ALARM, ADJUST_RAISE, 0), 1606 STREAM_ALARM, 1607 "Should not be able to set alarm vol in zen"); 1608 1609 assertCallChangesStreamVolume( 1610 () -> mAudioManager.adjustStreamVolume(STREAM_RING, ADJUST_RAISE, 0), 1611 STREAM_RING, 1612 INIT_VOL + volumeDelta, 1613 "Should be able to set ring volume in zen"); 1614 1615 // Turn off zen and make sure stream levels are still the same prior to zen 1616 // aside from ringer since ringer can exit dnd 1617 setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL); 1618 1619 assertEquals(INIT_VOL, mAudioManager.getStreamVolume(STREAM_MUSIC)); 1620 assertEquals(INIT_VOL, mAudioManager.getStreamVolume(STREAM_ALARM)); 1621 assertEquals(INIT_VOL + volumeDelta, mAudioManager.getStreamVolume(STREAM_RING)); 1622 } 1623 1624 @Test testPriorityOnlyMuteAll()1625 public void testPriorityOnlyMuteAll() throws Exception { 1626 assumeFalse(mSkipRingerTests); 1627 Utils.toggleNotificationPolicyAccess( 1628 mContext.getPackageName(), getInstrumentation(), true); 1629 Map<Integer, MuteStateTransition> expectedTransitions = Map.of( 1630 STREAM_MUSIC, new MuteStateTransition(false, true), 1631 STREAM_SYSTEM, new MuteStateTransition(false, true), 1632 STREAM_ALARM, new MuteStateTransition(false, true), 1633 // if channels cannot bypass DND, the Ringer stream should be muted, else it 1634 // shouldn't be muted 1635 STREAM_RING, new MuteStateTransition(false, !mAppsBypassingDnd)); 1636 1637 assertStreamMuteStateChange(() -> { 1638 // disallow all sounds in priority only, turn on priority only DND 1639 mNm.setNotificationPolicy(new NotificationManager.Policy(0, 0, 0)); 1640 setInterruptionFilter( NotificationManager.INTERRUPTION_FILTER_PRIORITY); 1641 }, 1642 expectedTransitions, 1643 "Priority mute all should mute all streams including ringer if" + 1644 "channels cannot bypass DND"); 1645 } 1646 1647 @Test testPriorityOnlyMediaAllowed()1648 public void testPriorityOnlyMediaAllowed() throws Exception { 1649 assumeFalse(mSkipRingerTests); 1650 Utils.toggleNotificationPolicyAccess( 1651 mContext.getPackageName(), getInstrumentation(), true); 1652 1653 Map<Integer, MuteStateTransition> expectedTransitions = Map.of( 1654 STREAM_MUSIC, new MuteStateTransition(false, false), 1655 STREAM_SYSTEM, new MuteStateTransition(false, true), 1656 STREAM_ALARM, new MuteStateTransition(false, true), 1657 STREAM_RING, new MuteStateTransition(false, !mAppsBypassingDnd)); 1658 assertStreamMuteStateChange(() -> { 1659 // allow only media in priority only 1660 mNm.setNotificationPolicy(new NotificationManager.Policy( 1661 NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA, 0, 0)); 1662 setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY); 1663 }, 1664 expectedTransitions, 1665 "Priority category media should leave media unmuted, and rest muted"); 1666 } 1667 1668 @Test testPriorityOnlySystemAllowed()1669 public void testPriorityOnlySystemAllowed() throws Exception { 1670 assumeFalse(mSkipRingerTests); 1671 Utils.toggleNotificationPolicyAccess( 1672 mContext.getPackageName(), getInstrumentation(), true); 1673 1674 Map<Integer, MuteStateTransition> expectedTransitions = Map.of( 1675 STREAM_MUSIC, new MuteStateTransition(false, true), 1676 STREAM_SYSTEM, new MuteStateTransition(false, false), 1677 STREAM_ALARM, new MuteStateTransition(false, true), 1678 STREAM_RING, new MuteStateTransition(false, false)); 1679 1680 assertStreamMuteStateChange(() -> { 1681 // allow only system in priority only 1682 mNm.setNotificationPolicy(new NotificationManager.Policy( 1683 NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM, 0, 0)); 1684 setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY); 1685 }, 1686 expectedTransitions, 1687 "PRIORITY_CATEGORY_SYSTEM should leave RING and SYSTEM unmuted"); 1688 } 1689 1690 @Test testPriorityOnlySystemDisallowedWithRingerMuted()1691 public void testPriorityOnlySystemDisallowedWithRingerMuted() throws Exception { 1692 assumeFalse(mSkipRingerTests); 1693 1694 Utils.toggleNotificationPolicyAccess( 1695 mContext.getPackageName(), getInstrumentation(), true); 1696 Map<Integer, MuteStateTransition> expectedSilentTransition = Map.of( 1697 STREAM_MUSIC, new MuteStateTransition(false, false), 1698 STREAM_SYSTEM, new MuteStateTransition(false, true), 1699 STREAM_ALARM, new MuteStateTransition(false, false), 1700 STREAM_RING, new MuteStateTransition(false, true)); 1701 1702 assertStreamMuteStateChange(() -> { 1703 mAudioManager.setStreamVolume(STREAM_RING, 0, 0); 1704 mAudioManager.setRingerMode(RINGER_MODE_SILENT); 1705 }, 1706 expectedSilentTransition, 1707 "RING/SYSTEM should be silenced by RINGER_MODE"); 1708 1709 Map<Integer, MuteStateTransition> expectedTransitions = Map.of( 1710 STREAM_MUSIC, new MuteStateTransition(false, true), 1711 STREAM_SYSTEM, new MuteStateTransition(true, true), 1712 STREAM_ALARM, new MuteStateTransition(false, true), 1713 STREAM_RING, new MuteStateTransition(true, true)); 1714 1715 assertStreamMuteStateChange(() -> { 1716 // allow only system in priority only 1717 mNm.setNotificationPolicy(new NotificationManager.Policy( 1718 NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM, 0, 0)); 1719 setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY); 1720 }, 1721 expectedTransitions, 1722 "SYSTEM/RING should stay muted if RINGER_MODE_SILENT entering zen"); 1723 } 1724 1725 @Test testPriorityOnlyAlarmsAllowed()1726 public void testPriorityOnlyAlarmsAllowed() throws Exception { 1727 assumeFalse(mSkipRingerTests); 1728 1729 Utils.toggleNotificationPolicyAccess( 1730 mContext.getPackageName(), getInstrumentation(), true); 1731 1732 Map<Integer, MuteStateTransition> expectedTransitions = Map.of( 1733 STREAM_MUSIC, new MuteStateTransition(false, true), 1734 STREAM_SYSTEM, new MuteStateTransition(false, true), 1735 STREAM_ALARM, new MuteStateTransition(false, false), 1736 // if channels cannot bypass DND, the Ringer stream should be muted, else it 1737 // shouldn't be muted 1738 STREAM_RING, new MuteStateTransition(false, !mAppsBypassingDnd)); 1739 1740 1741 assertStreamMuteStateChange(() -> { 1742 // allow only alarms in priority only 1743 mNm.setNotificationPolicy(new NotificationManager.Policy( 1744 NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS, 0, 0)); 1745 setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY); 1746 }, 1747 expectedTransitions, 1748 "Alarm stream should be unmuted, all others muted"); 1749 } 1750 1751 @Test testPriorityOnlyRingerAllowed()1752 public void testPriorityOnlyRingerAllowed() throws Exception { 1753 assumeFalse(mSkipRingerTests); 1754 1755 Utils.toggleNotificationPolicyAccess( 1756 mContext.getPackageName(), getInstrumentation(), true); 1757 1758 Map<Integer, MuteStateTransition> expectedTransitions = Map.of( 1759 STREAM_MUSIC, new MuteStateTransition(false, true), 1760 STREAM_SYSTEM, new MuteStateTransition(false, true), 1761 STREAM_ALARM, new MuteStateTransition(false, true), 1762 STREAM_RING, new MuteStateTransition(false, false)); 1763 1764 assertStreamMuteStateChange(() -> { 1765 // allow only reminders in priority only 1766 mNm.setNotificationPolicy(new NotificationManager.Policy( 1767 NotificationManager.Policy.PRIORITY_CATEGORY_REMINDERS, 0, 0)); 1768 setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY); 1769 }, 1770 expectedTransitions, 1771 "All streams except ring should be unmuted"); 1772 } 1773 1774 @Test testPriorityOnlyChannelsCanBypassDnd()1775 public void testPriorityOnlyChannelsCanBypassDnd() throws Exception { 1776 assumeFalse(mSkipRingerTests); 1777 1778 Utils.toggleNotificationPolicyAccess( 1779 mContext.getPackageName(), getInstrumentation(), true); 1780 1781 final String NOTIFICATION_CHANNEL_ID = "test_id_" + SystemClock.uptimeMillis(); 1782 NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "TEST", 1783 NotificationManager.IMPORTANCE_DEFAULT); 1784 try { 1785 1786 // create a channel that can bypass dnd 1787 channel.setBypassDnd(true); 1788 mNm.createNotificationChannel(channel); 1789 Map<Integer, MuteStateTransition> expectedTransitions = Map.of( 1790 STREAM_MUSIC, new MuteStateTransition(false, true), 1791 STREAM_SYSTEM, new MuteStateTransition(false, true), 1792 STREAM_ALARM, new MuteStateTransition(false, true), 1793 STREAM_RING, new MuteStateTransition(false, false)); 1794 1795 // allow nothing 1796 assertStreamMuteStateChange(() -> { 1797 mNm.setNotificationPolicy(new NotificationManager.Policy(0,0, 0)); 1798 setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY); 1799 }, 1800 expectedTransitions, 1801 "Ringer stream should not be muted." 1802 + " areChannelsBypassing=" 1803 + NotificationManager.getService().areChannelsBypassingDnd()); 1804 1805 // delete the channel that can bypass dnd 1806 Map<Integer, MuteStateTransition> expectedTransitionsDeleteChannel = Map.of( 1807 STREAM_MUSIC, new MuteStateTransition(true, true), 1808 STREAM_SYSTEM, new MuteStateTransition(true, true), 1809 STREAM_ALARM, new MuteStateTransition(true, true), 1810 // if channels cannot bypass DND, the Ringer stream should be muted, else it 1811 // shouldn't be muted 1812 STREAM_RING, new MuteStateTransition(false, !mAppsBypassingDnd)); 1813 1814 assertStreamMuteStateChange(() -> mNm.deleteNotificationChannel( 1815 NOTIFICATION_CHANNEL_ID), 1816 expectedTransitionsDeleteChannel, 1817 "Ringer stream should be muted if apps are not bypassing dnd" 1818 + " areChannelsBypassing=" 1819 + NotificationManager.getService().areChannelsBypassingDnd()); 1820 } finally { 1821 mNm.deleteNotificationChannel(NOTIFICATION_CHANNEL_ID); 1822 } 1823 } 1824 1825 @Test testAdjustVolumeWithIllegalDirection()1826 public void testAdjustVolumeWithIllegalDirection() throws Exception { 1827 if (mSkipAutoVolumeTests) { 1828 // adjustVolume is a no-op 1829 return; 1830 } 1831 // Call the method with illegal direction. System should not reboot. 1832 mAudioManager.adjustVolume(37, 0); 1833 } 1834 1835 @Test testGetStreamVolumeDbWithIllegalArguments()1836 public void testGetStreamVolumeDbWithIllegalArguments() throws Exception { 1837 Exception ex = null; 1838 // invalid stream type 1839 try { 1840 float gain = mAudioManager.getStreamVolumeDb(-100 /*streamType*/, 0, 1841 AudioDeviceInfo.TYPE_BUILTIN_SPEAKER); 1842 } catch (Exception e) { 1843 ex = e; // expected 1844 } 1845 assertNotNull("No exception was thrown for an invalid stream type", ex); 1846 assertEquals("Wrong exception thrown for invalid stream type", 1847 ex.getClass(), IllegalArgumentException.class); 1848 1849 // invalid volume index 1850 ex = null; 1851 try { 1852 float gain = mAudioManager.getStreamVolumeDb(STREAM_MUSIC, -101 /*volume*/, 1853 AudioDeviceInfo.TYPE_BUILTIN_SPEAKER); 1854 } catch (Exception e) { 1855 ex = e; // expected 1856 } 1857 assertNotNull("No exception was thrown for an invalid volume index", ex); 1858 assertEquals("Wrong exception thrown for invalid volume index", 1859 ex.getClass(), IllegalArgumentException.class); 1860 1861 // invalid out of range volume index 1862 ex = null; 1863 try { 1864 final int maxVol = mAudioManager.getStreamMaxVolume(STREAM_MUSIC); 1865 float gain = mAudioManager.getStreamVolumeDb(STREAM_MUSIC, maxVol + 1, 1866 AudioDeviceInfo.TYPE_BUILTIN_SPEAKER); 1867 } catch (Exception e) { 1868 ex = e; // expected 1869 } 1870 assertNotNull("No exception was thrown for an invalid out of range volume index", ex); 1871 assertEquals("Wrong exception thrown for invalid out of range volume index", 1872 ex.getClass(), IllegalArgumentException.class); 1873 1874 // invalid device type 1875 ex = null; 1876 try { 1877 float gain = mAudioManager.getStreamVolumeDb(STREAM_MUSIC, 0, 1878 -102 /*deviceType*/); 1879 } catch (Exception e) { 1880 ex = e; // expected 1881 } 1882 assertNotNull("No exception was thrown for an invalid device type", ex); 1883 assertEquals("Wrong exception thrown for invalid device type", 1884 ex.getClass(), IllegalArgumentException.class); 1885 1886 // invalid input device type 1887 ex = null; 1888 try { 1889 float gain = mAudioManager.getStreamVolumeDb(STREAM_MUSIC, 0, 1890 AudioDeviceInfo.TYPE_BUILTIN_MIC); 1891 } catch (Exception e) { 1892 ex = e; // expected 1893 } 1894 assertNotNull("No exception was thrown for an invalid input device type", ex); 1895 assertEquals("Wrong exception thrown for invalid input device type", 1896 ex.getClass(), IllegalArgumentException.class); 1897 } 1898 1899 @Test testGetStreamVolumeDb()1900 public void testGetStreamVolumeDb() throws Exception { 1901 for (int streamType : PUBLIC_STREAM_TYPES) { 1902 // verify mininum index is strictly inferior to maximum index 1903 final int minIndex = mAudioManager.getStreamMinVolume(streamType); 1904 final int maxIndex = mAudioManager.getStreamMaxVolume(streamType); 1905 assertTrue("Min vol index (" + minIndex + ") for stream " + streamType + " not inferior" 1906 + " to max vol index (" + maxIndex + ")", minIndex <= maxIndex); 1907 float prevGain = Float.NEGATIVE_INFINITY; 1908 // verify gain increases with the volume indices 1909 for (int idx = minIndex ; idx <= maxIndex ; idx++) { 1910 float gain = mAudioManager.getStreamVolumeDb(streamType, idx, 1911 AudioDeviceInfo.TYPE_BUILTIN_SPEAKER); 1912 assertTrue("Non-monotonically increasing gain at index " + idx + " for stream" 1913 + streamType, prevGain <= gain); 1914 prevGain = gain; 1915 } 1916 } 1917 } 1918 1919 @Test testAdjustSuggestedStreamVolumeWithIllegalArguments()1920 public void testAdjustSuggestedStreamVolumeWithIllegalArguments() throws Exception { 1921 // Call the method with illegal direction. System should not reboot. 1922 mAudioManager.adjustSuggestedStreamVolume(37, STREAM_MUSIC, 0); 1923 1924 // Call the method with illegal stream. System should not reboot. 1925 mAudioManager.adjustSuggestedStreamVolume(ADJUST_RAISE, 66747, 0); 1926 } 1927 1928 @CddTest(requirement="5.4.1/C-1-4") 1929 @Test testGetMicrophones()1930 public void testGetMicrophones() throws Exception { 1931 if (!mContext.getPackageManager().hasSystemFeature( 1932 PackageManager.FEATURE_MICROPHONE)) { 1933 return; 1934 } 1935 List<MicrophoneInfo> microphones = mAudioManager.getMicrophones(); 1936 assertTrue(microphones.size() > 0); 1937 for (int i = 0; i < microphones.size(); i++) { 1938 MicrophoneInfo microphone = microphones.get(i); 1939 Log.i(TAG, "deviceId:" + microphone.getDescription()); 1940 Log.i(TAG, "portId:" + microphone.getId()); 1941 Log.i(TAG, "type:" + microphone.getType()); 1942 Log.i(TAG, "address:" + microphone.getAddress()); 1943 Log.i(TAG, "deviceLocation:" + microphone.getLocation()); 1944 Log.i(TAG, "deviceGroup:" + microphone.getGroup() 1945 + " index:" + microphone.getIndexInTheGroup()); 1946 MicrophoneInfo.Coordinate3F position = microphone.getPosition(); 1947 Log.i(TAG, "position:" + position.x + " " + position.y + " " + position.z); 1948 MicrophoneInfo.Coordinate3F orientation = microphone.getOrientation(); 1949 Log.i(TAG, "orientation:" + orientation.x + " " 1950 + orientation.y + " " + orientation.z); 1951 Log.i(TAG, "frequencyResponse:" + microphone.getFrequencyResponse()); 1952 Log.i(TAG, "channelMapping:" + microphone.getChannelMapping()); 1953 Log.i(TAG, "sensitivity:" + microphone.getSensitivity()); 1954 Log.i(TAG, "max spl:" + microphone.getMaxSpl()); 1955 Log.i(TAG, "min spl:" + microphone.getMinSpl()); 1956 Log.i(TAG, "directionality:" + microphone.getDirectionality()); 1957 Log.i(TAG, "--------------"); 1958 } 1959 } 1960 1961 @Test testIsHapticPlaybackSupported()1962 public void testIsHapticPlaybackSupported() { 1963 // Calling the API to make sure it doesn't crash. 1964 Log.i(TAG, "isHapticPlaybackSupported: " + AudioManager.isHapticPlaybackSupported()); 1965 } 1966 1967 @Test testIsUltrasoundSupported()1968 public void testIsUltrasoundSupported() { 1969 // Calling the API to make sure it must crash due to no permission. 1970 try { 1971 mAudioManager.isUltrasoundSupported(); 1972 fail("isUltrasoundSupported must fail due to no permission"); 1973 } catch (SecurityException e) { 1974 } 1975 } 1976 1977 @Test testIsHotwordStreamSupported()1978 public void testIsHotwordStreamSupported() { 1979 // Validate API requires permission 1980 assertThrows(SecurityException.class, () -> mAudioManager.isHotwordStreamSupported(false)); 1981 assertThrows(SecurityException.class, () -> mAudioManager.isHotwordStreamSupported(true)); 1982 // Validate functionality when caller holds appropriate permissions 1983 InstrumentationRegistry.getInstrumentation() 1984 .getUiAutomation() 1985 .adoptShellPermissionIdentity( 1986 Manifest.permission.CAPTURE_AUDIO_HOTWORD); 1987 boolean result1 = mAudioManager.isHotwordStreamSupported(false); 1988 boolean result2 = mAudioManager.isHotwordStreamSupported(true); 1989 1990 InstrumentationRegistry.getInstrumentation() 1991 .getUiAutomation() 1992 .dropShellPermissionIdentity(); 1993 } 1994 1995 @Test testGetAudioHwSyncForSession()1996 public void testGetAudioHwSyncForSession() { 1997 // AudioManager.getAudioHwSyncForSession is not supported before S 1998 if (ApiLevelUtil.isAtMost(Build.VERSION_CODES.R)) { 1999 Log.i(TAG, "testGetAudioHwSyncForSession skipped, release: " + Build.VERSION.SDK_INT); 2000 return; 2001 } 2002 try { 2003 int sessionId = mAudioManager.generateAudioSessionId(); 2004 assertNotEquals("testGetAudioHwSyncForSession cannot get audio session ID", 2005 AudioManager.ERROR, sessionId); 2006 int hwSyncId = mAudioManager.getAudioHwSyncForSession(sessionId); 2007 Log.i(TAG, "getAudioHwSyncForSession: " + hwSyncId); 2008 } catch (UnsupportedOperationException e) { 2009 Log.i(TAG, "getAudioHwSyncForSession not supported"); 2010 } catch (Exception e) { 2011 fail("Unexpected exception thrown by getAudioHwSyncForSession: " + e); 2012 } 2013 } 2014 setInterruptionFilter(int filter)2015 private void setInterruptionFilter(int filter) throws Exception { 2016 // TODO (b/294941884) investigate uncommenting this 2017 /* 2018 assertWithMessage("Setting interruption filter relies on unset ringer mode") 2019 .that(mAudioManager.getRingerMode()) 2020 .isEqualTo(AudioManager.RINGER_MODE_NORMAL); 2021 */ 2022 2023 if (mNm.getCurrentInterruptionFilter() == filter) { 2024 return; 2025 } 2026 final int expectedRingerMode = switch(filter) { 2027 case NotificationManager.INTERRUPTION_FILTER_NONE, 2028 NotificationManager.INTERRUPTION_FILTER_PRIORITY, 2029 NotificationManager.INTERRUPTION_FILTER_ALARMS 2030 -> AudioManager.RINGER_MODE_SILENT; 2031 case NotificationManager.INTERRUPTION_FILTER_ALL -> AudioManager.RINGER_MODE_NORMAL; 2032 default -> throw new AssertionError("Unexpected notification type"); 2033 }; 2034 2035 2036 var future = mCancelRule.registerFuture(getFutureForIntent( 2037 mContext, 2038 AudioManager.RINGER_MODE_CHANGED_ACTION, 2039 i -> (i != null) 2040 && i.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1) 2041 == expectedRingerMode)); 2042 mNm.setInterruptionFilter(filter); 2043 var intent = future.get(FUTURE_WAIT_SECS, TimeUnit.SECONDS); 2044 } 2045 getVolumeDelta(int volume)2046 private int getVolumeDelta(int volume) { 2047 return 1; 2048 } 2049 getTestRingerVol()2050 private int getTestRingerVol() { 2051 final int currentRingVol = mAudioManager.getStreamVolume(STREAM_RING); 2052 final int maxRingVol = mAudioManager.getStreamMaxVolume(STREAM_RING); 2053 if (currentRingVol != maxRingVol) { 2054 return maxRingVol; 2055 } else { 2056 return maxRingVol - 1; 2057 } 2058 } 2059 2060 @Test testAllowedCapturePolicy()2061 public void testAllowedCapturePolicy() throws Exception { 2062 final int policy = mAudioManager.getAllowedCapturePolicy(); 2063 assertEquals("Wrong default capture policy", AudioAttributes.ALLOW_CAPTURE_BY_ALL, policy); 2064 2065 for (int setPolicy : new int[] { AudioAttributes.ALLOW_CAPTURE_BY_NONE, 2066 AudioAttributes.ALLOW_CAPTURE_BY_SYSTEM, 2067 AudioAttributes.ALLOW_CAPTURE_BY_ALL}) { 2068 mAudioManager.setAllowedCapturePolicy(setPolicy); 2069 final int getPolicy = mAudioManager.getAllowedCapturePolicy(); 2070 assertEquals("Allowed capture policy doesn't match", setPolicy, getPolicy); 2071 } 2072 } 2073 2074 @Test testIsHdmiSystemAudidoSupported()2075 public void testIsHdmiSystemAudidoSupported() { 2076 // just make sure the call works 2077 boolean isSupported = mAudioManager.isHdmiSystemAudioSupported(); 2078 Log.d(TAG, "isHdmiSystemAudioSupported() = " + isSupported); 2079 } 2080 2081 @Test testIsBluetoothScoAvailableOffCall()2082 public void testIsBluetoothScoAvailableOffCall() { 2083 // just make sure the call works 2084 boolean isSupported = mAudioManager.isBluetoothScoAvailableOffCall(); 2085 Log.d(TAG, "isBluetoothScoAvailableOffCall() = " + isSupported); 2086 } 2087 2088 @Test testStartStopBluetoothSco()2089 public void testStartStopBluetoothSco() { 2090 mAudioManager.startBluetoothSco(); 2091 mAudioManager.stopBluetoothSco(); 2092 } 2093 2094 @Test testStartStopBluetoothScoVirtualCall()2095 public void testStartStopBluetoothScoVirtualCall() { 2096 mAudioManager.startBluetoothScoVirtualCall(); 2097 mAudioManager.stopBluetoothSco(); 2098 } 2099 2100 @Test testGetAdditionalOutputDeviceDelay()2101 public void testGetAdditionalOutputDeviceDelay() { 2102 AudioDeviceInfo[] devices = mAudioManager.getDevices(AudioManager.GET_DEVICES_ALL); 2103 for (AudioDeviceInfo device : devices) { 2104 long delay = mAudioManager.getAdditionalOutputDeviceDelay(device); 2105 assertTrue("getAdditionalOutputDeviceDelay() = " + delay +" (should be >= 0)", 2106 delay >= 0); 2107 delay = mAudioManager.getMaxAdditionalOutputDeviceDelay(device); 2108 assertTrue("getMaxAdditionalOutputDeviceDelay() = " + delay +" (should be >= 0)", 2109 delay >= 0); 2110 } 2111 } 2112 2113 static class MyPrevDevForStrategyListener implements 2114 AudioManager.OnPreferredDevicesForStrategyChangedListener { 2115 @Override onPreferredDevicesForStrategyChanged(AudioProductStrategy strategy, List<AudioDeviceAttributes> devices)2116 public void onPreferredDevicesForStrategyChanged(AudioProductStrategy strategy, 2117 List<AudioDeviceAttributes> devices) { 2118 fail("onPreferredDevicesForStrategyChanged must not be called"); 2119 } 2120 } 2121 2122 @Test testPreferredDevicesForStrategy()2123 public void testPreferredDevicesForStrategy() { 2124 // setPreferredDeviceForStrategy 2125 AudioDeviceInfo[] devices = mAudioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS); 2126 if (devices.length <= 0) { 2127 Log.i(TAG, "Skip testPreferredDevicesForStrategy as there is no output device"); 2128 return; 2129 } 2130 final AudioDeviceAttributes ada = new AudioDeviceAttributes(devices[0]); 2131 2132 final AudioAttributes mediaAttr = new AudioAttributes.Builder().setUsage( 2133 AudioAttributes.USAGE_MEDIA).build(); 2134 final List<AudioProductStrategy> strategies = 2135 AudioProductStrategy.getAudioProductStrategies(); 2136 AudioProductStrategy strategyForMedia = null; 2137 for (AudioProductStrategy strategy : strategies) { 2138 if (strategy.supportsAudioAttributes(mediaAttr)) { 2139 strategyForMedia = strategy; 2140 break; 2141 } 2142 } 2143 if (strategyForMedia == null) { 2144 Log.i(TAG, "Skip testPreferredDevicesForStrategy as there is no strategy for media"); 2145 return; 2146 } 2147 Log.i(TAG, "Found strategy " + strategyForMedia.getName() + " for media"); 2148 try { 2149 mAudioManager.setPreferredDeviceForStrategy(strategyForMedia, ada); 2150 fail("setPreferredDeviceForStrategy must fail due to no permission"); 2151 } catch (SecurityException e) { 2152 } 2153 try { 2154 mAudioManager.getPreferredDeviceForStrategy(strategyForMedia); 2155 fail("getPreferredDeviceForStrategy must fail due to no permission"); 2156 } catch (SecurityException e) { 2157 } 2158 final List<AudioDeviceAttributes> adas = new ArrayList<>(); 2159 adas.add(ada); 2160 try { 2161 mAudioManager.setPreferredDevicesForStrategy(strategyForMedia, adas); 2162 fail("setPreferredDevicesForStrategy must fail due to no permission"); 2163 } catch (SecurityException e) { 2164 } 2165 try { 2166 mAudioManager.getPreferredDevicesForStrategy(strategyForMedia); 2167 fail("getPreferredDevicesForStrategy must fail due to no permission"); 2168 } catch (SecurityException e) { 2169 } 2170 MyPrevDevForStrategyListener listener = new MyPrevDevForStrategyListener(); 2171 try { 2172 mAudioManager.addOnPreferredDevicesForStrategyChangedListener( 2173 Executors.newSingleThreadExecutor(), listener); 2174 fail("addOnPreferredDevicesForStrategyChangedListener must fail due to no permission"); 2175 } catch (SecurityException e) { 2176 } 2177 try { 2178 // removeOnPreferredDevicesForStrategyChangedListener should throw on non-registered 2179 // listener. 2180 mAudioManager.removeOnPreferredDevicesForStrategyChangedListener(listener); 2181 fail("removeOnPreferredDevicesForStrategyChangedListener must fail on bad listener"); 2182 } catch (IllegalArgumentException e) { 2183 } 2184 } 2185 2186 static class MyPrevDevicesForCapturePresetChangedListener implements 2187 AudioManager.OnPreferredDevicesForCapturePresetChangedListener { 2188 @Override onPreferredDevicesForCapturePresetChanged( int capturePreset, List<AudioDeviceAttributes> devices)2189 public void onPreferredDevicesForCapturePresetChanged( 2190 int capturePreset, List<AudioDeviceAttributes> devices) { 2191 fail("onPreferredDevicesForCapturePresetChanged must not be called"); 2192 } 2193 } 2194 2195 @Test testPreferredDeviceForCapturePreset()2196 public void testPreferredDeviceForCapturePreset() { 2197 AudioDeviceInfo[] devices = mAudioManager.getDevices(AudioManager.GET_DEVICES_INPUTS); 2198 if (devices.length <= 0) { 2199 Log.i(TAG, "Skip testPreferredDevicesForStrategy as there is no input device"); 2200 return; 2201 } 2202 final AudioDeviceAttributes ada = new AudioDeviceAttributes(devices[0]); 2203 2204 try { 2205 mAudioManager.setPreferredDeviceForCapturePreset(MediaRecorder.AudioSource.MIC, ada); 2206 fail("setPreferredDeviceForCapturePreset must fail due to no permission"); 2207 } catch (SecurityException e) { 2208 } 2209 try { 2210 mAudioManager.getPreferredDevicesForCapturePreset(MediaRecorder.AudioSource.MIC); 2211 fail("getPreferredDevicesForCapturePreset must fail due to no permission"); 2212 } catch (SecurityException e) { 2213 } 2214 try { 2215 mAudioManager.clearPreferredDevicesForCapturePreset(MediaRecorder.AudioSource.MIC); 2216 fail("clearPreferredDevicesForCapturePreset must fail due to no permission"); 2217 } catch (SecurityException e) { 2218 } 2219 MyPrevDevicesForCapturePresetChangedListener listener = 2220 new MyPrevDevicesForCapturePresetChangedListener(); 2221 try { 2222 mAudioManager.addOnPreferredDevicesForCapturePresetChangedListener( 2223 Executors.newSingleThreadExecutor(), listener); 2224 fail("addOnPreferredDevicesForCapturePresetChangedListener must fail" 2225 + "due to no permission"); 2226 } catch (SecurityException e) { 2227 } 2228 // There is not listener added at server side. Nothing to remove. 2229 mAudioManager.removeOnPreferredDevicesForCapturePresetChangedListener(listener); 2230 } 2231 2232 @Test testGetDevices()2233 public void testGetDevices() { 2234 AudioDeviceInfo[] devices = mAudioManager.getDevices(AudioManager.GET_DEVICES_ALL); 2235 for (AudioDeviceInfo device : devices) { 2236 Set<Integer> formats = IntStream.of(device.getEncodings()).boxed() 2237 .collect(Collectors.toSet()); 2238 Set<Integer> channelMasks = IntStream.of(device.getChannelMasks()).boxed() 2239 .collect(Collectors.toSet()); 2240 Set<Integer> channelIndexMasks = IntStream.of(device.getChannelIndexMasks()).boxed() 2241 .collect(Collectors.toSet()); 2242 Set<Integer> sampleRates = IntStream.of(device.getSampleRates()).boxed() 2243 .collect(Collectors.toSet()); 2244 HashSet<Integer> formatsFromProfile = new HashSet<>(); 2245 HashSet<Integer> channelMasksFromProfile = new HashSet<>(); 2246 HashSet<Integer> channelIndexMasksFromProfile = new HashSet<>(); 2247 HashSet<Integer> sampleRatesFromProfile = new HashSet<>(); 2248 for (AudioProfile profile : device.getAudioProfiles()) { 2249 formatsFromProfile.add(profile.getFormat()); 2250 channelMasksFromProfile.addAll(Arrays.stream(profile.getChannelMasks()).boxed() 2251 .collect(Collectors.toList())); 2252 channelIndexMasksFromProfile.addAll(Arrays.stream(profile.getChannelIndexMasks()) 2253 .boxed().collect(Collectors.toList())); 2254 sampleRatesFromProfile.addAll(Arrays.stream(profile.getSampleRates()).boxed() 2255 .collect(Collectors.toList())); 2256 assertTrue(ALL_ENCAPSULATION_TYPES.contains(profile.getEncapsulationType())); 2257 } 2258 for (AudioDescriptor descriptor : device.getAudioDescriptors()) { 2259 assertNotEquals(AudioDescriptor.STANDARD_NONE, descriptor.getStandard()); 2260 assertNotNull(descriptor.getDescriptor()); 2261 assertTrue( 2262 ALL_KNOWN_ENCAPSULATION_TYPES.contains(descriptor.getEncapsulationType())); 2263 } 2264 assertEquals(formats, formatsFromProfile); 2265 assertEquals(channelMasks, channelMasksFromProfile); 2266 assertEquals(channelIndexMasks, channelIndexMasksFromProfile); 2267 assertEquals(sampleRates, sampleRatesFromProfile); 2268 } 2269 } 2270 2271 @Test 2272 @RequiresFlagsEnabled(value = Flags.FLAG_SUPPORTED_DEVICE_TYPES_API) testGetSupportedDeviceTypes()2273 public void testGetSupportedDeviceTypes() { 2274 Set<Integer> deviceTypesOutputs = 2275 mAudioManager.getSupportedDeviceTypes(AudioManager.GET_DEVICES_OUTPUTS); 2276 assertNotEquals(deviceTypesOutputs, null); 2277 2278 if (AudioTestUtil.hasAudioOutput(mContext)) { 2279 assertNotEquals(deviceTypesOutputs.size(), 0); 2280 } else { 2281 assertEquals(deviceTypesOutputs.size(), 0); 2282 } 2283 2284 Set<Integer> deviceTypesInputs = 2285 mAudioManager.getSupportedDeviceTypes(AudioManager.GET_DEVICES_INPUTS); 2286 assertNotEquals(deviceTypesInputs, null); 2287 2288 if (AudioTestUtil.hasAudioInput(mContext)) { 2289 assertNotEquals(deviceTypesInputs.size(), 0); 2290 } else { 2291 // We can't really check this. 2292 // We are not sure of the equivalence of has "microphone" and "never support audio 2293 // inputs". For instance an android device could support input devices like HDMI IN 2294 // but not have a microphone. 2295 // assertEquals(deviceTypesInputs.size(), 0); 2296 } 2297 } 2298 2299 @Test testGetDirectPlaybackSupport()2300 public void testGetDirectPlaybackSupport() { 2301 assertEquals(AudioManager.DIRECT_PLAYBACK_NOT_SUPPORTED, 2302 AudioManager.getDirectPlaybackSupport( 2303 new AudioFormat.Builder().build(), 2304 new AudioAttributes.Builder().build())); 2305 AudioDeviceInfo[] devices = mAudioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS); 2306 AudioAttributes attr = new AudioAttributes.Builder() 2307 .setUsage(AudioAttributes.USAGE_MEDIA) 2308 .setLegacyStreamType(STREAM_MUSIC).build(); 2309 for (AudioDeviceInfo device : devices) { 2310 for (int encoding : device.getEncodings()) { 2311 for (int channelMask : device.getChannelMasks()) { 2312 for (int sampleRate : device.getSampleRates()) { 2313 AudioFormat format = new AudioFormat.Builder() 2314 .setEncoding(encoding) 2315 .setChannelMask(channelMask) 2316 .setSampleRate(sampleRate).build(); 2317 final int directPlaybackSupport = 2318 AudioManager.getDirectPlaybackSupport(format, attr); 2319 assertEquals( 2320 AudioTrack.isDirectPlaybackSupported(format, attr), 2321 directPlaybackSupport 2322 != AudioManager.DIRECT_PLAYBACK_NOT_SUPPORTED); 2323 if (directPlaybackSupport == AudioManager.DIRECT_PLAYBACK_NOT_SUPPORTED) { 2324 assertEquals( 2325 DIRECT_OFFLOAD_MAP.getOrDefault( 2326 AudioManager.getPlaybackOffloadSupport(format, attr), 2327 INVALID_DIRECT_PLAYBACK_MODE).intValue(), 2328 directPlaybackSupport); 2329 } else if ((directPlaybackSupport 2330 & AudioManager.DIRECT_PLAYBACK_OFFLOAD_SUPPORTED) 2331 != AudioManager.DIRECT_PLAYBACK_NOT_SUPPORTED) { 2332 // AudioManager.getPlaybackOffloadSupport can only query offload 2333 // support but not other direct support like passthrough. 2334 assertNotEquals( 2335 AudioManager.DIRECT_PLAYBACK_NOT_SUPPORTED, 2336 DIRECT_OFFLOAD_MAP.getOrDefault( 2337 AudioManager.getPlaybackOffloadSupport(format, attr), 2338 AudioManager.DIRECT_PLAYBACK_NOT_SUPPORTED) 2339 & directPlaybackSupport); 2340 } 2341 } 2342 } 2343 } 2344 } 2345 } 2346 2347 @AppModeFull(reason = "Instant apps cannot hold permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED") 2348 @Test testIndependentStreamTypes()2349 public void testIndependentStreamTypes() throws Exception { 2350 Log.i(TAG, "starting testIndependentStreamTypes"); 2351 getInstrumentation().getUiAutomation() 2352 .adoptShellPermissionIdentity(Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED); 2353 try { 2354 final List<Integer> independentStreamTypes = mAudioManager.getIndependentStreamTypes(); 2355 assertNotNull("Null list of independent stream types", independentStreamTypes); 2356 final boolean usesGroups = mAudioManager.isVolumeControlUsingVolumeGroups(); 2357 Log.i(TAG, "testIndependentStreamTypes: usesGroups:" + usesGroups 2358 + " independentTypes" + independentStreamTypes); 2359 if (usesGroups) { 2360 assertTrue("Empty list of independent stream types with volume groups", 2361 independentStreamTypes.size() > 0); 2362 return; 2363 } 2364 assertTrue("Unexpected number of independent stream types " 2365 + independentStreamTypes.size(), independentStreamTypes.size() > 0); 2366 // verify independent streams are not aliased 2367 for (int indepStream : independentStreamTypes) { 2368 final int alias = mAudioManager.getStreamTypeAlias(indepStream); 2369 assertEquals("Independent stream " + indepStream + " has alias " + alias, 2370 indepStream, alias); 2371 } 2372 // verify aliased streams are not independent, and non-aliased streams are 2373 for (int stream : PUBLIC_STREAM_TYPES) { 2374 final int alias = mAudioManager.getStreamTypeAlias(stream); 2375 if (alias != stream) { 2376 assertFalse("Stream" + stream + " aliased to " + alias 2377 + " but marked independent", independentStreamTypes.contains(stream)); 2378 } else { 2379 // independent stream 2380 assertTrue("Stream " + stream 2381 + " has no alias but is not marked as independent", 2382 independentStreamTypes.contains(stream)); 2383 } 2384 } 2385 } finally { 2386 getInstrumentation().getUiAutomation().dropShellPermissionIdentity(); 2387 } 2388 } 2389 2390 @AppModeFull(reason = "Instant apps cannot hold permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED") 2391 @Test testStreamTypeAliasChange()2392 public void testStreamTypeAliasChange() throws Exception { 2393 if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) { 2394 Log.i(TAG, "skipping testStreamTypeAliasChange, not a phone"); 2395 return; 2396 } 2397 Log.i(TAG, "starting testStreamTypeAliasChange"); 2398 getInstrumentation().getUiAutomation() 2399 .adoptShellPermissionIdentity(Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED); 2400 2401 // get initial state 2402 final int notifAliasAtStart = mAudioManager.getStreamTypeAlias(STREAM_NOTIFICATION); 2403 if (notifAliasAtStart != STREAM_NOTIFICATION && notifAliasAtStart != STREAM_RING) { 2404 // skipping test because it can't take advantage of the test API to modify 2405 // the notification alias 2406 Log.i(TAG, "skipping testStreamTypeAliasChange: NOTIFICATION aliased to stream " 2407 + notifAliasAtStart); 2408 return; 2409 } 2410 boolean notifAliasedToRingAtStart = (notifAliasAtStart == STREAM_RING); 2411 final MyBlockingRunnableListener streamAliasCb = new MyBlockingRunnableListener(); 2412 Runnable onStreamAliasChanged = () -> streamAliasCb.onSomeEventThatsExpected(); 2413 try { 2414 if (!notifAliasedToRingAtStart) { 2415 // if notif and ring are not aliased, they should each be independent streams 2416 final List<Integer> indies = mAudioManager.getIndependentStreamTypes(); 2417 assertTrue("NOTIFICATION not in independent streams " + indies, 2418 indies.contains(STREAM_NOTIFICATION)); 2419 assertTrue("RING not in independent streams " + indies, 2420 indies.contains(STREAM_RING)); 2421 } 2422 mAudioManager.addOnStreamAliasingChangedListener( 2423 Executors.newSingleThreadExecutor(), 2424 onStreamAliasChanged); 2425 mAudioManager.setNotifAliasRingForTest(!notifAliasedToRingAtStart); 2426 final String aliasing = notifAliasedToRingAtStart ? "unaliasing" : "aliasing"; 2427 assertTrue(aliasing + " RING and NOTIFICATION didn't trigger callback", 2428 streamAliasCb.waitForExpectedEvent(TIME_TO_WAIT_CALLBACK_MS)); 2429 final int expectedNotifAlias = notifAliasedToRingAtStart ? STREAM_NOTIFICATION 2430 : STREAM_RING; 2431 assertEquals("After " + aliasing + " alias incorrect", 2432 expectedNotifAlias, mAudioManager.getStreamTypeAlias(STREAM_NOTIFICATION)); 2433 if (notifAliasedToRingAtStart) { 2434 // if notif and ring were aliased, they should now be independent streams 2435 final List<Integer> indies = mAudioManager.getIndependentStreamTypes(); 2436 assertTrue("After alias change, NOTIFICATION not in independent streams " 2437 + indies, 2438 indies.contains(STREAM_NOTIFICATION)); 2439 assertTrue("After alias change, RING not in independent streams " + indies, 2440 indies.contains(STREAM_RING)); 2441 } 2442 2443 } finally { 2444 mAudioManager.setNotifAliasRingForTest(notifAliasedToRingAtStart); 2445 mAudioManager.removeOnStreamAliasingChangedListener(onStreamAliasChanged); 2446 getInstrumentation().getUiAutomation().dropShellPermissionIdentity(); 2447 } 2448 } 2449 2450 @Test testAssistantUidRouting()2451 public void testAssistantUidRouting() { 2452 try { 2453 mAudioManager.addAssistantServicesUids(new int[0]); 2454 fail("addAssistantServicesUids must fail due to no permission"); 2455 } catch (SecurityException e) { 2456 } 2457 2458 try { 2459 mAudioManager.removeAssistantServicesUids(new int[0]); 2460 fail("removeAssistantServicesUids must fail due to no permission"); 2461 } catch (SecurityException e) { 2462 } 2463 2464 try { 2465 int[] uids = mAudioManager.getAssistantServicesUids(); 2466 fail("getAssistantServicesUids must fail due to no permission"); 2467 } catch (SecurityException e) { 2468 } 2469 2470 try { 2471 mAudioManager.setActiveAssistantServiceUids(new int[0]); 2472 fail("setActiveAssistantServiceUids must fail due to no permission"); 2473 } catch (SecurityException e) { 2474 } 2475 2476 try { 2477 int[] activeUids = mAudioManager.getActiveAssistantServicesUids(); 2478 fail("getActiveAssistantServicesUids must fail due to no permission"); 2479 } catch (SecurityException e) { 2480 } 2481 } 2482 2483 @AppModeFull(reason = "Instant apps cannot hold android.permission.MODIFY_AUDIO_ROUTING") 2484 @Test testBluetoothVariableLatency()2485 public void testBluetoothVariableLatency() throws Exception { 2486 assertThrows(SecurityException.class, 2487 () -> mAudioManager.supportsBluetoothVariableLatency()); 2488 assertThrows(SecurityException.class, 2489 () -> mAudioManager.setBluetoothVariableLatencyEnabled(false)); 2490 assertThrows(SecurityException.class, 2491 () -> mAudioManager.setBluetoothVariableLatencyEnabled(true)); 2492 assertThrows(SecurityException.class, 2493 () -> mAudioManager.isBluetoothVariableLatencyEnabled()); 2494 2495 getInstrumentation().getUiAutomation() 2496 .adoptShellPermissionIdentity(Manifest.permission.MODIFY_AUDIO_ROUTING); 2497 if (mAudioManager.supportsBluetoothVariableLatency()) { 2498 boolean savedEnabled = mAudioManager.isBluetoothVariableLatencyEnabled(); 2499 mAudioManager.setBluetoothVariableLatencyEnabled(false); 2500 assertFalse(mAudioManager.isBluetoothVariableLatencyEnabled()); 2501 mAudioManager.setBluetoothVariableLatencyEnabled(true); 2502 assertTrue(mAudioManager.isBluetoothVariableLatencyEnabled()); 2503 mAudioManager.setBluetoothVariableLatencyEnabled(savedEnabled); 2504 } 2505 getInstrumentation().getUiAutomation().dropShellPermissionIdentity(); 2506 } 2507 2508 @Test testGetHalVersion()2509 public void testGetHalVersion() { 2510 AudioHalVersionInfo halVersion = AudioManager.getHalVersion(); 2511 assertNotEquals(null, halVersion); 2512 assertTrue( 2513 AudioHalVersionInfo.AUDIO_HAL_TYPE_AIDL == halVersion.getHalType() 2514 || AudioHalVersionInfo.AUDIO_HAL_TYPE_HIDL == halVersion.getHalType()); 2515 assertTrue(halVersion.getMajorVersion() > 0); 2516 assertTrue(halVersion.getMinorVersion() >= 0); 2517 } 2518 2519 @Test testPreferredMixerAttributes()2520 public void testPreferredMixerAttributes() throws Exception { 2521 final AudioAttributes attr = new AudioAttributes.Builder() 2522 .setUsage(AudioAttributes.USAGE_MEDIA).build(); 2523 final AudioMixerAttributes defaultMixerAttributes = new AudioMixerAttributes.Builder( 2524 new AudioFormat.Builder() 2525 .setEncoding(AudioFormat.ENCODING_PCM_16BIT) 2526 .setChannelMask(AudioFormat.CHANNEL_OUT_STEREO) 2527 .setSampleRate(48000) 2528 .build()) 2529 .setMixerBehavior(AudioMixerAttributes.MIXER_BEHAVIOR_DEFAULT) 2530 .build(); 2531 2532 for (AudioDeviceInfo device : mAudioManager.getDevices(AudioManager.GET_DEVICES_ALL)) { 2533 List<AudioMixerAttributes> supportedMixerAttributes = 2534 mAudioManager.getSupportedMixerAttributes(device); 2535 if (supportedMixerAttributes.isEmpty()) { 2536 // Setting preferred mixer attributes is not supported 2537 assertFalse(mAudioManager.setPreferredMixerAttributes( 2538 attr, device, defaultMixerAttributes)); 2539 } else { 2540 for (AudioMixerAttributes mixerAttr : supportedMixerAttributes) { 2541 ListenableFuture<Void> setMixerFuture = getMixerAttrChangedFuture(attr, 2542 device.getId()); 2543 assertNotNull(mixerAttr.getFormat()); 2544 assertTrue(ALL_MIXER_BEHAVIORS.contains(mixerAttr.getMixerBehavior())); 2545 assertTrue(mAudioManager.setPreferredMixerAttributes(attr, device, mixerAttr)); 2546 waitForMixerAttrChanged(setMixerFuture); 2547 ListenableFuture<Void> clearMixerFuture = getMixerAttrChangedFuture(attr, 2548 device.getId()); 2549 final AudioMixerAttributes mixerAttrFromQuery = 2550 mAudioManager.getPreferredMixerAttributes(attr, device); 2551 assertEquals(mixerAttr, mixerAttrFromQuery); 2552 assertTrue(mAudioManager.clearPreferredMixerAttributes(attr, device)); 2553 waitForMixerAttrChanged(clearMixerFuture); 2554 assertNull(mAudioManager.getPreferredMixerAttributes(attr, device)); 2555 } 2556 } 2557 } 2558 } 2559 2560 @Test testVolumeGroupHashCode()2561 public void testVolumeGroupHashCode() throws Exception { 2562 getInstrumentation().getUiAutomation().adoptShellPermissionIdentity( 2563 Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED); 2564 List<AudioVolumeGroup> audioVolumeGroups = mAudioManager.getAudioVolumeGroups(); 2565 getInstrumentation().getUiAutomation().dropShellPermissionIdentity(); 2566 2567 List<AudioVolumeGroup> copyVolumeGroups = List.copyOf(audioVolumeGroups); 2568 for (AudioVolumeGroup avg : audioVolumeGroups) { 2569 final AudioVolumeGroup copiedGroup = copyVolumeGroups.stream().filter( 2570 group -> group.getId() == avg.getId()).findFirst().get(); 2571 assertTrue(avg.equals(copiedGroup)); 2572 assertEquals("hashCode doesn't return the same value twice for id " 2573 + avg.getId(), avg.hashCode(), avg.hashCode()); 2574 assertEquals("hashCode on the copied group doesn't return the same value for id " 2575 + avg.getId(), avg.hashCode(), copiedGroup.hashCode()); 2576 } 2577 } 2578 2579 @Test testAdjustVolumeGroupVolume()2580 public void testAdjustVolumeGroupVolume() { 2581 getInstrumentation().getUiAutomation().adoptShellPermissionIdentity( 2582 Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED, 2583 Manifest.permission.MODIFY_AUDIO_ROUTING, 2584 Manifest.permission.QUERY_AUDIO_STATE, 2585 Manifest.permission.MODIFY_PHONE_STATE); 2586 2587 List<AudioVolumeGroup> audioVolumeGroups = mAudioManager.getAudioVolumeGroups(); 2588 assertTrue(audioVolumeGroups.size() > 0); 2589 2590 final AudioAttributes callAa = new AudioAttributes.Builder() 2591 .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION) 2592 .build(); 2593 int voiceCallVolumeGroup = mAudioManager.getVolumeGroupIdForAttributes(callAa); 2594 2595 assertNotEquals(voiceCallVolumeGroup, AudioVolumeGroup.DEFAULT_VOLUME_GROUP); 2596 2597 AudioVolumeGroupCallbackHelper vgCbReceiver = new AudioVolumeGroupCallbackHelper(); 2598 mAudioManager.registerVolumeGroupCallback(mContext.getMainExecutor(), vgCbReceiver); 2599 2600 try { 2601 // Validate Audio Volume Groups callback reception 2602 for (final AudioVolumeGroup audioVolumeGroup : audioVolumeGroups) { 2603 int volumeGroupId = audioVolumeGroup.getId(); 2604 int[] avgStreamTypes = audioVolumeGroup.getLegacyStreamTypes(); 2605 if (avgStreamTypes.length != 0) { 2606 // filters out bijective as API is dispatched to stream. 2607 // Following compatibility test will ensure API are dispatched 2608 continue; 2609 } 2610 int indexMax = mAudioManager.getVolumeGroupMaxVolumeIndex(volumeGroupId); 2611 int indexMin = mAudioManager.getVolumeGroupMinVolumeIndex(volumeGroupId); 2612 boolean isMutable = (indexMin == 0) || (volumeGroupId == voiceCallVolumeGroup); 2613 2614 // Set the receiver to filter only the current group callback 2615 int index = resetVolumeIndex(indexMin, indexMax); 2616 vgCbReceiver.setExpectedVolumeGroup(volumeGroupId); 2617 mAudioManager.setVolumeGroupVolumeIndex(volumeGroupId, index, 0/*flags*/); 2618 assertTrue(vgCbReceiver.waitForExpectedVolumeGroupChanged( 2619 AudioVolumeGroupCallbackHelper.ASYNC_TIMEOUT_MS)); 2620 int readIndex = mAudioManager.getVolumeGroupVolumeIndex(volumeGroupId); 2621 assertEquals("Failed to set volume for group id " 2622 + volumeGroupId, readIndex, index); 2623 2624 while (index < indexMax) { 2625 vgCbReceiver.setExpectedVolumeGroup(volumeGroupId); 2626 mAudioManager.adjustVolumeGroupVolume( 2627 volumeGroupId, AudioManager.ADJUST_RAISE, 0/*flags*/); 2628 assertTrue(vgCbReceiver.waitForExpectedVolumeGroupChanged( 2629 AudioVolumeGroupCallbackHelper.ASYNC_TIMEOUT_MS)); 2630 readIndex = mAudioManager.getVolumeGroupVolumeIndex(volumeGroupId); 2631 index += 1; 2632 assertEquals(readIndex, index); 2633 } 2634 // Max reached 2635 vgCbReceiver.setExpectedVolumeGroup(volumeGroupId); 2636 mAudioManager.adjustVolumeGroupVolume( 2637 volumeGroupId, AudioManager.ADJUST_RAISE, 0/*flags*/); 2638 assertTrue("Cb expected for group " 2639 + volumeGroupId, vgCbReceiver.waitForExpectedVolumeGroupChanged( 2640 AudioVolumeGroupCallbackHelper.ASYNC_TIMEOUT_MS)); 2641 readIndex = mAudioManager.getVolumeGroupVolumeIndex(volumeGroupId); 2642 assertEquals(readIndex, indexMax); 2643 2644 while (index > indexMin) { 2645 vgCbReceiver.setExpectedVolumeGroup(volumeGroupId); 2646 mAudioManager.adjustVolumeGroupVolume( 2647 volumeGroupId, AudioManager.ADJUST_LOWER, 0/*flags*/); 2648 assertTrue(vgCbReceiver.waitForExpectedVolumeGroupChanged( 2649 AudioVolumeGroupCallbackHelper.ASYNC_TIMEOUT_MS)); 2650 index -= 1; 2651 readIndex = mAudioManager.getVolumeGroupVolumeIndex(volumeGroupId); 2652 assertEquals("Failed to decrease volume for group id " 2653 + volumeGroupId, readIndex, index); 2654 } 2655 // Min reached 2656 vgCbReceiver.setExpectedVolumeGroup(volumeGroupId); 2657 mAudioManager.adjustVolumeGroupVolume( 2658 volumeGroupId, AudioManager.ADJUST_LOWER, 0/*flags*/); 2659 assertTrue("Cb expected for group " 2660 + volumeGroupId, vgCbReceiver.waitForExpectedVolumeGroupChanged( 2661 AudioVolumeGroupCallbackHelper.ASYNC_TIMEOUT_MS)); 2662 readIndex = mAudioManager.getVolumeGroupVolumeIndex(volumeGroupId); 2663 assertEquals("Failed to decrease volume for group id " 2664 + volumeGroupId, readIndex, indexMin); 2665 2666 // Mute/Unmute 2667 if (isMutable) { 2668 int lastAudibleIndex; 2669 index = resetVolumeIndex(indexMin, indexMax); 2670 vgCbReceiver.setExpectedVolumeGroup(volumeGroupId); 2671 mAudioManager.setVolumeGroupVolumeIndex(volumeGroupId, index, 0/*flags*/); 2672 assertTrue(vgCbReceiver.waitForExpectedVolumeGroupChanged( 2673 AudioVolumeGroupCallbackHelper.ASYNC_TIMEOUT_MS)); 2674 2675 readIndex = mAudioManager.getVolumeGroupVolumeIndex(volumeGroupId); 2676 assertEquals("Failed to set volume for group id " 2677 + volumeGroupId, readIndex, index); 2678 2679 lastAudibleIndex = 2680 mAudioManager.getLastAudibleVolumeForVolumeGroup(volumeGroupId); 2681 assertEquals(lastAudibleIndex, index); 2682 assertFalse(mAudioManager.isVolumeGroupMuted(volumeGroupId)); 2683 2684 // Mute 2685 vgCbReceiver.setExpectedVolumeGroup(volumeGroupId); 2686 mAudioManager.adjustVolumeGroupVolume( 2687 volumeGroupId, AudioManager.ADJUST_MUTE, 0/*flags*/); 2688 assertTrue(vgCbReceiver.waitForExpectedVolumeGroupChanged( 2689 AudioVolumeGroupCallbackHelper.ASYNC_TIMEOUT_MS)); 2690 readIndex = mAudioManager.getVolumeGroupVolumeIndex(volumeGroupId); 2691 assertEquals("Failed to mute volume for group id " 2692 + volumeGroupId, readIndex, indexMin); 2693 assertEquals(lastAudibleIndex, 2694 mAudioManager.getLastAudibleVolumeForVolumeGroup(volumeGroupId)); 2695 assertTrue(mAudioManager.isVolumeGroupMuted(volumeGroupId)); 2696 2697 // Unmute 2698 vgCbReceiver.setExpectedVolumeGroup(volumeGroupId); 2699 mAudioManager.adjustVolumeGroupVolume( 2700 volumeGroupId, AudioManager.ADJUST_UNMUTE, 0/*flags*/); 2701 assertTrue(vgCbReceiver.waitForExpectedVolumeGroupChanged( 2702 AudioVolumeGroupCallbackHelper.ASYNC_TIMEOUT_MS)); 2703 readIndex = mAudioManager.getVolumeGroupVolumeIndex(volumeGroupId); 2704 assertEquals("Failed to unmute volume for group id " 2705 + volumeGroupId, readIndex, lastAudibleIndex); 2706 assertEquals(lastAudibleIndex, 2707 mAudioManager.getLastAudibleVolumeForVolumeGroup(volumeGroupId)); 2708 assertFalse(mAudioManager.isVolumeGroupMuted(volumeGroupId)); 2709 2710 // Toggle Mute (from unmuted) 2711 vgCbReceiver.setExpectedVolumeGroup(volumeGroupId); 2712 mAudioManager.adjustVolumeGroupVolume( 2713 volumeGroupId, AudioManager.ADJUST_TOGGLE_MUTE, 0/*flags*/); 2714 assertTrue(vgCbReceiver.waitForExpectedVolumeGroupChanged( 2715 AudioVolumeGroupCallbackHelper.ASYNC_TIMEOUT_MS)); 2716 readIndex = mAudioManager.getVolumeGroupVolumeIndex(volumeGroupId); 2717 assertEquals("Failed to mute volume for group id " 2718 + volumeGroupId, readIndex, indexMin); 2719 assertEquals(lastAudibleIndex, 2720 mAudioManager.getLastAudibleVolumeForVolumeGroup(volumeGroupId)); 2721 assertTrue(mAudioManager.isVolumeGroupMuted(volumeGroupId)); 2722 2723 // Toggle Mute (from muted) 2724 vgCbReceiver.setExpectedVolumeGroup(volumeGroupId); 2725 mAudioManager.adjustVolumeGroupVolume( 2726 volumeGroupId, AudioManager.ADJUST_TOGGLE_MUTE, 0/*flags*/); 2727 assertTrue(vgCbReceiver.waitForExpectedVolumeGroupChanged( 2728 AudioVolumeGroupCallbackHelper.ASYNC_TIMEOUT_MS)); 2729 readIndex = mAudioManager.getVolumeGroupVolumeIndex(volumeGroupId); 2730 assertEquals("Failed to unmute volume for group id " 2731 + volumeGroupId, readIndex, lastAudibleIndex); 2732 assertEquals(lastAudibleIndex, 2733 mAudioManager.getLastAudibleVolumeForVolumeGroup(volumeGroupId)); 2734 assertFalse(mAudioManager.isVolumeGroupMuted(volumeGroupId)); 2735 } else { 2736 int lastAudibleIndex; 2737 index = resetVolumeIndex(indexMin, indexMax); 2738 vgCbReceiver.setExpectedVolumeGroup(volumeGroupId); 2739 mAudioManager.setVolumeGroupVolumeIndex(volumeGroupId, index, 0/*flags*/); 2740 assertTrue(vgCbReceiver.waitForExpectedVolumeGroupChanged( 2741 AudioVolumeGroupCallbackHelper.ASYNC_TIMEOUT_MS)); 2742 readIndex = mAudioManager.getVolumeGroupVolumeIndex(volumeGroupId); 2743 assertEquals(readIndex, index); 2744 2745 lastAudibleIndex = 2746 mAudioManager.getLastAudibleVolumeForVolumeGroup(volumeGroupId); 2747 assertEquals(lastAudibleIndex, index); 2748 assertFalse(mAudioManager.isVolumeGroupMuted(volumeGroupId)); 2749 2750 // Mute 2751 vgCbReceiver.setExpectedVolumeGroup(volumeGroupId); 2752 mAudioManager.adjustVolumeGroupVolume( 2753 volumeGroupId, AudioManager.ADJUST_MUTE, 0/*flags*/); 2754 assertFalse(vgCbReceiver.waitForExpectedVolumeGroupChanged( 2755 AudioVolumeGroupCallbackHelper.ASYNC_TIMEOUT_MS)); 2756 readIndex = mAudioManager.getVolumeGroupVolumeIndex(volumeGroupId); 2757 assertEquals("Unexpected volume mute for group id " + volumeGroupId 2758 + " readIndex=" + readIndex, readIndex, lastAudibleIndex); 2759 assertEquals(lastAudibleIndex, 2760 mAudioManager.getLastAudibleVolumeForVolumeGroup(volumeGroupId)); 2761 assertFalse(mAudioManager.isVolumeGroupMuted(volumeGroupId)); 2762 2763 // Unmute 2764 vgCbReceiver.setExpectedVolumeGroup(volumeGroupId); 2765 mAudioManager.adjustVolumeGroupVolume( 2766 volumeGroupId, AudioManager.ADJUST_UNMUTE, 0/*flags*/); 2767 assertFalse(vgCbReceiver.waitForExpectedVolumeGroupChanged( 2768 AudioVolumeGroupCallbackHelper.ASYNC_TIMEOUT_MS)); 2769 readIndex = mAudioManager.getVolumeGroupVolumeIndex(volumeGroupId); 2770 assertEquals(readIndex, lastAudibleIndex); 2771 assertEquals(lastAudibleIndex, 2772 mAudioManager.getLastAudibleVolumeForVolumeGroup(volumeGroupId)); 2773 assertFalse(mAudioManager.isVolumeGroupMuted(volumeGroupId)); 2774 2775 // Toggle Mute (from unmuted) 2776 vgCbReceiver.setExpectedVolumeGroup(volumeGroupId); 2777 mAudioManager.adjustVolumeGroupVolume( 2778 volumeGroupId, AudioManager.ADJUST_TOGGLE_MUTE, 0/*flags*/); 2779 assertFalse(vgCbReceiver.waitForExpectedVolumeGroupChanged( 2780 AudioVolumeGroupCallbackHelper.ASYNC_TIMEOUT_MS)); 2781 readIndex = mAudioManager.getVolumeGroupVolumeIndex(volumeGroupId); 2782 assertEquals(readIndex, lastAudibleIndex); 2783 assertEquals(lastAudibleIndex, 2784 mAudioManager.getLastAudibleVolumeForVolumeGroup(volumeGroupId)); 2785 assertFalse(mAudioManager.isVolumeGroupMuted(volumeGroupId)); 2786 2787 // Toggle Mute (from muted) 2788 vgCbReceiver.setExpectedVolumeGroup(volumeGroupId); 2789 mAudioManager.adjustVolumeGroupVolume( 2790 volumeGroupId, AudioManager.ADJUST_TOGGLE_MUTE, 0/*flags*/); 2791 assertFalse(vgCbReceiver.waitForExpectedVolumeGroupChanged( 2792 AudioVolumeGroupCallbackHelper.ASYNC_TIMEOUT_MS)); 2793 readIndex = mAudioManager.getVolumeGroupVolumeIndex(volumeGroupId); 2794 assertEquals(readIndex, lastAudibleIndex); 2795 assertEquals(lastAudibleIndex, 2796 mAudioManager.getLastAudibleVolumeForVolumeGroup(volumeGroupId)); 2797 assertFalse(mAudioManager.isVolumeGroupMuted(volumeGroupId)); 2798 } 2799 } 2800 } finally { 2801 mAudioManager.unregisterVolumeGroupCallback(vgCbReceiver); 2802 getInstrumentation().getUiAutomation().dropShellPermissionIdentity(); 2803 } 2804 } 2805 waitForMixerAttrChanged(ListenableFuture<Void> future)2806 private void waitForMixerAttrChanged(ListenableFuture<Void> future) 2807 throws Exception { 2808 future.get(FUTURE_WAIT_SECS, TimeUnit.SECONDS); 2809 } 2810 getMixerAttrChangedFuture(AudioAttributes audioAttributes, int deviceId)2811 private ListenableFuture<Void> getMixerAttrChangedFuture(AudioAttributes audioAttributes, 2812 int deviceId) { 2813 final ListenableFuture<Void> future = 2814 mCancelRule.registerFuture( 2815 getFutureForListener( 2816 listener -> 2817 mAudioManager.addOnPreferredMixerAttributesChangedListener( 2818 MoreExecutors.directExecutor(), listener), 2819 mAudioManager::removeOnPreferredMixerAttributesChangedListener, 2820 (completer) -> 2821 (AudioAttributes aa, 2822 AudioDeviceInfo device, 2823 AudioMixerAttributes ma) -> { 2824 if (device.getId() == deviceId 2825 && Objects.equals(aa, audioAttributes)) { 2826 completer.set(null); 2827 } 2828 }, 2829 "Wait for mixer attr changed future")); 2830 return future; 2831 } 2832 assertCallChangesStreamVolume(Runnable r, int stream, int expectedVolume)2833 private void assertCallChangesStreamVolume(Runnable r, int stream, int expectedVolume) 2834 throws Exception { 2835 assertCallChangesStreamVolume(r, stream, expectedVolume, null); 2836 } 2837 assertCallChangesStreamVolume(Runnable r, int stream, int expectedVolume, String msg)2838 private void assertCallChangesStreamVolume(Runnable r, int stream, int expectedVolume, 2839 String msg) 2840 throws Exception { 2841 var initVol = mAudioManager.getStreamVolume(stream); 2842 assertWithMessage("Stream volume is already at desired") 2843 .that(initVol) 2844 .isNotEqualTo(expectedVolume); 2845 2846 var future = mCancelRule.registerFuture(getFutureForIntent( 2847 mContext, 2848 AudioManager.ACTION_VOLUME_CHANGED, 2849 i -> (i != null) 2850 && i.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1) 2851 == stream)); 2852 r.run(); 2853 var intent = future.get(FUTURE_WAIT_SECS, TimeUnit.SECONDS); 2854 String assertMessage = "Unexpected volume for stream " + stream + ". " 2855 + ((msg != null) ? msg : ""); 2856 // TODO prev volume from intent is not zeroed when moving out of zen 2857 /* 2858 assertWithMessage(assertMessage) 2859 .that(intent.getIntExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, -1)) 2860 .isEqualTo(initVol); 2861 */ 2862 assertWithMessage(assertMessage) 2863 .that(intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, -1)) 2864 .isEqualTo(expectedVolume); 2865 assertWithMessage(assertMessage) 2866 .that(mAudioManager.getStreamVolume(stream)) 2867 .isEqualTo(expectedVolume); 2868 } 2869 assertCallDoesNotChangeStreamVolume(Runnable r, int stream)2870 private void assertCallDoesNotChangeStreamVolume(Runnable r, int stream) throws Exception { 2871 assertCallDoesNotChangeStreamVolume(r, stream, null); 2872 } 2873 assertCallDoesNotChangeStreamVolume(Runnable r, int stream, String message)2874 private void assertCallDoesNotChangeStreamVolume(Runnable r, int stream, String message) 2875 throws Exception { 2876 // It is hard to test a negative, but we will do our best 2877 final int initVol = mAudioManager.getStreamVolume(stream); 2878 // Set the volume to a known value 2879 2880 var future = mCancelRule.registerFuture(getFutureForIntent( 2881 mContext, 2882 AudioManager.ACTION_VOLUME_CHANGED, 2883 i -> (i != null) 2884 && i.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1) 2885 == stream)); 2886 r.run(); 2887 SystemClock.sleep(PROVE_NEGATIVE_DURATION_MS); 2888 AmUtils.waitForBroadcastBarrier(); 2889 assertThat(future.isDone()) 2890 .isFalse(); 2891 2892 assertWithMessage("Call expected to not change volume. " 2893 + ((message != null) ? message : "")) 2894 .that(mAudioManager.getStreamVolume(stream)) 2895 .isEqualTo(initVol); 2896 } 2897 waitForStreamVolumeSet(int stream, int expectedVolume)2898 private void waitForStreamVolumeSet(int stream, int expectedVolume) throws Exception { 2899 final var initVol = mAudioManager.getStreamVolume(stream); 2900 // Set the volume to a known value 2901 if (initVol != expectedVolume) { 2902 var future = mCancelRule.registerFuture(getFutureForIntent( 2903 mContext, 2904 AudioManager.ACTION_VOLUME_CHANGED, 2905 i -> (i != null) 2906 && i.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1) 2907 == stream)); 2908 mAudioManager.setStreamVolume(stream, 2909 expectedVolume, 0 /* flags */); 2910 assertThat(future.get(FUTURE_WAIT_SECS, TimeUnit.SECONDS) 2911 .getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, -1)) 2912 .isEqualTo(expectedVolume); 2913 } 2914 assertWithMessage("Failed to set stream volume for " + stream + " to " + expectedVolume) 2915 .that(mAudioManager.getStreamVolume(stream)) 2916 .isEqualTo(expectedVolume); 2917 2918 } 2919 2920 pollWithBackoff(BooleanSupplier isDone, long initialMs, long backoff, long maxBackoff, long timeout)2921 private void pollWithBackoff(BooleanSupplier isDone, long initialMs, 2922 long backoff, long maxBackoff, long timeout) { 2923 final long startTime = SystemClock.uptimeMillis(); 2924 long waitMs = initialMs; 2925 while (true) { 2926 if (isDone.getAsBoolean()) { 2927 return; 2928 } 2929 long timeLeft = timeout - (SystemClock.uptimeMillis() - startTime); 2930 if (timeLeft < 0) { 2931 throw new AssertionError("Polling timeout"); 2932 } 2933 waitMs = Math.min(Math.min(waitMs + backoff, maxBackoff), timeLeft); 2934 SystemClock.sleep(waitMs); 2935 } 2936 } 2937 createMuteFuture(int stream)2938 private ListenableFuture<Intent> createMuteFuture(int stream) { 2939 return mCancelRule.registerFuture(getFutureForIntent(mContext, 2940 "android.media.STREAM_MUTE_CHANGED_ACTION", 2941 i -> (i != null) && 2942 i.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1) == stream)); 2943 } 2944 MuteStateTransition(boolean before, boolean after)2945 private static record MuteStateTransition(boolean before, boolean after) {} 2946 2947 private static interface ThrowingRunnable { run()2948 public void run() throws Exception; 2949 } 2950 assertStreamMuteStateChange(ThrowingRunnable r, Map<Integer, MuteStateTransition> streamMuteMap, String msg)2951 private void assertStreamMuteStateChange(ThrowingRunnable r, 2952 Map<Integer, MuteStateTransition> streamMuteMap, 2953 String msg) 2954 throws Exception { 2955 2956 streamMuteMap.forEach( 2957 (Integer stream, MuteStateTransition mute) 2958 -> assertWithMessage(msg + " Initial stream mute state for " + stream + 2959 "does not correspond to expected mute state") 2960 .that(mAudioManager.isStreamMute(stream)) 2961 .isEqualTo(mute.before())); 2962 2963 ListenableFuture<List<Intent>> futures = null; 2964 List<ListenableFuture<Intent>> unchangedFutures = null; 2965 2966 futures = Futures.allAsList(streamMuteMap.entrySet().stream() 2967 .filter(e -> e.getValue().before() != e.getValue().after()) 2968 .map(e -> { 2969 return Futures.transform(createMuteFuture(e.getKey()), 2970 (Intent i) -> { 2971 assertWithMessage(msg + " Stream " + e.getKey() + " failed to mute") 2972 .that(i.getBooleanExtra( 2973 "android.media.EXTRA_STREAM_VOLUME_MUTED", 2974 false)) 2975 .isEqualTo(e.getValue().after()); 2976 return i; 2977 }, MoreExecutors.directExecutor()); 2978 }) 2979 .collect(Collectors.toList())); 2980 2981 unchangedFutures = streamMuteMap.entrySet().stream() 2982 .filter(e -> e.getValue().before() == e.getValue().after()) 2983 .map(e -> createMuteFuture(e.getKey())) 2984 .collect(Collectors.toList()); 2985 2986 r.run(); 2987 2988 SystemClock.sleep(PROVE_NEGATIVE_DURATION_MS); 2989 AmUtils.waitForBroadcastBarrier(); 2990 futures.get(FUTURE_WAIT_SECS, TimeUnit.SECONDS); 2991 2992 for (var f : unchangedFutures) { 2993 if (f.isDone()) { 2994 throw new AssertionError(msg + " Unexpected unmute: " + f.get()); 2995 } 2996 } 2997 2998 streamMuteMap.forEach( 2999 (Integer stream, MuteStateTransition mute) 3000 -> assertWithMessage(msg + " Final stream mute state for " + stream 3001 + " does not correspond to expected mute state") 3002 .that(mAudioManager.isStreamMute(stream)) 3003 .isEqualTo(mute.after())); 3004 } 3005 assertMusicActive(boolean expectedIsMusicActive)3006 private void assertMusicActive(boolean expectedIsMusicActive) throws Exception { 3007 final long startPoll = SystemClock.uptimeMillis(); 3008 boolean actualIsMusicActive = mAudioManager.isMusicActive(); 3009 while (SystemClock.uptimeMillis() - startPoll < POLL_TIME_PLAY_MUSIC 3010 && expectedIsMusicActive != actualIsMusicActive) { 3011 actualIsMusicActive = mAudioManager.isMusicActive(); 3012 } 3013 assertEquals(actualIsMusicActive, actualIsMusicActive); 3014 } 3015 3016 private static final long REPEATED_CHECK_POLL_PERIOD_MS = 100; // 100ms 3017 private static final long DEFAULT_ASYNC_CALL_TIMEOUT_MS = 5 * REPEATED_CHECK_POLL_PERIOD_MS; 3018 3019 /** 3020 * Makes multiple attempts over a given timeout period to test the predicate on an AudioManager 3021 * instance. Test success is evaluated against a true predicate result. 3022 * @param am the AudioManager instance to use for the test 3023 * @param predicate the test to run either until it returns true, or until the timeout expires 3024 * @param timeoutMs the maximum time allowed for the test to pass 3025 * @param errorString the string to be displayed in case of failure 3026 * @throws Exception 3027 */ assertTrueCheckTimeout(AudioManager am, Predicate<AudioManager> predicate, long timeoutMs, String errorString)3028 private void assertTrueCheckTimeout(AudioManager am, Predicate<AudioManager> predicate, 3029 long timeoutMs, String errorString) throws Exception { 3030 long checkStart = SystemClock.uptimeMillis(); 3031 boolean result = false; 3032 while (SystemClock.uptimeMillis() - checkStart < timeoutMs) { 3033 result = predicate.test(am); 3034 if (result) { 3035 break; 3036 } 3037 Thread.sleep(REPEATED_CHECK_POLL_PERIOD_MS); 3038 } 3039 assertTrue(errorString, result); 3040 } 3041 isAutomotive()3042 private boolean isAutomotive() { 3043 PackageManager pm = mContext.getPackageManager(); 3044 return pm.hasSystemFeature(pm.FEATURE_AUTOMOTIVE); 3045 } 3046 3047 // getParameters() & setParameters() are deprecated, so don't test 3048 3049 // setAdditionalOutputDeviceDelay(), getAudioVolumeGroups(), getVolumeIndexForAttributes() 3050 // getMinVolumeIndexForAttributes(), getMaxVolumeIndexForAttributes() & 3051 // setVolumeIndexForAttributes() require privledged permission MODIFY_AUDIO_ROUTING 3052 // and thus cannot be tested here. 3053 } 3054