/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.media.audio.cts;

import static android.media.AudioManager.ADJUST_LOWER;
import static android.media.AudioManager.ADJUST_RAISE;
import static android.media.AudioManager.ADJUST_SAME;
import static android.media.AudioManager.MODE_IN_CALL;
import static android.media.AudioManager.MODE_IN_COMMUNICATION;
import static android.media.AudioManager.MODE_NORMAL;
import static android.media.AudioManager.MODE_RINGTONE;
import static android.media.AudioManager.RINGER_MODE_NORMAL;
import static android.media.AudioManager.RINGER_MODE_SILENT;
import static android.media.AudioManager.RINGER_MODE_VIBRATE;
import static android.media.AudioManager.STREAM_ACCESSIBILITY;
import static android.media.AudioManager.STREAM_ALARM;
import static android.media.AudioManager.STREAM_DTMF;
import static android.media.AudioManager.STREAM_MUSIC;
import static android.media.AudioManager.STREAM_NOTIFICATION;
import static android.media.AudioManager.STREAM_RING;
import static android.media.AudioManager.STREAM_SYSTEM;
import static android.media.AudioManager.STREAM_VOICE_CALL;
import static android.media.AudioManager.USE_DEFAULT_STREAM_TYPE;
import static android.media.AudioManager.VIBRATE_SETTING_OFF;
import static android.media.AudioManager.VIBRATE_SETTING_ON;
import static android.media.AudioManager.VIBRATE_SETTING_ONLY_SILENT;
import static android.media.AudioManager.VIBRATE_TYPE_NOTIFICATION;
import static android.media.AudioManager.VIBRATE_TYPE_RINGER;
import static android.provider.Settings.Global.APPLY_RAMPING_RINGER;
import static android.provider.Settings.System.SOUND_EFFECTS_ENABLED;

import static org.junit.Assert.assertNotEquals;

import android.Manifest;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.media.AudioAttributes;
import android.media.AudioDescriptor;
import android.media.AudioDeviceAttributes;
import android.media.AudioDeviceInfo;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioProfile;
import android.media.AudioTrack;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.media.MicrophoneInfo;
import android.media.audio.cts.R;
import android.media.audiopolicy.AudioProductStrategy;
import android.media.cts.NonMediaMainlineTest;
import android.media.cts.Utils;
import android.os.Build;
import android.os.SystemClock;
import android.os.Vibrator;
import android.platform.test.annotations.AppModeFull;
import android.provider.Settings;
import android.provider.Settings.System;
import android.test.InstrumentationTestCase;
import android.text.TextUtils;
import android.util.Log;
import android.view.SoundEffectConstants;

import androidx.test.InstrumentationRegistry;

import com.android.compatibility.common.util.ApiLevelUtil;
import com.android.compatibility.common.util.CddTest;
import com.android.compatibility.common.util.MediaUtils;
import com.android.compatibility.common.util.SettingsStateKeeperRule;
import com.android.internal.annotations.GuardedBy;

import org.junit.ClassRule;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

@NonMediaMainlineTest
public class AudioManagerTest extends InstrumentationTestCase {
    private final static String TAG = "AudioManagerTest";

    private final static long ASYNC_TIMING_TOLERANCE_MS = 50;
    private final static long POLL_TIME_VOLUME_ADJUST = 200;
    private final static long POLL_TIME_UPDATE_INTERRUPTION_FILTER = 5000;
    private final static int MP3_TO_PLAY = R.raw.testmp3; // ~ 5 second mp3
    private final static long POLL_TIME_PLAY_MUSIC = 2000;
    private final static long TIME_TO_PLAY = 2000;
    private final static String APPOPS_OP_STR = "android:write_settings";
    private final static Set<Integer> ALL_KNOWN_ENCAPSULATION_TYPES = new HashSet<>() {{
            add(AudioProfile.AUDIO_ENCAPSULATION_TYPE_IEC61937);
    }};
    private final static Set<Integer> ALL_ENCAPSULATION_TYPES = new HashSet<>() {{
            add(AudioProfile.AUDIO_ENCAPSULATION_TYPE_NONE);
            add(AudioProfile.AUDIO_ENCAPSULATION_TYPE_IEC61937);
    }};
    private final static HashSet<Integer> ALL_AUDIO_STANDARDS = new HashSet<>() {{
            add(AudioDescriptor.STANDARD_NONE);
            add(AudioDescriptor.STANDARD_EDID);
    }};
    private static final HashMap<Integer, Integer> DIRECT_OFFLOAD_MAP = new HashMap<>() {{
            put(AudioManager.PLAYBACK_OFFLOAD_NOT_SUPPORTED,
                    AudioManager.DIRECT_PLAYBACK_NOT_SUPPORTED);
            put(AudioManager.PLAYBACK_OFFLOAD_SUPPORTED,
                    AudioManager.DIRECT_PLAYBACK_OFFLOAD_SUPPORTED);
            put(AudioManager.PLAYBACK_OFFLOAD_GAPLESS_SUPPORTED,
                    AudioManager.DIRECT_PLAYBACK_OFFLOAD_GAPLESS_SUPPORTED);
        }};
    private static final int INVALID_DIRECT_PLAYBACK_MODE = -1;
    private AudioManager mAudioManager;
    private NotificationManager mNm;
    private boolean mHasVibrator;
    private boolean mUseFixedVolume;
    private boolean mIsTelevision;
    private boolean mIsSingleVolume;
    private boolean mSkipRingerTests;
    // From N onwards, ringer mode adjustments that toggle DND are not allowed unless
    // package has DND access. Many tests in this package toggle DND access in order
    // to get device out of the DND state for the test to proceed correctly.
    // But DND access is disabled completely on low ram devices,
    // so completely skip those tests here.
    // These tests are migrated to CTS verifier tests to ensure test coverage.
    private Context mContext;
    private int mOriginalRingerMode;
    private Map<Integer, Integer> mOriginalStreamVolumes = new HashMap<>();
    private NotificationManager.Policy mOriginalNotificationPolicy;
    private int mOriginalZen;
    private boolean mDoNotCheckUnmute;
    private boolean mAppsBypassingDnd;

    @ClassRule
    public static final SettingsStateKeeperRule mSurroundSoundFormatsSettingsKeeper =
            new SettingsStateKeeperRule(InstrumentationRegistry.getTargetContext(),
                    Settings.Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS);

    @ClassRule
    public static final SettingsStateKeeperRule mSurroundSoundModeSettingsKeeper =
            new SettingsStateKeeperRule(InstrumentationRegistry.getTargetContext(),
                    Settings.Global.ENCODED_SURROUND_OUTPUT);

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        mContext = getInstrumentation().getContext();
        Utils.enableAppOps(mContext.getPackageName(), APPOPS_OP_STR, getInstrumentation());
        mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
        Vibrator vibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
        mNm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
        mAppsBypassingDnd = NotificationManager.getService().areChannelsBypassingDnd();
        mHasVibrator = (vibrator != null) && vibrator.hasVibrator();
        mUseFixedVolume = mContext.getResources().getBoolean(
                Resources.getSystem().getIdentifier("config_useFixedVolume", "bool", "android"));
        PackageManager packageManager = mContext.getPackageManager();
        mIsTelevision = packageManager != null
                && (packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
                        || packageManager.hasSystemFeature(PackageManager.FEATURE_TELEVISION));
        mIsSingleVolume = mContext.getResources().getBoolean(
                Resources.getSystem().getIdentifier("config_single_volume", "bool", "android"));
        mSkipRingerTests = mUseFixedVolume || mIsTelevision || mIsSingleVolume;

        // Store the original volumes that that they can be recovered in tearDown().
        final int[] streamTypes = {
            STREAM_VOICE_CALL,
            STREAM_SYSTEM,
            STREAM_RING,
            STREAM_MUSIC,
            STREAM_ALARM,
            STREAM_NOTIFICATION,
            STREAM_DTMF,
            STREAM_ACCESSIBILITY,
        };
        mOriginalRingerMode = mAudioManager.getRingerMode();
        for (int streamType : streamTypes) {
            mOriginalStreamVolumes.put(streamType, mAudioManager.getStreamVolume(streamType));
        }

        try {
            Utils.toggleNotificationPolicyAccess(
                    mContext.getPackageName(), getInstrumentation(), true);
            mOriginalNotificationPolicy = mNm.getNotificationPolicy();
            mOriginalZen = mNm.getCurrentInterruptionFilter();
        } finally {
            setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
            Utils.toggleNotificationPolicyAccess(
                    mContext.getPackageName(), getInstrumentation(), false);
        }

        // Check original microphone mute/unmute status
        mDoNotCheckUnmute = false;
        if (mAudioManager.isMicrophoneMute()) {
            mAudioManager.setMicrophoneMute(false);
            if (mAudioManager.isMicrophoneMute()) {
                Log.w(TAG, "Mic seems muted by hardware! Please unmute and rerrun the test.");
                mDoNotCheckUnmute = true;
            }
        }
    }

    @Override
    protected void tearDown() throws Exception {
        try {
            Utils.toggleNotificationPolicyAccess(
                    mContext.getPackageName(), getInstrumentation(), true);
            mNm.setNotificationPolicy(mOriginalNotificationPolicy);
            setInterruptionFilter(mOriginalZen);

            // Recover the volume and the ringer mode that the test may have overwritten.
            for (Map.Entry<Integer, Integer> e : mOriginalStreamVolumes.entrySet()) {
                mAudioManager.setStreamVolume(e.getKey(), e.getValue(),
                                              AudioManager.FLAG_ALLOW_RINGER_MODES);
            }
            mAudioManager.setRingerMode(mOriginalRingerMode);
        } finally {
            Utils.toggleNotificationPolicyAccess(
                    mContext.getPackageName(), getInstrumentation(), false);
        }
    }

    @AppModeFull(reason = "Instant apps cannot hold android.permission.MODIFY_AUDIO_SETTINGS")
    public void testMicrophoneMute() throws Exception {
        mAudioManager.setMicrophoneMute(true);
        assertTrue(mAudioManager.isMicrophoneMute());
        mAudioManager.setMicrophoneMute(false);
        assertFalse(mAudioManager.isMicrophoneMute() && !mDoNotCheckUnmute);
    }

    @AppModeFull(reason = "Instant apps cannot hold android.permission.MODIFY_AUDIO_SETTINGS")
    public void testMicrophoneMuteIntent() throws Exception {
        if (!mDoNotCheckUnmute) {
            final MyBlockingIntentReceiver receiver = new MyBlockingIntentReceiver(
                    AudioManager.ACTION_MICROPHONE_MUTE_CHANGED);
            final boolean initialMicMute = mAudioManager.isMicrophoneMute();
            try {
                mContext.registerReceiver(receiver,
                        new IntentFilter(AudioManager.ACTION_MICROPHONE_MUTE_CHANGED));
                // change the mic mute state
                mAudioManager.setMicrophoneMute(!initialMicMute);
                // verify a change was reported
                final boolean intentFired = receiver.waitForExpectedAction(500/*ms*/);
                assertTrue("ACTION_MICROPHONE_MUTE_CHANGED wasn't fired", intentFired);
                // verify the mic mute state is expected
                final boolean newMicMute = mAudioManager.isMicrophoneMute();
                assertTrue("new mic mute state not as expected (" + !initialMicMute + ")",
                        (newMicMute == !initialMicMute));
            } finally {
                mContext.unregisterReceiver(receiver);
                mAudioManager.setMicrophoneMute(initialMicMute);
            }
        }
    }

    @AppModeFull(reason = "Instant apps cannot hold android.permission.MODIFY_AUDIO_SETTINGS")
    public void testSpeakerphoneIntent() throws Exception {
        //  Speaker Phone Not supported in Automotive
        if (isAutomotive()) {
            return;
        }
        final MyBlockingIntentReceiver receiver = new MyBlockingIntentReceiver(
                AudioManager.ACTION_SPEAKERPHONE_STATE_CHANGED);
        final boolean initialSpeakerphoneState = mAudioManager.isSpeakerphoneOn();
        try {
            mContext.registerReceiver(receiver,
                    new IntentFilter(AudioManager.ACTION_SPEAKERPHONE_STATE_CHANGED));
            // change the speakerphone state
            mAudioManager.setSpeakerphoneOn(!initialSpeakerphoneState);
            // verify a change was reported
            final boolean intentFired = receiver.waitForExpectedAction(500/*ms*/);
            assertTrue("ACTION_SPEAKERPHONE_STATE_CHANGED wasn't fired", intentFired);
            // verify the speakerphon state is expected
            final boolean newSpeakerphoneState = mAudioManager.isSpeakerphoneOn();
            assertTrue("new mic mute state not as expected ("
                    + !initialSpeakerphoneState + ")",
                    newSpeakerphoneState == !initialSpeakerphoneState);
        } finally {
            mContext.unregisterReceiver(receiver);
            mAudioManager.setSpeakerphoneOn(initialSpeakerphoneState);
        }
    }

    private static final class MyBlockingIntentReceiver extends BroadcastReceiver {
        private final SafeWaitObject mLock = new SafeWaitObject();
        // the action for the intent to check
        private final String mAction;
        @GuardedBy("mLock")
        private boolean mIntentReceived = false;

        MyBlockingIntentReceiver(String action) {
            mAction = action;
        }

        @Override
        public void onReceive(Context context, Intent intent) {
            if (!TextUtils.equals(intent.getAction(), mAction)) {
                // move along, this is not the action we're looking for
                return;
            }
            synchronized (mLock) {
                mIntentReceived = true;
                mLock.safeNotify();
            }
        }

        public boolean waitForExpectedAction(long timeOutMs) {
            synchronized (mLock) {
                try {
                    mLock.safeWait(timeOutMs);
                } catch (InterruptedException e) { }
                return mIntentReceived;
            }
        }
    }

    public void testSoundEffects() throws Exception {
        Settings.System.putInt(mContext.getContentResolver(), SOUND_EFFECTS_ENABLED, 1);

        // should hear sound after loadSoundEffects() called.
        mAudioManager.loadSoundEffects();
        Thread.sleep(TIME_TO_PLAY);
        float volume = 0.5f;  // volume should be between 0.f to 1.f (or -1).
        mAudioManager.playSoundEffect(SoundEffectConstants.CLICK);
        mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_UP);
        mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_DOWN);
        mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_LEFT);
        mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_RIGHT);

        mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_UP, volume);
        mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_DOWN, volume);
        mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_LEFT, volume);
        mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_RIGHT, volume);

        // won't hear sound after unloadSoundEffects() called();
        mAudioManager.unloadSoundEffects();
        mAudioManager.playSoundEffect(AudioManager.FX_KEY_CLICK);
        mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_UP);
        mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_DOWN);
        mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_LEFT);
        mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_RIGHT);

        mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_UP, volume);
        mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_DOWN, volume);
        mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_LEFT, volume);
        mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_RIGHT, volume);
    }

    public void testCheckingZenModeBlockDoesNotRequireNotificationPolicyAccess() throws Exception {
        try {
            // set zen mode to priority only, so playSoundEffect will check notification policy
            Utils.toggleNotificationPolicyAccess(mContext.getPackageName(), getInstrumentation(),
                    true);
            setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY);
            Settings.System.putInt(mContext.getContentResolver(), SOUND_EFFECTS_ENABLED, 1);

            // take away write-notification policy access from the package
            Utils.toggleNotificationPolicyAccess(mContext.getPackageName(), getInstrumentation(),
                    false);

            // playSoundEffect should NOT throw a security exception; all apps have read-access
            mAudioManager.playSoundEffect(SoundEffectConstants.CLICK);
        } finally {
            Utils.toggleNotificationPolicyAccess(mContext.getPackageName(), getInstrumentation(),
                    true);
            setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
            Utils.toggleNotificationPolicyAccess(mContext.getPackageName(), getInstrumentation(),
                    false);
        }
    }

    public void testMusicActive() throws Exception {
        if (mAudioManager.isMusicActive()) {
            return;
        }
        MediaPlayer mp = MediaPlayer.create(mContext, MP3_TO_PLAY);
        assertNotNull(mp);
        mp.setAudioStreamType(STREAM_MUSIC);
        mp.start();
        assertMusicActive(true);
        mp.stop();
        mp.release();
        assertMusicActive(false);
    }

    @AppModeFull(reason = "Instant apps cannot hold android.permission.MODIFY_AUDIO_SETTINGS")
    public void testAccessMode() throws Exception {
        mAudioManager.setMode(MODE_RINGTONE);
        assertEquals(MODE_RINGTONE, mAudioManager.getMode());
        mAudioManager.setMode(MODE_IN_COMMUNICATION);
        assertEquals(MODE_IN_COMMUNICATION, mAudioManager.getMode());
        mAudioManager.setMode(MODE_NORMAL);
        assertEquals(MODE_NORMAL, mAudioManager.getMode());
    }

    public void testSetSurroundFormatEnabled() throws Exception {
        getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
                Manifest.permission.WRITE_SETTINGS);

        int audioFormat = AudioFormat.ENCODING_DTS;

        mAudioManager.setSurroundFormatEnabled(audioFormat, true /*enabled*/);
        assertTrue(mAudioManager.isSurroundFormatEnabled(audioFormat));

        mAudioManager.setSurroundFormatEnabled(audioFormat, false /*enabled*/);
        assertFalse(mAudioManager.isSurroundFormatEnabled(audioFormat));

        getInstrumentation().getUiAutomation().dropShellPermissionIdentity();
    }

    public void testSetEncodedSurroundMode() throws Exception {
        getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
                Manifest.permission.WRITE_SETTINGS);

        int expectedSurroundFormatsMode = Settings.Global.ENCODED_SURROUND_OUTPUT_MANUAL;
        mAudioManager.setEncodedSurroundMode(expectedSurroundFormatsMode);
        assertEquals(expectedSurroundFormatsMode, mAudioManager.getEncodedSurroundMode());

        expectedSurroundFormatsMode = Settings.Global.ENCODED_SURROUND_OUTPUT_NEVER;
        mAudioManager.setEncodedSurroundMode(expectedSurroundFormatsMode);
        assertEquals(expectedSurroundFormatsMode, mAudioManager.getEncodedSurroundMode());

        getInstrumentation().getUiAutomation().dropShellPermissionIdentity();
    }

    @SuppressWarnings("deprecation")
    @AppModeFull(reason = "Instant apps cannot hold android.permission.MODIFY_AUDIO_SETTINGS")
    public void testRouting() throws Exception {
        // setBluetoothA2dpOn is a no-op, and getRouting should always return -1
        boolean oldA2DP = mAudioManager.isBluetoothA2dpOn();
        mAudioManager.setBluetoothA2dpOn(true);
        assertEquals(oldA2DP , mAudioManager.isBluetoothA2dpOn());
        mAudioManager.setBluetoothA2dpOn(false);
        assertEquals(oldA2DP , mAudioManager.isBluetoothA2dpOn());

        assertEquals(-1, mAudioManager.getRouting(MODE_RINGTONE));
        assertEquals(-1, mAudioManager.getRouting(MODE_NORMAL));
        assertEquals(-1, mAudioManager.getRouting(MODE_IN_CALL));
        assertEquals(-1, mAudioManager.getRouting(MODE_IN_COMMUNICATION));

        mAudioManager.setBluetoothScoOn(true);
        assertTrueCheckTimeout(mAudioManager, p -> p.isBluetoothScoOn(),
                DEFAULT_ASYNC_CALL_TIMEOUT_MS, "isBluetoothScoOn returned false");

        mAudioManager.setBluetoothScoOn(false);
        assertTrueCheckTimeout(mAudioManager, p -> !p.isBluetoothScoOn(),
                DEFAULT_ASYNC_CALL_TIMEOUT_MS, "isBluetoothScoOn returned true");

        //  Speaker Phone Not supported in Automotive
        if (isAutomotive()) {
            return;
        }
        mAudioManager.setSpeakerphoneOn(true);
        assertTrueCheckTimeout(mAudioManager, p -> p.isSpeakerphoneOn(),
                DEFAULT_ASYNC_CALL_TIMEOUT_MS, "isSpeakerPhoneOn() returned false");

        mAudioManager.setSpeakerphoneOn(false);
        assertTrueCheckTimeout(mAudioManager, p -> !p.isSpeakerphoneOn(),
                DEFAULT_ASYNC_CALL_TIMEOUT_MS, "isSpeakerPhoneOn() returned true");
    }

    public void testVibrateNotification() throws Exception {
        if (mUseFixedVolume || !mHasVibrator) {
            return;
        }
        Utils.toggleNotificationPolicyAccess(
                mContext.getPackageName(), getInstrumentation(), true);
        // VIBRATE_SETTING_ON
        mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ON);
        assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF,
                mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
        mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
        assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));

        mAudioManager.setRingerMode(RINGER_MODE_SILENT);
        assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));

        mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
        assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
                mAudioManager.getRingerMode());
        assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));

        // VIBRATE_SETTING_OFF
        mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_OFF);
        assertEquals(VIBRATE_SETTING_OFF,
                mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
        mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
        assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));

        mAudioManager.setRingerMode(RINGER_MODE_SILENT);
        assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));

        mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
        assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
                mAudioManager.getRingerMode());
        assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));

        // VIBRATE_SETTING_ONLY_SILENT
        mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ONLY_SILENT);
        assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF,
                mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
        mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
        assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));

        mAudioManager.setRingerMode(RINGER_MODE_SILENT);
        assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));

        mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
        assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
                mAudioManager.getRingerMode());
        assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));

        // VIBRATE_TYPE_NOTIFICATION
        mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ON);
        assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF,
                mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
        mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_OFF);
        assertEquals(VIBRATE_SETTING_OFF, mAudioManager
                .getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
        mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ONLY_SILENT);
        assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF,
                mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
    }

    public void testVibrateRinger() throws Exception {
        if (mUseFixedVolume || !mHasVibrator) {
            return;
        }
        Utils.toggleNotificationPolicyAccess(
                mContext.getPackageName(), getInstrumentation(), true);
        // VIBRATE_TYPE_RINGER
        mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ON);
        assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF,
                mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
        mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
        assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));

        mAudioManager.setRingerMode(RINGER_MODE_SILENT);
        assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));

        mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
        assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
                mAudioManager.getRingerMode());
        assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));

        // VIBRATE_SETTING_OFF
        mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_OFF);
        assertEquals(VIBRATE_SETTING_OFF, mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
        mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
        assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));

        mAudioManager.setRingerMode(RINGER_MODE_SILENT);
        assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));

        mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
        assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
                mAudioManager.getRingerMode());
        // Note: as of Froyo, if VIBRATE_TYPE_RINGER is set to OFF, it will
        // not vibrate, even in RINGER_MODE_VIBRATE. This allows users to
        // disable the vibration for incoming calls only.
        assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));

        // VIBRATE_SETTING_ONLY_SILENT
        mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ONLY_SILENT);
        assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF,
                mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
        mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
        assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));

        mAudioManager.setRingerMode(RINGER_MODE_SILENT);
        assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));

        mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
        assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
                mAudioManager.getRingerMode());
        assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));

        // VIBRATE_TYPE_NOTIFICATION
        mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ON);
        assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF,
                mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
        mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_OFF);
        assertEquals(VIBRATE_SETTING_OFF, mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
        mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ONLY_SILENT);
        assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF,
                mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
    }

    public void testAccessRingMode() throws Exception {
        Utils.toggleNotificationPolicyAccess(
                mContext.getPackageName(), getInstrumentation(), true);
        mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
        assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());

        mAudioManager.setRingerMode(RINGER_MODE_SILENT);
        // AudioService#setRingerMode() has:
        // if (isTelevision) return;
        if (mSkipRingerTests) {
            assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
        } else {
            assertEquals(RINGER_MODE_SILENT, mAudioManager.getRingerMode());
        }

        mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
        if (mSkipRingerTests) {
            assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
        } else {
            assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
                    mAudioManager.getRingerMode());
        }
    }

    public void testSetRingerModePolicyAccess() throws Exception {
        if (mSkipRingerTests) {
            return;
        }
        // Apps without policy access cannot change silent -> normal or silent -> vibrate.
        Utils.toggleNotificationPolicyAccess(
                mContext.getPackageName(), getInstrumentation(), true);
        mAudioManager.setRingerMode(RINGER_MODE_SILENT);
        assertEquals(RINGER_MODE_SILENT, mAudioManager.getRingerMode());
        Utils.toggleNotificationPolicyAccess(
                mContext.getPackageName(), getInstrumentation(), false);

        try {
            mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
            fail("Apps without notification policy access cannot change ringer mode");
        } catch (SecurityException e) {
        }

        try {
            mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
            fail("Apps without notification policy access cannot change ringer mode");
        } catch (SecurityException e) {
        }

        // Apps without policy access cannot change normal -> silent.
        Utils.toggleNotificationPolicyAccess(
                mContext.getPackageName(), getInstrumentation(), true);
        mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
        assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
        Utils.toggleNotificationPolicyAccess(
                mContext.getPackageName(), getInstrumentation(), false);

        try {
            mAudioManager.setRingerMode(RINGER_MODE_SILENT);
            fail("Apps without notification policy access cannot change ringer mode");
        } catch (SecurityException e) {
        }
        assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());

        if (mHasVibrator) {
            // Apps without policy access cannot change vibrate -> silent.
            Utils.toggleNotificationPolicyAccess(
                    mContext.getPackageName(), getInstrumentation(), true);
            mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
            assertEquals(RINGER_MODE_VIBRATE, mAudioManager.getRingerMode());
            Utils.toggleNotificationPolicyAccess(
                    mContext.getPackageName(), getInstrumentation(), false);

            try {
                mAudioManager.setRingerMode(RINGER_MODE_SILENT);
                fail("Apps without notification policy access cannot change ringer mode");
            } catch (SecurityException e) {
            }

            // Apps without policy access can change vibrate -> normal and vice versa.
            assertEquals(RINGER_MODE_VIBRATE, mAudioManager.getRingerMode());
            mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
            assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
            mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
            assertEquals(RINGER_MODE_VIBRATE, mAudioManager.getRingerMode());
        }
    }

    public void testAccessRampingRinger() {
        boolean originalEnabledState = mAudioManager.isRampingRingerEnabled();
        try {
            mAudioManager.setRampingRingerEnabled(false);
            assertFalse(mAudioManager.isRampingRingerEnabled());

            mAudioManager.setRampingRingerEnabled(true);
            assertTrue(mAudioManager.isRampingRingerEnabled());
        } finally {
            mAudioManager.setRampingRingerEnabled(originalEnabledState);
        }
    }

    public void testRampingRingerSetting() {
        boolean originalEnabledState = mAudioManager.isRampingRingerEnabled();
        try {
            // Deprecated public setting should still be supported and affect the setting getter.
            Settings.Global.putInt(mContext.getContentResolver(), APPLY_RAMPING_RINGER, 0);
            assertFalse(mAudioManager.isRampingRingerEnabled());

            Settings.Global.putInt(mContext.getContentResolver(), APPLY_RAMPING_RINGER, 1);
            assertTrue(mAudioManager.isRampingRingerEnabled());
        } finally {
            mAudioManager.setRampingRingerEnabled(originalEnabledState);
        }
    }

    public void testVolume() throws Exception {
        if (MediaUtils.check(mIsTelevision, "No volume test due to fixed/full vol devices"))
            return;
        Utils.toggleNotificationPolicyAccess(
                mContext.getPackageName(), getInstrumentation(), true);
        int volume, volumeDelta;
        int[] streams = {STREAM_ALARM,
                STREAM_MUSIC,
                STREAM_VOICE_CALL,
                STREAM_RING};

        mAudioManager.adjustVolume(ADJUST_RAISE, 0);
        // adjusting volume is asynchronous, wait before other volume checks
        Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
        mAudioManager.adjustSuggestedStreamVolume(
                ADJUST_LOWER, USE_DEFAULT_STREAM_TYPE, 0);
        Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
        int maxMusicVolume = mAudioManager.getStreamMaxVolume(STREAM_MUSIC);

        for (int stream : streams) {
            if (mIsSingleVolume && stream != STREAM_MUSIC) {
                continue;
            }

            // set ringer mode to back normal to not interfere with volume tests
            mAudioManager.setRingerMode(RINGER_MODE_NORMAL);

            int maxVolume = mAudioManager.getStreamMaxVolume(stream);
            int minVolume = mAudioManager.getStreamMinVolume(stream);

            // validate min
            assertTrue(String.format("minVolume(%d) must be >= 0", minVolume), minVolume >= 0);
            assertTrue(String.format("minVolume(%d) must be < maxVolume(%d)", minVolume,
                    maxVolume),
                    minVolume < maxVolume);

            final int minNonZeroVolume = Math.max(minVolume, 1);
            mAudioManager.setStreamVolume(stream, minNonZeroVolume, 0);
            if (mUseFixedVolume) {
                assertEquals(maxVolume, mAudioManager.getStreamVolume(stream));
                continue;
            }
            assertEquals(String.format("stream=%d", stream),
                    minNonZeroVolume, mAudioManager.getStreamVolume(stream));

            if (stream == STREAM_MUSIC && mAudioManager.isWiredHeadsetOn()) {
                // due to new regulations, music sent over a wired headset may be volume limited
                // until the user explicitly increases the limit, so we can't rely on being able
                // to set the volume to getStreamMaxVolume(). Instead, determine the current limit
                // by increasing the volume until it won't go any higher, then use that volume as
                // the maximum for the purposes of this test
                int curvol = 0;
                int prevvol = 0;
                do {
                    prevvol = curvol;
                    mAudioManager.adjustStreamVolume(stream, ADJUST_RAISE, 0);
                    curvol = mAudioManager.getStreamVolume(stream);
                } while (curvol != prevvol);
                maxVolume = maxMusicVolume = curvol;
            }
            mAudioManager.setStreamVolume(stream, maxVolume, 0);
            mAudioManager.adjustStreamVolume(stream, ADJUST_RAISE, 0);
            assertEquals(maxVolume, mAudioManager.getStreamVolume(stream));

            volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(stream));
            mAudioManager.adjustSuggestedStreamVolume(ADJUST_LOWER, stream, 0);
            assertStreamVolumeEquals(stream, maxVolume - volumeDelta,
                    "Vol ADJUST_LOWER suggested stream:" + stream + " maxVol:" + maxVolume);

            // volume lower
            mAudioManager.setStreamVolume(stream, maxVolume, 0);
            volume = mAudioManager.getStreamVolume(stream);
            while (volume > minVolume) {
                volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(stream));
                mAudioManager.adjustStreamVolume(stream, ADJUST_LOWER, 0);
                assertStreamVolumeEquals(stream,  Math.max(0, volume - volumeDelta),
                        "Vol ADJUST_LOWER on stream:" + stream + " vol:" + volume
                                + " minVol:" + minVolume + " volDelta:" + volumeDelta);
                volume = mAudioManager.getStreamVolume(stream);
            }

            mAudioManager.adjustStreamVolume(stream, ADJUST_SAME, 0);

            // volume raise
            mAudioManager.setStreamVolume(stream, minNonZeroVolume, 0);
            volume = mAudioManager.getStreamVolume(stream);
            while (volume < maxVolume) {
                volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(stream));
                mAudioManager.adjustStreamVolume(stream, ADJUST_RAISE, 0);
                assertStreamVolumeEquals(stream,   Math.min(volume + volumeDelta, maxVolume),
                        "Vol ADJUST_RAISE on stream:" + stream + " vol:" + volume
                                + " maxVol:" + maxVolume + " volDelta:" + volumeDelta);
                volume = mAudioManager.getStreamVolume(stream);
            }

            // volume same
            mAudioManager.setStreamVolume(stream, maxVolume, 0);
            mAudioManager.adjustStreamVolume(stream, ADJUST_SAME, 0);
            Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
            assertEquals("Vol ADJUST_RAISE onADJUST_SAME stream:" + stream,
                    maxVolume, mAudioManager.getStreamVolume(stream));

            mAudioManager.setStreamVolume(stream, maxVolume, 0);
        }

        if (mUseFixedVolume) {
            return;
        }

        // adjust volume
        mAudioManager.adjustVolume(ADJUST_RAISE, 0);
        Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);

        boolean isMusicPlayingBeforeTest = false;
        if (mAudioManager.isMusicActive()) {
            isMusicPlayingBeforeTest = true;
        }

        MediaPlayer mp = MediaPlayer.create(mContext, MP3_TO_PLAY);
        assertNotNull(mp);
        mp.setAudioStreamType(STREAM_MUSIC);
        mp.setLooping(true);
        mp.start();
        assertMusicActive(true);

        // adjust volume as ADJUST_SAME
        mAudioManager.adjustVolume(ADJUST_SAME, 0);
        Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
        assertStreamVolumeEquals(STREAM_MUSIC, maxMusicVolume);

        // adjust volume as ADJUST_RAISE
        mAudioManager.setStreamVolume(STREAM_MUSIC, 0, 0);
        volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(STREAM_MUSIC));
        mAudioManager.adjustVolume(ADJUST_RAISE, 0);
        Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
        assertStreamVolumeEquals(STREAM_MUSIC, Math.min(volumeDelta, maxMusicVolume));

        // adjust volume as ADJUST_LOWER
        mAudioManager.setStreamVolume(STREAM_MUSIC, maxMusicVolume, 0);
        maxMusicVolume = mAudioManager.getStreamVolume(STREAM_MUSIC);
        volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(STREAM_MUSIC));
        mAudioManager.adjustVolume(ADJUST_LOWER, 0);
        assertStreamVolumeEquals(STREAM_MUSIC, Math.max(0, maxMusicVolume - volumeDelta));

        mp.stop();
        mp.release();
        if (!isMusicPlayingBeforeTest) {
            assertMusicActive(false);
        }
    }

    public void testAccessibilityVolume() throws Exception {
        if (mUseFixedVolume) {
            Log.i("AudioManagerTest", "testAccessibilityVolume() skipped: fixed volume");
            return;
        }
        final int maxA11yVol = mAudioManager.getStreamMaxVolume(STREAM_ACCESSIBILITY);
        assertTrue("Max a11yVol not strictly positive", maxA11yVol > 0);
        int originalVol = mAudioManager.getStreamVolume(STREAM_ACCESSIBILITY);

        // changing STREAM_ACCESSIBILITY is subject to permission, shouldn't be able to change it
        // test setStreamVolume
        final int testSetVol;
        if (originalVol != maxA11yVol) {
            testSetVol = maxA11yVol;
        } else {
            testSetVol = maxA11yVol - 1;
        }
        mAudioManager.setStreamVolume(STREAM_ACCESSIBILITY, testSetVol, 0);
        assertStreamVolumeEquals(STREAM_ACCESSIBILITY, originalVol,
                "Should not be able to change A11y vol");

        // test adjustStreamVolume
        //        LOWER
        if (originalVol > 0) {
            mAudioManager.adjustStreamVolume(STREAM_ACCESSIBILITY, ADJUST_LOWER, 0);
            assertStreamVolumeEquals(STREAM_ACCESSIBILITY, originalVol,
                    "Should not be able to change A11y vol");
        }
        //        RAISE
        if (originalVol < maxA11yVol) {
            mAudioManager.adjustStreamVolume(STREAM_ACCESSIBILITY, ADJUST_RAISE, 0);
            assertStreamVolumeEquals(STREAM_ACCESSIBILITY, originalVol,
                    "Should not be able to change A11y vol");
        }
    }

    public void testSetVoiceCallVolumeToZeroPermission() {
        // Verify that only apps with MODIFY_PHONE_STATE can set VOICE_CALL_STREAM to 0
        mAudioManager.setStreamVolume(STREAM_VOICE_CALL, 0, 0);
        assertTrue("MODIFY_PHONE_STATE is required in order to set voice call volume to 0",
                    mAudioManager.getStreamVolume(STREAM_VOICE_CALL) != 0);
    }

    public void testMuteFixedVolume() throws Exception {
        int[] streams = {
                STREAM_VOICE_CALL,
                STREAM_MUSIC,
                STREAM_RING,
                STREAM_ALARM,
                STREAM_NOTIFICATION,
                STREAM_SYSTEM};
        if (mUseFixedVolume) {
            for (int stream : streams) {
                mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_MUTE, 0);
                assertFalse("Muting should not affect a fixed volume device.",
                        mAudioManager.isStreamMute(stream));

                mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_TOGGLE_MUTE, 0);
                assertFalse("Toggling mute should not affect a fixed volume device.",
                        mAudioManager.isStreamMute(stream));

                mAudioManager.setStreamMute(stream, true);
                assertFalse("Muting should not affect a fixed volume device.",
                        mAudioManager.isStreamMute(stream));
            }
        }
    }

    public void testMuteDndAffectedStreams() throws Exception {
        if (mSkipRingerTests) {
            return;
        }
        int[] streams = { STREAM_RING };
        // Mute streams
        Utils.toggleNotificationPolicyAccess(
                mContext.getPackageName(), getInstrumentation(), true);
        mAudioManager.setRingerMode(RINGER_MODE_SILENT);
        Utils.toggleNotificationPolicyAccess(
                mContext.getPackageName(), getInstrumentation(), false);
        // Verify streams cannot be unmuted without policy access.
        for (int stream : streams) {
            try {
                mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_UNMUTE, 0);
                assertEquals("Apps without Notification policy access can't change ringer mode",
                        RINGER_MODE_SILENT, mAudioManager.getRingerMode());
            } catch (SecurityException e) {
            }

            try {
                mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_TOGGLE_MUTE,
                        0);
                assertEquals("Apps without Notification policy access can't change ringer mode",
                        RINGER_MODE_SILENT, mAudioManager.getRingerMode());
            } catch (SecurityException e) {
            }

            try {
                mAudioManager.setStreamMute(stream, false);
                assertEquals("Apps without Notification policy access can't change ringer mode",
                        RINGER_MODE_SILENT, mAudioManager.getRingerMode());
            } catch (SecurityException e) {
            }
        }

        // This ensures we're out of vibrate or silent modes.
        Utils.toggleNotificationPolicyAccess(
                mContext.getPackageName(), getInstrumentation(), true);
        mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
        for (int stream : streams) {
            // ensure each stream is on and turned up.
            mAudioManager.setStreamVolume(stream,
                    mAudioManager.getStreamMaxVolume(stream),
                    0);

            Utils.toggleNotificationPolicyAccess(
                    mContext.getPackageName(), getInstrumentation(), false);
            try {
                mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_MUTE, 0);
                assertEquals("Apps without Notification policy access can't change ringer mode",
                        RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
            } catch (SecurityException e) {
            }
            try {
                mAudioManager.adjustStreamVolume(
                        stream, AudioManager.ADJUST_TOGGLE_MUTE, 0);
                assertEquals("Apps without Notification policy access can't change ringer mode",
                        RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
            } catch (SecurityException e) {
            }

            try {
                mAudioManager.setStreamMute(stream, true);
                assertEquals("Apps without Notification policy access can't change ringer mode",
                        RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
            } catch (SecurityException e) {
            }
            Utils.toggleNotificationPolicyAccess(
                    mContext.getPackageName(), getInstrumentation(), true);
            testStreamMuting(stream);
        }
    }

    public void testMuteDndUnaffectedStreams() throws Exception {
        if (mSkipRingerTests) {
            return;
        }
        int[] streams = {
                STREAM_VOICE_CALL,
                STREAM_MUSIC,
                STREAM_ALARM
        };

        int muteAffectedStreams = System.getInt(mContext.getContentResolver(),
                System.MUTE_STREAMS_AFFECTED,
                // same defaults as in AudioService. Should be kept in sync.
                 (1 << STREAM_MUSIC) |
                         (1 << STREAM_RING) |
                         (1 << STREAM_NOTIFICATION) |
                         (1 << STREAM_SYSTEM) |
                         (1 << STREAM_VOICE_CALL));

        Utils.toggleNotificationPolicyAccess(
                mContext.getPackageName(), getInstrumentation(), true);
        // This ensures we're out of vibrate or silent modes.
        mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
        Utils.toggleNotificationPolicyAccess(
                mContext.getPackageName(), getInstrumentation(), false);
        for (int stream : streams) {
            // ensure each stream is on and turned up.
            mAudioManager.setStreamVolume(stream,
                    mAudioManager.getStreamMaxVolume(stream),
                    0);
            if (((1 << stream) & muteAffectedStreams) == 0) {
                mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_MUTE, 0);
                assertFalse("Stream " + stream + " should not be affected by mute.",
                        mAudioManager.isStreamMute(stream));
                mAudioManager.setStreamMute(stream, true);
                assertFalse("Stream " + stream + " should not be affected by mute.",
                        mAudioManager.isStreamMute(stream));
                mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_TOGGLE_MUTE,
                        0);
                assertFalse("Stream " + stream + " should not be affected by mute.",
                        mAudioManager.isStreamMute(stream));
                continue;
            }
            testStreamMuting(stream);
        }
    }

    private void testStreamMuting(int stream) {
        getInstrumentation().getUiAutomation()
                .adoptShellPermissionIdentity(Manifest.permission.QUERY_AUDIO_STATE);

        final int streamVolume = mAudioManager.getLastAudibleStreamVolume(stream);

        // Voice call requires MODIFY_PHONE_STATE, so we should not be able to mute
        if (stream == STREAM_VOICE_CALL) {
            mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_MUTE, 0);
            assertFalse("Muting voice call stream (" + stream + ") should require "
                            + "MODIFY_PHONE_STATE.", mAudioManager.isStreamMute(stream));
        } else {
            mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_MUTE, 0);
            assertTrue("Muting stream " + stream + " failed.",
                    mAudioManager.isStreamMute(stream));

            assertEquals(streamVolume, mAudioManager.getLastAudibleStreamVolume(stream));

            mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_UNMUTE, 0);
            assertFalse("Unmuting stream " + stream + " failed.",
                    mAudioManager.isStreamMute(stream));

            assertEquals(streamVolume, mAudioManager.getLastAudibleStreamVolume(stream));

            mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_TOGGLE_MUTE, 0);
            assertTrue("Toggling mute on stream " + stream + " failed.",
                    mAudioManager.isStreamMute(stream));

            assertEquals(streamVolume, mAudioManager.getLastAudibleStreamVolume(stream));

            mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_TOGGLE_MUTE, 0);
            assertFalse("Toggling mute on stream " + stream + " failed.",
                    mAudioManager.isStreamMute(stream));

            assertEquals(streamVolume, mAudioManager.getLastAudibleStreamVolume(stream));

            mAudioManager.setStreamMute(stream, true);
            assertTrue("Muting stream " + stream + " using setStreamMute failed",
                    mAudioManager.isStreamMute(stream));

            assertEquals(streamVolume, mAudioManager.getLastAudibleStreamVolume(stream));

            // mute it three more times to verify the ref counting is gone.
            mAudioManager.setStreamMute(stream, true);
            mAudioManager.setStreamMute(stream, true);
            mAudioManager.setStreamMute(stream, true);

            mAudioManager.setStreamMute(stream, false);
            assertFalse("Unmuting stream " + stream + " using setStreamMute failed.",
                    mAudioManager.isStreamMute(stream));
        }
        assertEquals(streamVolume, mAudioManager.getLastAudibleStreamVolume(stream));

        getInstrumentation().getUiAutomation().dropShellPermissionIdentity();
    }

    public void testSetInvalidRingerMode() {
        int ringerMode = mAudioManager.getRingerMode();
        mAudioManager.setRingerMode(-1337);
        assertEquals(ringerMode, mAudioManager.getRingerMode());

        mAudioManager.setRingerMode(-3007);
        assertEquals(ringerMode, mAudioManager.getRingerMode());
    }

    public void testAdjustVolumeInTotalSilenceMode() throws Exception {
        if (mSkipRingerTests) {
            return;
        }
        try {
            Utils.toggleNotificationPolicyAccess(
                    mContext.getPackageName(), getInstrumentation(), true);
            mAudioManager.setStreamVolume(STREAM_MUSIC, 1, 0);
            setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_NONE);
            Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
            int musicVolume = mAudioManager.getStreamVolume(STREAM_MUSIC);
            mAudioManager.adjustStreamVolume(
                    STREAM_MUSIC, ADJUST_RAISE, 0);
            assertStreamVolumeEquals(STREAM_MUSIC, musicVolume);

        } finally {
            setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
        }
    }

    public void testAdjustVolumeInAlarmsOnlyMode() throws Exception {
        if (mSkipRingerTests) {
            return;
        }
        try {
            Utils.toggleNotificationPolicyAccess(
                    mContext.getPackageName(), getInstrumentation(), true);
            mAudioManager.setStreamVolume(STREAM_MUSIC, 1, 0);

            setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALARMS);
            Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
            int musicVolume = mAudioManager.getStreamVolume(STREAM_MUSIC);
            mAudioManager.adjustStreamVolume(
                    STREAM_MUSIC, ADJUST_RAISE, 0);
            int volumeDelta =
                    getVolumeDelta(mAudioManager.getStreamVolume(STREAM_MUSIC));
            assertStreamVolumeEquals(STREAM_MUSIC, musicVolume + volumeDelta);

        } finally {
            setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
        }
    }

    public void testSetStreamVolumeInTotalSilenceMode() throws Exception {
        if (mSkipRingerTests) {
            return;
        }
        try {
            Utils.toggleNotificationPolicyAccess(
                    mContext.getPackageName(), getInstrumentation(), true);
            mAudioManager.setStreamVolume(STREAM_RING, 1, 0);
            mAudioManager.setStreamVolume(STREAM_MUSIC, 1, 0);

            setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_NONE);
            // delay for streams interruption filter to get into correct state
            Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);

            // cannot adjust music, can adjust ringer since it could exit DND
            int musicVolume = mAudioManager.getStreamVolume(STREAM_MUSIC);
            mAudioManager.setStreamVolume(STREAM_MUSIC, 7, 0);
            assertStreamVolumeEquals(STREAM_MUSIC, musicVolume);
            mAudioManager.setStreamVolume(STREAM_RING, 7, 0);
            assertStreamVolumeEquals(STREAM_RING, 7);
        } finally {
            setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
        }
    }

    public void testSetStreamVolumeInAlarmsOnlyMode() throws Exception {
        if (mSkipRingerTests) {
            return;
        }
        try {
            Utils.toggleNotificationPolicyAccess(
                    mContext.getPackageName(), getInstrumentation(), true);
            mAudioManager.setStreamVolume(STREAM_RING, 1, 0);
            mAudioManager.setStreamVolume(STREAM_MUSIC, 1, 0);
            setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALARMS);
            // delay for streams to get into correct volume states
            Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);

            // can still adjust music and ring volume
            mAudioManager.setStreamVolume(STREAM_MUSIC, 3, 0);
            assertStreamVolumeEquals(STREAM_MUSIC, 3);
            mAudioManager.setStreamVolume(STREAM_RING, 7, 0);
            assertStreamVolumeEquals(STREAM_RING, 7);
        } finally {
            setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
        }
    }

    public void testSetStreamVolumeInPriorityOnlyMode() throws Exception {
        if (mSkipRingerTests) {
            return;
        }
        Utils.toggleNotificationPolicyAccess(
                mContext.getPackageName(), getInstrumentation(), true);

        try {
            // turn off zen, set stream volumes to check for later
            setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);

            final int testRingerVol = getTestRingerVol();
            mAudioManager.setStreamVolume(STREAM_MUSIC, 1, 0);
            mAudioManager.setStreamVolume(STREAM_ALARM, 1, 0);
            int musicVolume = mAudioManager.getStreamVolume(STREAM_MUSIC);
            int alarmVolume = mAudioManager.getStreamVolume(STREAM_ALARM);

            // disallow all sounds in priority only, turn on priority only DND, try to change volume
            mNm.setNotificationPolicy(new NotificationManager.Policy(0, 0 , 0));
            setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY);
            // delay for streams to get into correct volume states
            Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
            mAudioManager.setStreamVolume(STREAM_MUSIC, 3, 0);
            mAudioManager.setStreamVolume(STREAM_ALARM, 5, 0);
            mAudioManager.setStreamVolume(STREAM_RING, testRingerVol, 0);

            // Turn off zen and make sure stream levels are still the same prior to zen
            // aside from ringer since ringer can exit dnd
            setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
            Thread.sleep(ASYNC_TIMING_TOLERANCE_MS); // delay for streams to get into correct states
            assertEquals(musicVolume, mAudioManager.getStreamVolume(STREAM_MUSIC));
            assertEquals(alarmVolume, mAudioManager.getStreamVolume(STREAM_ALARM));
            assertEquals(testRingerVol, mAudioManager.getStreamVolume(STREAM_RING));
        } finally {
            setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
        }
    }

    public void testAdjustVolumeInPriorityOnly() throws Exception {
        if (mSkipRingerTests) {
            return;
        }

        Utils.toggleNotificationPolicyAccess(
                mContext.getPackageName(), getInstrumentation(), true);
        try {
            // turn off zen, set stream volumes to check for later
            setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
            mAudioManager.setStreamVolume(STREAM_RING, 1, 0);
            mAudioManager.setStreamVolume(STREAM_MUSIC, 1, 0);
            mAudioManager.setStreamVolume(STREAM_ALARM, 1, 0);
            int ringVolume = mAudioManager.getStreamVolume(STREAM_RING);
            int musicVolume = mAudioManager.getStreamVolume(STREAM_MUSIC);
            int alarmVolume = mAudioManager.getStreamVolume(STREAM_ALARM);

            // disallow all sounds in priority only, turn on priority only DND, try to change volume
            mNm.setNotificationPolicy(new NotificationManager.Policy(0, 0, 0));
            setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY);
            // delay for streams to get into correct mute states
            Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
            mAudioManager.adjustStreamVolume(
                    STREAM_RING, ADJUST_RAISE, 0);
            mAudioManager.adjustStreamVolume(
                    STREAM_MUSIC, ADJUST_RAISE, 0);
            mAudioManager.adjustStreamVolume(
                    STREAM_ALARM, ADJUST_RAISE, 0);

            // Turn off zen and make sure stream levels are still the same prior to zen
            // aside from ringer since ringer can exit dnd
            setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
            Thread.sleep(ASYNC_TIMING_TOLERANCE_MS); // delay for streams to get into correct states
            assertEquals(musicVolume, mAudioManager.getStreamVolume(STREAM_MUSIC));
            assertEquals(alarmVolume, mAudioManager.getStreamVolume(STREAM_ALARM));

            int volumeDelta =
                    getVolumeDelta(mAudioManager.getStreamVolume(STREAM_RING));
            assertEquals(ringVolume + volumeDelta,
                    mAudioManager.getStreamVolume(STREAM_RING));
        } finally {
            setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
        }
    }

    public void testPriorityOnlyMuteAll() throws Exception {
        if (mSkipRingerTests) {
            return;
        }

        Utils.toggleNotificationPolicyAccess(
                mContext.getPackageName(), getInstrumentation(), true);
        try {
            // ensure volume is not muted/0 to start test
            mAudioManager.setStreamVolume(STREAM_MUSIC, 1, 0);
            mAudioManager.setStreamVolume(STREAM_ALARM, 1, 0);
            mAudioManager.setStreamVolume(STREAM_SYSTEM, 1, 0);
            mAudioManager.setStreamVolume(STREAM_RING, 1, 0);

            // disallow all sounds in priority only, turn on priority only DND
            mNm.setNotificationPolicy(new NotificationManager.Policy(0, 0, 0));
            setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY);

            assertStreamMuted(STREAM_MUSIC, true,
                    "Music (media) stream should be muted");
            assertStreamMuted(STREAM_SYSTEM, true,
                    "System stream should be muted");
            assertStreamMuted(STREAM_ALARM, true,
                    "Alarm stream should be muted");

            // if channels cannot bypass DND, the Ringer stream should be muted, else it
            // shouldn't be muted
            assertStreamMuted(STREAM_RING, !mAppsBypassingDnd,
                    "Ringer stream should be muted if channels cannot bypassDnd");
        } finally {
            setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
        }
    }

    public void testPriorityOnlyMediaAllowed() throws Exception {
        if (mSkipRingerTests) {
            return;
        }
        Utils.toggleNotificationPolicyAccess(
                mContext.getPackageName(), getInstrumentation(), true);
        try {
            // ensure volume is not muted/0 to start test
            mAudioManager.setStreamVolume(STREAM_MUSIC, 1, 0);
            mAudioManager.setStreamVolume(STREAM_ALARM, 1, 0);
            mAudioManager.setStreamVolume(STREAM_SYSTEM, 1, 0);
            mAudioManager.setStreamVolume(STREAM_RING, 1, 0);

            // allow only media in priority only
            mNm.setNotificationPolicy(new NotificationManager.Policy(
                    NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA, 0, 0));
            setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY);

            assertStreamMuted(STREAM_MUSIC, false,
                    "Music (media) stream should not be muted");
            assertStreamMuted(STREAM_SYSTEM, true,
                    "System stream should be muted");
            assertStreamMuted(STREAM_ALARM, true,
                    "Alarm stream should be muted");

            // if channels cannot bypass DND, the Ringer stream should be muted, else it
            // shouldn't be muted
            assertStreamMuted(STREAM_RING, !mAppsBypassingDnd,
                    "Ringer stream should be muted if channels cannot bypassDnd");
        } finally {
            setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
        }
    }

    public void testPriorityOnlySystemAllowed() throws Exception {
        if (mSkipRingerTests) {
            return;
        }

        Utils.toggleNotificationPolicyAccess(
                mContext.getPackageName(), getInstrumentation(), true);
        try {
            // ensure volume is not muted/0 to start test
            mAudioManager.setStreamVolume(STREAM_MUSIC, 1, 0);
            mAudioManager.setStreamVolume(STREAM_ALARM, 1, 0);
            mAudioManager.setStreamVolume(STREAM_SYSTEM, 1, 0);
            mAudioManager.setStreamVolume(STREAM_RING, 1, 0);

            // allow only system in priority only
            mNm.setNotificationPolicy(new NotificationManager.Policy(
                    NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM, 0, 0));
            setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY);

            assertStreamMuted(STREAM_MUSIC, true,
                    "Music (media) stream should be muted");
            assertStreamMuted(STREAM_SYSTEM, false,
                    "System stream should not be muted");
            assertStreamMuted(STREAM_ALARM, true,
                    "Alarm stream should be muted");
            assertStreamMuted(STREAM_RING, false,
                    "Ringer stream should not be muted");
        } finally {
            setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
        }
    }

    public void testPriorityOnlySystemDisallowedWithRingerMuted() throws Exception {
        if (mSkipRingerTests) {
            return;
        }

        Utils.toggleNotificationPolicyAccess(
                mContext.getPackageName(), getInstrumentation(), true);
        try {
            // ensure volume is not muted/0 to start test, but then mute ringer
            mAudioManager.setStreamVolume(STREAM_MUSIC, 1, 0);
            mAudioManager.setStreamVolume(STREAM_ALARM, 1, 0);
            mAudioManager.setStreamVolume(STREAM_SYSTEM, 1, 0);
            mAudioManager.setStreamVolume(STREAM_RING, 0, 0);
            mAudioManager.setRingerMode(RINGER_MODE_SILENT);

            // allow only system in priority only
            mNm.setNotificationPolicy(new NotificationManager.Policy(
                    NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM, 0, 0));
            setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY);

            assertStreamMuted(STREAM_MUSIC, true,
                    "Music (media) stream should be muted");
            assertStreamMuted(STREAM_SYSTEM, true,
                    "System stream should be muted");
            assertStreamMuted(STREAM_ALARM, true,
                    "Alarm stream should be muted");
            assertStreamMuted(STREAM_RING, true,
                    "Ringer stream should be muted");
        } finally {
            setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
        }
    }

    public void testPriorityOnlyAlarmsAllowed() throws Exception {
        if (mSkipRingerTests) {
            return;
        }

        Utils.toggleNotificationPolicyAccess(
                mContext.getPackageName(), getInstrumentation(), true);
        try {
            // ensure volume is not muted/0 to start test
            mAudioManager.setStreamVolume(STREAM_MUSIC, 1, 0);
            mAudioManager.setStreamVolume(STREAM_ALARM, 1, 0);
            mAudioManager.setStreamVolume(STREAM_SYSTEM, 1, 0);
            mAudioManager.setStreamVolume(STREAM_RING, 1, 0);

            // allow only alarms in priority only
            mNm.setNotificationPolicy(new NotificationManager.Policy(
                    NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS, 0, 0));
            setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY);

            assertStreamMuted(STREAM_MUSIC, true,
                    "Music (media) stream should be muted");
            assertStreamMuted(STREAM_SYSTEM, true,
                    "System stream should be muted");
            assertStreamMuted(STREAM_ALARM, false,
                    "Alarm stream should not be muted");

            // if channels cannot bypass DND, the Ringer stream should be muted, else it
            // shouldn't be muted
            assertStreamMuted(STREAM_RING, !mAppsBypassingDnd,
                    "Ringer stream should be muted if channels cannot bypassDnd");
        } finally {
            setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
        }
    }

    public void testPriorityOnlyRingerAllowed() throws Exception {
        if (mSkipRingerTests) {
            return;
        }

        Utils.toggleNotificationPolicyAccess(
                mContext.getPackageName(), getInstrumentation(), true);
        try {
            // ensure volume is not muted/0 to start test
            mAudioManager.setStreamVolume(STREAM_MUSIC, 1, 0);
            mAudioManager.setStreamVolume(STREAM_ALARM, 1, 0);
            mAudioManager.setStreamVolume(STREAM_SYSTEM, 1, 0);
            mAudioManager.setStreamVolume(STREAM_RING, 1, 0);

            // allow only reminders in priority only
            mNm.setNotificationPolicy(new NotificationManager.Policy(
                    NotificationManager.Policy.PRIORITY_CATEGORY_REMINDERS, 0, 0));
            setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY);

            assertStreamMuted(STREAM_MUSIC, true,
                    "Music (media) stream should be muted");
            assertStreamMuted(STREAM_SYSTEM, true,
                    "System stream should be muted");
            assertStreamMuted(STREAM_ALARM, true,
                    "Alarm stream should be muted");
            assertStreamMuted(STREAM_RING, false,
                    "Ringer stream should not be muted");
        } finally {
            setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
        }
    }

    public void testPriorityOnlyChannelsCanBypassDnd() throws Exception {
        if (mSkipRingerTests) {
            return;
        }

        Utils.toggleNotificationPolicyAccess(
                mContext.getPackageName(), getInstrumentation(), true);

        final String NOTIFICATION_CHANNEL_ID = "test_id_" + SystemClock.uptimeMillis();
        NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "TEST",
                NotificationManager.IMPORTANCE_DEFAULT);
        try {
            // ensure volume is not muted/0 to start test
            mAudioManager.setStreamVolume(STREAM_MUSIC, 1, 0);
            mAudioManager.setStreamVolume(STREAM_ALARM, 1, 0);
            mAudioManager.setStreamVolume(STREAM_SYSTEM, 1, 0);
            mAudioManager.setStreamVolume(STREAM_RING, 1, 0);

            // create a channel that can bypass dnd
            channel.setBypassDnd(true);
            mNm.createNotificationChannel(channel);

            // allow nothing
            mNm.setNotificationPolicy(new NotificationManager.Policy(0,0, 0));
            setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY);

            assertStreamMuted(STREAM_MUSIC, true,
                    "Music (media) stream should be muted");
            assertStreamMuted(STREAM_SYSTEM, true,
                    "System stream should be muted");
            assertStreamMuted(STREAM_ALARM, true,
                    "Alarm stream should be muted");
            assertStreamMuted(STREAM_RING, false,
                    "Ringer stream should not be muted."
                            + " areChannelsBypassing="
                            + NotificationManager.getService().areChannelsBypassingDnd());

            // delete the channel that can bypass dnd
            mNm.deleteNotificationChannel(NOTIFICATION_CHANNEL_ID);

            assertStreamMuted(STREAM_MUSIC, true,
                    "Music (media) stream should be muted");
            assertStreamMuted(STREAM_SYSTEM, true,
                    "System stream should be muted");
            assertStreamMuted(STREAM_ALARM, true,
                    "Alarm stream should be muted");
            // if channels cannot bypass DND, the Ringer stream should be muted, else it
            // shouldn't be muted
            assertStreamMuted(STREAM_RING, !mAppsBypassingDnd,
                    "Ringer stream should be muted if apps are bypassing dnd"
                            + " areChannelsBypassing="
                            + NotificationManager.getService().areChannelsBypassingDnd());
        } finally {
            setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
            mNm.deleteNotificationChannel(NOTIFICATION_CHANNEL_ID);
            Utils.toggleNotificationPolicyAccess(mContext.getPackageName(), getInstrumentation(),
                    false);
        }
    }

    public void testAdjustVolumeWithIllegalDirection() throws Exception {
        // Call the method with illegal direction. System should not reboot.
        mAudioManager.adjustVolume(37, 0);
    }

    private final int[] PUBLIC_STREAM_TYPES = { STREAM_VOICE_CALL,
            STREAM_SYSTEM, STREAM_RING, STREAM_MUSIC,
            STREAM_ALARM, STREAM_NOTIFICATION,
            STREAM_DTMF,  STREAM_ACCESSIBILITY };

    public void testGetStreamVolumeDbWithIllegalArguments() throws Exception {
        Exception ex = null;
        // invalid stream type
        try {
            float gain = mAudioManager.getStreamVolumeDb(-100 /*streamType*/, 0,
                    AudioDeviceInfo.TYPE_BUILTIN_SPEAKER);
        } catch (Exception e) {
            ex = e; // expected
        }
        assertNotNull("No exception was thrown for an invalid stream type", ex);
        assertEquals("Wrong exception thrown for invalid stream type",
                ex.getClass(), IllegalArgumentException.class);

        // invalid volume index
        ex = null;
        try {
            float gain = mAudioManager.getStreamVolumeDb(STREAM_MUSIC, -101 /*volume*/,
                    AudioDeviceInfo.TYPE_BUILTIN_SPEAKER);
        } catch (Exception e) {
            ex = e; // expected
        }
        assertNotNull("No exception was thrown for an invalid volume index", ex);
        assertEquals("Wrong exception thrown for invalid volume index",
                ex.getClass(), IllegalArgumentException.class);

        // invalid out of range volume index
        ex = null;
        try {
            final int maxVol = mAudioManager.getStreamMaxVolume(STREAM_MUSIC);
            float gain = mAudioManager.getStreamVolumeDb(STREAM_MUSIC, maxVol + 1,
                    AudioDeviceInfo.TYPE_BUILTIN_SPEAKER);
        } catch (Exception e) {
            ex = e; // expected
        }
        assertNotNull("No exception was thrown for an invalid out of range volume index", ex);
        assertEquals("Wrong exception thrown for invalid out of range volume index",
                ex.getClass(), IllegalArgumentException.class);

        // invalid device type
        ex = null;
        try {
            float gain = mAudioManager.getStreamVolumeDb(STREAM_MUSIC, 0,
                    -102 /*deviceType*/);
        } catch (Exception e) {
            ex = e; // expected
        }
        assertNotNull("No exception was thrown for an invalid device type", ex);
        assertEquals("Wrong exception thrown for invalid device type",
                ex.getClass(), IllegalArgumentException.class);

        // invalid input device type
        ex = null;
        try {
            float gain = mAudioManager.getStreamVolumeDb(STREAM_MUSIC, 0,
                    AudioDeviceInfo.TYPE_BUILTIN_MIC);
        } catch (Exception e) {
            ex = e; // expected
        }
        assertNotNull("No exception was thrown for an invalid input device type", ex);
        assertEquals("Wrong exception thrown for invalid input device type",
                ex.getClass(), IllegalArgumentException.class);
    }

    public void testGetStreamVolumeDb() throws Exception {
        for (int streamType : PUBLIC_STREAM_TYPES) {
            // verify mininum index is strictly inferior to maximum index
            final int minIndex = mAudioManager.getStreamMinVolume(streamType);
            final int maxIndex = mAudioManager.getStreamMaxVolume(streamType);
            assertTrue("Min vol index (" + minIndex + ") for stream " + streamType + " not inferior"
                    + " to max vol index (" + maxIndex + ")", minIndex <= maxIndex);
            float prevGain = Float.NEGATIVE_INFINITY;
            // verify gain increases with the volume indices
            for (int idx = minIndex ; idx <= maxIndex ; idx++) {
                float gain = mAudioManager.getStreamVolumeDb(streamType, idx,
                        AudioDeviceInfo.TYPE_BUILTIN_SPEAKER);
                assertTrue("Non-monotonically increasing gain at index " + idx + " for stream"
                        + streamType, prevGain <= gain);
                prevGain = gain;
            }
        }
    }

    public void testAdjustSuggestedStreamVolumeWithIllegalArguments() throws Exception {
        // Call the method with illegal direction. System should not reboot.
        mAudioManager.adjustSuggestedStreamVolume(37, STREAM_MUSIC, 0);

        // Call the method with illegal stream. System should not reboot.
        mAudioManager.adjustSuggestedStreamVolume(ADJUST_RAISE, 66747, 0);
    }

    @CddTest(requirement="5.4.1/C-1-4")
    public void testGetMicrophones() throws Exception {
        if (!mContext.getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_MICROPHONE)) {
            return;
        }
        List<MicrophoneInfo> microphones = mAudioManager.getMicrophones();
        assertTrue(microphones.size() > 0);
        for (int i = 0; i < microphones.size(); i++) {
            MicrophoneInfo microphone = microphones.get(i);
            Log.i(TAG, "deviceId:" + microphone.getDescription());
            Log.i(TAG, "portId:" + microphone.getId());
            Log.i(TAG, "type:" + microphone.getType());
            Log.i(TAG, "address:" + microphone.getAddress());
            Log.i(TAG, "deviceLocation:" + microphone.getLocation());
            Log.i(TAG, "deviceGroup:" + microphone.getGroup()
                    + " index:" + microphone.getIndexInTheGroup());
            MicrophoneInfo.Coordinate3F position = microphone.getPosition();
            Log.i(TAG, "position:" + position.x + " " + position.y + " " + position.z);
            MicrophoneInfo.Coordinate3F orientation = microphone.getOrientation();
            Log.i(TAG, "orientation:" + orientation.x + " "
                    + orientation.y + " " + orientation.z);
            Log.i(TAG, "frequencyResponse:" + microphone.getFrequencyResponse());
            Log.i(TAG, "channelMapping:" + microphone.getChannelMapping());
            Log.i(TAG, "sensitivity:" + microphone.getSensitivity());
            Log.i(TAG, "max spl:" + microphone.getMaxSpl());
            Log.i(TAG, "min spl:" + microphone.getMinSpl());
            Log.i(TAG, "directionality:" + microphone.getDirectionality());
            Log.i(TAG, "--------------");
        }
    }

    public void testIsHapticPlaybackSupported() {
        // Calling the API to make sure it doesn't crash.
        Log.i(TAG, "isHapticPlaybackSupported: " + AudioManager.isHapticPlaybackSupported());
    }

    public void testIsUltrasoundSupported() {
        // Calling the API to make sure it must crash due to no permission.
        try {
            mAudioManager.isUltrasoundSupported();
            fail("isUltrasoundSupported must fail due to no permission");
        } catch (SecurityException e) {
        }
    }

    public void testGetAudioHwSyncForSession() {
        // AudioManager.getAudioHwSyncForSession is not supported before S
        if (ApiLevelUtil.isAtMost(Build.VERSION_CODES.R)) {
            Log.i(TAG, "testGetAudioHwSyncForSession skipped, release: " + Build.VERSION.SDK_INT);
            return;
        }
        try {
            int sessionId = mAudioManager.generateAudioSessionId();
            assertNotEquals("testGetAudioHwSyncForSession cannot get audio session ID",
                    AudioManager.ERROR, sessionId);
            int hwSyncId = mAudioManager.getAudioHwSyncForSession(sessionId);
            Log.i(TAG, "getAudioHwSyncForSession: " + hwSyncId);
        } catch (UnsupportedOperationException e) {
            Log.i(TAG, "getAudioHwSyncForSession not supported");
        } catch (Exception e) {
            fail("Unexpected exception thrown by getAudioHwSyncForSession: " + e);
        }
    }

    private void setInterruptionFilter(int filter) {
        mNm.setInterruptionFilter(filter);
        final long startPoll = SystemClock.uptimeMillis();
        int currentFilter = -1;
        while (SystemClock.uptimeMillis() - startPoll < POLL_TIME_UPDATE_INTERRUPTION_FILTER) {
            currentFilter = mNm.getCurrentInterruptionFilter();
            if (currentFilter == filter) {
                return;
            }
        }
        Log.e(TAG, "interruption filter unsuccessfully set. wanted=" + filter
                + " actual=" + currentFilter);
    }

    private int getVolumeDelta(int volume) {
        return 1;
    }

    private int getTestRingerVol() {
        final int currentRingVol = mAudioManager.getStreamVolume(STREAM_RING);
        final int maxRingVol = mAudioManager.getStreamMaxVolume(STREAM_RING);
        if (currentRingVol != maxRingVol) {
            return maxRingVol;
        } else {
            return maxRingVol - 1;
        }
    }

    public void testAllowedCapturePolicy() throws Exception {
        final int policy = mAudioManager.getAllowedCapturePolicy();
        assertEquals("Wrong default capture policy", AudioAttributes.ALLOW_CAPTURE_BY_ALL, policy);

        for (int setPolicy : new int[] { AudioAttributes.ALLOW_CAPTURE_BY_NONE,
                                      AudioAttributes.ALLOW_CAPTURE_BY_SYSTEM,
                                      AudioAttributes.ALLOW_CAPTURE_BY_ALL}) {
            mAudioManager.setAllowedCapturePolicy(setPolicy);
            final int getPolicy = mAudioManager.getAllowedCapturePolicy();
            assertEquals("Allowed capture policy doesn't match", setPolicy, getPolicy);
        }
    }

    public void testIsHdmiSystemAudidoSupported() {
        // just make sure the call works
        boolean isSupported = mAudioManager.isHdmiSystemAudioSupported();
        Log.d(TAG, "isHdmiSystemAudioSupported() = " + isSupported);
    }

    public void testIsBluetoothScoAvailableOffCall() {
        // just make sure the call works
        boolean isSupported = mAudioManager.isBluetoothScoAvailableOffCall();
        Log.d(TAG, "isBluetoothScoAvailableOffCall() = " + isSupported);
    }

    public void testStartStopBluetoothSco() {
        mAudioManager.startBluetoothSco();
        mAudioManager.stopBluetoothSco();
    }

    public void testStartStopBluetoothScoVirtualCall() {
        mAudioManager.startBluetoothScoVirtualCall();
        mAudioManager.stopBluetoothSco();
    }

    public void testGetAdditionalOutputDeviceDelay() {
        AudioDeviceInfo[] devices = mAudioManager.getDevices(AudioManager.GET_DEVICES_ALL);
        for (AudioDeviceInfo device : devices) {
            long delay = mAudioManager.getAdditionalOutputDeviceDelay(device);
            assertTrue("getAdditionalOutputDeviceDelay() = " + delay +" (should be >= 0)",
                    delay >= 0);
            delay = mAudioManager.getMaxAdditionalOutputDeviceDelay(device);
            assertTrue("getMaxAdditionalOutputDeviceDelay() = " + delay +" (should be >= 0)",
                    delay >= 0);
        }
    }

    static class MyPrevDevForStrategyListener implements
            AudioManager.OnPreferredDevicesForStrategyChangedListener {
        @Override
        public void onPreferredDevicesForStrategyChanged(AudioProductStrategy strategy,
                List<AudioDeviceAttributes> devices) {
            fail("onPreferredDevicesForStrategyChanged must not be called");
        }
    }

    public void testPreferredDevicesForStrategy() {
        // setPreferredDeviceForStrategy
        AudioDeviceInfo[] devices = mAudioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
        if (devices.length <= 0) {
            Log.i(TAG, "Skip testPreferredDevicesForStrategy as there is no output device");
            return;
        }
        final AudioDeviceAttributes ada = new AudioDeviceAttributes(devices[0]);

        final AudioAttributes mediaAttr = new AudioAttributes.Builder().setUsage(
                AudioAttributes.USAGE_MEDIA).build();
        final List<AudioProductStrategy> strategies =
                AudioProductStrategy.getAudioProductStrategies();
        AudioProductStrategy strategyForMedia = null;
        for (AudioProductStrategy strategy : strategies) {
            if (strategy.supportsAudioAttributes(mediaAttr)) {
                strategyForMedia = strategy;
                break;
            }
        }
        if (strategyForMedia == null) {
            Log.i(TAG, "Skip testPreferredDevicesForStrategy as there is no strategy for media");
            return;
        }

        try {
            mAudioManager.setPreferredDeviceForStrategy(strategyForMedia, ada);
            fail("setPreferredDeviceForStrategy must fail due to no permission");
        } catch (SecurityException e) {
        }
        try {
            mAudioManager.getPreferredDeviceForStrategy(strategyForMedia);
            fail("getPreferredDeviceForStrategy must fail due to no permission");
        } catch (SecurityException e) {
        }
        final List<AudioDeviceAttributes> adas = new ArrayList<>();
        adas.add(ada);
        try {
            mAudioManager.setPreferredDevicesForStrategy(strategyForMedia, adas);
            fail("setPreferredDevicesForStrategy must fail due to no permission");
        } catch (SecurityException e) {
        }
        try {
            mAudioManager.getPreferredDevicesForStrategy(strategyForMedia);
            fail("getPreferredDevicesForStrategy must fail due to no permission");
        } catch (SecurityException e) {
        }
        MyPrevDevForStrategyListener listener = new MyPrevDevForStrategyListener();
        try {
            mAudioManager.addOnPreferredDevicesForStrategyChangedListener(
                    Executors.newSingleThreadExecutor(), listener);
            fail("addOnPreferredDevicesForStrategyChangedListener must fail due to no permission");
        } catch (SecurityException e) {
        }
        // There is not listener added at server side. Nothing to remove.
        mAudioManager.removeOnPreferredDevicesForStrategyChangedListener(listener);
    }

    static class MyPrevDevicesForCapturePresetChangedListener implements
            AudioManager.OnPreferredDevicesForCapturePresetChangedListener {
        @Override
        public void onPreferredDevicesForCapturePresetChanged(
                int capturePreset, List<AudioDeviceAttributes> devices) {
            fail("onPreferredDevicesForCapturePresetChanged must not be called");
        }
    }

    public void testPreferredDeviceForCapturePreset() {
        AudioDeviceInfo[] devices = mAudioManager.getDevices(AudioManager.GET_DEVICES_INPUTS);
        if (devices.length <= 0) {
            Log.i(TAG, "Skip testPreferredDevicesForStrategy as there is no input device");
            return;
        }
        final AudioDeviceAttributes ada = new AudioDeviceAttributes(devices[0]);

        try {
            mAudioManager.setPreferredDeviceForCapturePreset(MediaRecorder.AudioSource.MIC, ada);
            fail("setPreferredDeviceForCapturePreset must fail due to no permission");
        } catch (SecurityException e) {
        }
        try {
            mAudioManager.getPreferredDevicesForCapturePreset(MediaRecorder.AudioSource.MIC);
            fail("getPreferredDevicesForCapturePreset must fail due to no permission");
        } catch (SecurityException e) {
        }
        try {
            mAudioManager.clearPreferredDevicesForCapturePreset(MediaRecorder.AudioSource.MIC);
            fail("clearPreferredDevicesForCapturePreset must fail due to no permission");
        } catch (SecurityException e) {
        }
        MyPrevDevicesForCapturePresetChangedListener listener =
                new MyPrevDevicesForCapturePresetChangedListener();
        try {
            mAudioManager.addOnPreferredDevicesForCapturePresetChangedListener(
                Executors.newSingleThreadExecutor(), listener);
            fail("addOnPreferredDevicesForCapturePresetChangedListener must fail"
                    + "due to no permission");
        } catch (SecurityException e) {
        }
        // There is not listener added at server side. Nothing to remove.
        mAudioManager.removeOnPreferredDevicesForCapturePresetChangedListener(listener);
    }

    public void testGetDevices() {
        AudioDeviceInfo[] devices = mAudioManager.getDevices(AudioManager.GET_DEVICES_ALL);
        for (AudioDeviceInfo device : devices) {
            HashSet<Integer> formats = IntStream.of(device.getEncodings()).boxed()
                    .collect(Collectors.toCollection(HashSet::new));
            HashSet<Integer> channelMasks = IntStream.of(device.getChannelMasks()).boxed()
                    .collect(Collectors.toCollection(HashSet::new));
            HashSet<Integer> channelIndexMasks = IntStream.of(device.getChannelIndexMasks()).boxed()
                    .collect(Collectors.toCollection(HashSet::new));
            HashSet<Integer> sampleRates = IntStream.of(device.getSampleRates()).boxed()
                    .collect(Collectors.toCollection(HashSet::new));
            HashSet<Integer> formatsFromProfile = new HashSet<>();
            HashSet<Integer> channelMasksFromProfile = new HashSet<>();
            HashSet<Integer> channelIndexMasksFromProfile = new HashSet<>();
            HashSet<Integer> sampleRatesFromProfile = new HashSet<>();
            for (AudioProfile profile : device.getAudioProfiles()) {
                formatsFromProfile.add(profile.getFormat());
                channelMasksFromProfile.addAll(Arrays.stream(profile.getChannelMasks()).boxed()
                        .collect(Collectors.toList()));
                channelIndexMasksFromProfile.addAll(Arrays.stream(profile.getChannelIndexMasks())
                        .boxed().collect(Collectors.toList()));
                sampleRatesFromProfile.addAll(Arrays.stream(profile.getSampleRates()).boxed()
                        .collect(Collectors.toList()));
                assertTrue(ALL_ENCAPSULATION_TYPES.contains(profile.getEncapsulationType()));
            }
            for (AudioDescriptor descriptor : device.getAudioDescriptors()) {
                assertNotEquals(AudioDescriptor.STANDARD_NONE, descriptor.getStandard());
                assertNotNull(descriptor.getDescriptor());
                assertTrue(
                        ALL_KNOWN_ENCAPSULATION_TYPES.contains(descriptor.getEncapsulationType()));
            }
            assertEquals(formats, formatsFromProfile);
            assertEquals(channelMasks, channelMasksFromProfile);
            assertEquals(channelIndexMasks, channelIndexMasksFromProfile);
            assertEquals(sampleRates, sampleRatesFromProfile);
        }
    }

    public void testGetDirectPlaybackSupport() {
        assertEquals(AudioManager.DIRECT_PLAYBACK_NOT_SUPPORTED,
                AudioManager.getDirectPlaybackSupport(
                        new AudioFormat.Builder().build(),
                        new AudioAttributes.Builder().build()));
        AudioDeviceInfo[] devices = mAudioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
        AudioAttributes attr = new AudioAttributes.Builder()
                .setUsage(AudioAttributes.USAGE_MEDIA)
                .setLegacyStreamType(STREAM_MUSIC).build();
        for (AudioDeviceInfo device : devices) {
            for (int encoding : device.getEncodings()) {
                for (int channelMask : device.getChannelMasks()) {
                    for (int sampleRate : device.getSampleRates()) {
                        AudioFormat format = new AudioFormat.Builder()
                                .setEncoding(encoding)
                                .setChannelMask(channelMask)
                                .setSampleRate(sampleRate).build();
                        final int directPlaybackSupport =
                                AudioManager.getDirectPlaybackSupport(format, attr);
                        assertEquals(
                                AudioTrack.isDirectPlaybackSupported(format, attr),
                                directPlaybackSupport
                                        != AudioManager.DIRECT_PLAYBACK_NOT_SUPPORTED);
                        if (directPlaybackSupport == AudioManager.DIRECT_PLAYBACK_NOT_SUPPORTED) {
                            assertEquals(
                                    DIRECT_OFFLOAD_MAP.getOrDefault(
                                            AudioManager.getPlaybackOffloadSupport(format, attr),
                                            INVALID_DIRECT_PLAYBACK_MODE).intValue(),
                                    directPlaybackSupport);
                        } else if ((directPlaybackSupport
                                & AudioManager.DIRECT_PLAYBACK_OFFLOAD_SUPPORTED)
                                != AudioManager.DIRECT_PLAYBACK_NOT_SUPPORTED) {
                            // AudioManager.getPlaybackOffloadSupport can only query offload
                            // support but not other direct support like passthrough.
                            assertNotEquals(
                                    AudioManager.DIRECT_PLAYBACK_NOT_SUPPORTED,
                                    DIRECT_OFFLOAD_MAP.getOrDefault(
                                            AudioManager.getPlaybackOffloadSupport(format, attr),
                                            AudioManager.DIRECT_PLAYBACK_NOT_SUPPORTED)
                                            & directPlaybackSupport);
                        }
                    }
                }
            }
        }
    }

    public void testAssistantUidRouting() {
        try {
            mAudioManager.addAssistantServicesUids(new int[0]);
            fail("addAssistantServicesUids must fail due to no permission");
        } catch (SecurityException e) {
        }

        try {
            mAudioManager.removeAssistantServicesUids(new int[0]);
            fail("removeAssistantServicesUids must fail due to no permission");
        } catch (SecurityException e) {
        }

        try {
            int[] uids = mAudioManager.getAssistantServicesUids();
            fail("getAssistantServicesUids must fail due to no permission");
        } catch (SecurityException e) {
        }

        try {
            mAudioManager.setActiveAssistantServiceUids(new int[0]);
            fail("setActiveAssistantServiceUids must fail due to no permission");
        } catch (SecurityException e) {
        }

        try {
            int[] activeUids = mAudioManager.getActiveAssistantServicesUids();
            fail("getActiveAssistantServicesUids must fail due to no permission");
        } catch (SecurityException e) {
        }
    }

    public void testGetHalVersion() {
        assertNotEquals(null, AudioManager.getHalVersion());
    }

    private void assertStreamVolumeEquals(int stream, int expectedVolume) throws Exception {
        assertStreamVolumeEquals(stream, expectedVolume,
                "Unexpected stream volume for stream=" + stream);
    }

    // volume adjustments are asynchronous, we poll the volume in case the volume state hasn't
    // been adjusted yet
    private void assertStreamVolumeEquals(int stream, int expectedVolume, String msg)
            throws Exception {
        final long startPoll = SystemClock.uptimeMillis();
        int actualVolume = mAudioManager.getStreamVolume(stream);
        while (SystemClock.uptimeMillis() - startPoll < POLL_TIME_VOLUME_ADJUST
                && expectedVolume != actualVolume) {
            actualVolume = mAudioManager.getStreamVolume(stream);
        }
        assertEquals(msg, expectedVolume, actualVolume);
    }

    // volume adjustments are asynchronous, we poll the volume in case the mute state hasn't
    // changed yet
    private void assertStreamMuted(int stream, boolean expectedMuteState, String msg)
            throws Exception{
        final long startPoll = SystemClock.uptimeMillis();
        boolean actualMuteState = mAudioManager.isStreamMute(stream);
        while (SystemClock.uptimeMillis() - startPoll < POLL_TIME_VOLUME_ADJUST
                && expectedMuteState != actualMuteState) {
            actualMuteState = mAudioManager.isStreamMute(stream);
        }
        assertEquals(msg, expectedMuteState, actualMuteState);
    }

    private void assertMusicActive(boolean expectedIsMusicActive) throws Exception {
        final long startPoll = SystemClock.uptimeMillis();
        boolean actualIsMusicActive = mAudioManager.isMusicActive();
        while (SystemClock.uptimeMillis() - startPoll < POLL_TIME_PLAY_MUSIC
                && expectedIsMusicActive != actualIsMusicActive) {
            actualIsMusicActive = mAudioManager.isMusicActive();
        }
        assertEquals(actualIsMusicActive, actualIsMusicActive);
    }

    private static final long REPEATED_CHECK_POLL_PERIOD_MS = 100; // 100ms
    private static final long DEFAULT_ASYNC_CALL_TIMEOUT_MS = 5 * REPEATED_CHECK_POLL_PERIOD_MS;

    /**
     * Makes multiple attempts over a given timeout period to test the predicate on an AudioManager
     * instance. Test success is evaluated against a true predicate result.
     * @param am the AudioManager instance to use for the test
     * @param predicate the test to run either until it returns true, or until the timeout expires
     * @param timeoutMs the maximum time allowed for the test to pass
     * @param errorString the string to be displayed in case of failure
     * @throws Exception
     */
    private void assertTrueCheckTimeout(AudioManager am, Predicate<AudioManager> predicate,
            long timeoutMs, String errorString) throws Exception {
        long checkStart = SystemClock.uptimeMillis();
        boolean result = false;
        while (SystemClock.uptimeMillis() - checkStart < timeoutMs) {
            result = predicate.test(am);
            if (result) {
                break;
            }
            Thread.sleep(REPEATED_CHECK_POLL_PERIOD_MS);
        }
        assertTrue(errorString, result);
    }

    private boolean isAutomotive() {
        PackageManager pm = mContext.getPackageManager();
        return pm.hasSystemFeature(pm.FEATURE_AUTOMOTIVE);
    }

    // getParameters() & setParameters() are deprecated, so don't test

    // setAdditionalOutputDeviceDelay(), getAudioVolumeGroups(), getVolumeIndexForAttributes()
    // getMinVolumeIndexForAttributes(), getMaxVolumeIndexForAttributes() &
    // setVolumeIndexForAttributes() require privledged permission MODIFY_AUDIO_ROUTING
    // and thus cannot be tested here.
}
