1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.audiopolicytest; 18 19 import static androidx.test.core.app.ApplicationProvider.getApplicationContext; 20 21 import static com.android.audiopolicytest.AudioVolumeTestUtil.DEFAULT_ATTRIBUTES; 22 23 import static org.junit.Assert.assertEquals; 24 import static org.junit.Assert.assertTrue; 25 26 import android.content.Context; 27 import android.content.pm.PackageManager; 28 import android.media.AudioAttributes; 29 import android.media.AudioManager; 30 import android.media.audiopolicy.AudioProductStrategy; 31 import android.media.audiopolicy.AudioVolumeGroup; 32 33 import androidx.test.core.app.ActivityScenario; 34 35 import org.junit.After; 36 import org.junit.Before; 37 import org.junit.rules.ExternalResource; 38 39 import java.util.HashMap; 40 import java.util.List; 41 import java.util.Map; 42 43 final class AudioVolumesTestRule extends ExternalResource { 44 private AudioManager mAudioManager; 45 private Context mContext; 46 private Map<Integer, Integer> mOriginalStreamVolumes = new HashMap<>(); 47 private Map<Integer, Integer> mOriginalVolumeGroupVolumes = new HashMap<>(); 48 49 /** 50 * <p>Note: must be called with shell permission (MODIFY_AUDIO_ROUTING) 51 */ storeAllVolumes()52 private void storeAllVolumes() { 53 List<AudioVolumeGroup> audioVolumeGroups = mAudioManager.getAudioVolumeGroups(); 54 for (final AudioVolumeGroup avg : audioVolumeGroups) { 55 if (avg.getAudioAttributes().isEmpty()) { 56 // some volume group may not supports volume control per attributes 57 // like rerouting/patch since these groups are internal to audio policy manager 58 continue; 59 } 60 AudioAttributes avgAttributes = DEFAULT_ATTRIBUTES; 61 for (final AudioAttributes aa : avg.getAudioAttributes()) { 62 if (!aa.equals(AudioProductStrategy.getDefaultAttributes())) { 63 avgAttributes = aa; 64 break; 65 } 66 } 67 if (avgAttributes.equals(DEFAULT_ATTRIBUTES)) { 68 // This shall not happen, however, not purpose of this base class. 69 // so bailing out. 70 continue; 71 } 72 mOriginalVolumeGroupVolumes.put( 73 avg.getId(), mAudioManager.getVolumeIndexForAttributes(avgAttributes)); 74 } 75 } 76 77 /** 78 * <p>Note: must be called with shell permission (MODIFY_AUDIO_ROUTING) 79 */ restoreAllVolumes()80 private void restoreAllVolumes() { 81 List<AudioVolumeGroup> audioVolumeGroups = mAudioManager.getAudioVolumeGroups(); 82 for (Map.Entry<Integer, Integer> e : mOriginalVolumeGroupVolumes.entrySet()) { 83 for (final AudioVolumeGroup avg : audioVolumeGroups) { 84 if (avg.getId() == e.getKey()) { 85 assertTrue(!avg.getAudioAttributes().isEmpty()); 86 AudioAttributes avgAttributes = DEFAULT_ATTRIBUTES; 87 for (final AudioAttributes aa : avg.getAudioAttributes()) { 88 if (!aa.equals(AudioProductStrategy.getDefaultAttributes())) { 89 avgAttributes = aa; 90 break; 91 } 92 } 93 assertTrue(!avgAttributes.equals(DEFAULT_ATTRIBUTES)); 94 mAudioManager.setVolumeIndexForAttributes( 95 avgAttributes, e.getValue(), AudioManager.FLAG_ALLOW_RINGER_MODES); 96 } 97 } 98 } 99 } 100 101 @Before setUp()102 public void setUp() throws Exception { 103 ActivityScenario.launch(AudioVolumeTestActivity.class); 104 105 mContext = getApplicationContext(); 106 mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); 107 108 assertEquals(PackageManager.PERMISSION_GRANTED, 109 mContext.checkSelfPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)); 110 111 // Store the original volumes that that they can be recovered in tearDown(). 112 mOriginalStreamVolumes.clear(); 113 for (int streamType : AudioManager.getPublicStreamTypes()) { 114 mOriginalStreamVolumes.put(streamType, mAudioManager.getStreamVolume(streamType)); 115 } 116 // Store the original volume per attributes so that they can be recovered in tearDown() 117 mOriginalVolumeGroupVolumes.clear(); 118 storeAllVolumes(); 119 } 120 121 @After tearDown()122 public void tearDown() throws Exception { 123 // Recover the volume and the ringer mode that the test may have overwritten. 124 for (Map.Entry<Integer, Integer> e : mOriginalStreamVolumes.entrySet()) { 125 mAudioManager.setStreamVolume(e.getKey(), e.getValue(), 126 AudioManager.FLAG_ALLOW_RINGER_MODES); 127 } 128 129 // Recover the original volume per attributes 130 restoreAllVolumes(); 131 } 132 133 134 } 135