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 android.content.Context; 20 import android.content.pm.PackageManager; 21 import android.media.AudioAttributes; 22 import android.media.AudioManager; 23 import android.media.audiopolicy.AudioProductStrategy; 24 import android.media.audiopolicy.AudioVolumeGroup; 25 import android.test.ActivityInstrumentationTestCase2; 26 27 import java.util.HashMap; 28 import java.util.List; 29 import java.util.Map; 30 31 public class AudioVolumesTestBase extends ActivityInstrumentationTestCase2<AudioPolicyTest> { 32 public AudioManager mAudioManager; 33 Context mContext; 34 private Map<Integer, Integer> mOriginalStreamVolumes = new HashMap<>(); 35 private Map<Integer, Integer> mOriginalVolumeGroupVolumes = new HashMap<>(); 36 37 // Default matches the invalid (empty) attributes from native. 38 // The difference is the input source default which is not aligned between native and java 39 public static final AudioAttributes sDefaultAttributes = 40 AudioProductStrategy.sDefaultAttributes; 41 42 public static final AudioAttributes sInvalidAttributes = new AudioAttributes.Builder().build(); 43 44 public final int[] PUBLIC_STREAM_TYPES = { AudioManager.STREAM_VOICE_CALL, 45 AudioManager.STREAM_SYSTEM, AudioManager.STREAM_RING, AudioManager.STREAM_MUSIC, 46 AudioManager.STREAM_ALARM, AudioManager.STREAM_NOTIFICATION, 47 AudioManager.STREAM_DTMF, AudioManager.STREAM_ACCESSIBILITY }; 48 AudioVolumesTestBase()49 public AudioVolumesTestBase() { 50 super("com.android.audiopolicytest", AudioPolicyTest.class); 51 } 52 53 /** 54 * <p>Note: must be called with shell permission (MODIFY_AUDIO_ROUTING) 55 */ storeAllVolumes()56 private void storeAllVolumes() { 57 List<AudioVolumeGroup> audioVolumeGroups = mAudioManager.getAudioVolumeGroups(); 58 for (final AudioVolumeGroup avg : audioVolumeGroups) { 59 if (avg.getAudioAttributes().isEmpty()) { 60 // some volume group may not supports volume control per attributes 61 // like rerouting/patch since these groups are internal to audio policy manager 62 continue; 63 } 64 AudioAttributes avgAttributes = sDefaultAttributes; 65 for (final AudioAttributes aa : avg.getAudioAttributes()) { 66 if (!aa.equals(AudioProductStrategy.sDefaultAttributes)) { 67 avgAttributes = aa; 68 break; 69 } 70 } 71 if (avgAttributes.equals(sDefaultAttributes)) { 72 // This shall not happen, however, not purpose of this base class. 73 // so bailing out. 74 continue; 75 } 76 mOriginalVolumeGroupVolumes.put( 77 avg.getId(), mAudioManager.getVolumeIndexForAttributes(avgAttributes)); 78 } 79 } 80 81 /** 82 * <p>Note: must be called with shell permission (MODIFY_AUDIO_ROUTING) 83 */ restoreAllVolumes()84 private void restoreAllVolumes() { 85 List<AudioVolumeGroup> audioVolumeGroups = mAudioManager.getAudioVolumeGroups(); 86 for (Map.Entry<Integer, Integer> e : mOriginalVolumeGroupVolumes.entrySet()) { 87 for (final AudioVolumeGroup avg : audioVolumeGroups) { 88 if (avg.getId() == e.getKey()) { 89 assertTrue(!avg.getAudioAttributes().isEmpty()); 90 AudioAttributes avgAttributes = sDefaultAttributes; 91 for (final AudioAttributes aa : avg.getAudioAttributes()) { 92 if (!aa.equals(AudioProductStrategy.sDefaultAttributes)) { 93 avgAttributes = aa; 94 break; 95 } 96 } 97 assertTrue(!avgAttributes.equals(sDefaultAttributes)); 98 mAudioManager.setVolumeIndexForAttributes( 99 avgAttributes, e.getValue(), AudioManager.FLAG_ALLOW_RINGER_MODES); 100 } 101 } 102 } 103 } 104 105 @Override setUp()106 protected void setUp() throws Exception { 107 super.setUp(); 108 109 mContext = getActivity(); 110 mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); 111 112 assertEquals(PackageManager.PERMISSION_GRANTED, 113 mContext.checkSelfPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)); 114 115 // Store the original volumes that that they can be recovered in tearDown(). 116 mOriginalStreamVolumes.clear(); 117 for (int streamType : PUBLIC_STREAM_TYPES) { 118 mOriginalStreamVolumes.put(streamType, mAudioManager.getStreamVolume(streamType)); 119 } 120 // Store the original volume per attributes so that they can be recovered in tearDown() 121 mOriginalVolumeGroupVolumes.clear(); 122 storeAllVolumes(); 123 } 124 125 @Override tearDown()126 protected void tearDown() throws Exception { 127 super.tearDown(); 128 129 // Recover the volume and the ringer mode that the test may have overwritten. 130 for (Map.Entry<Integer, Integer> e : mOriginalStreamVolumes.entrySet()) { 131 mAudioManager.setStreamVolume(e.getKey(), e.getValue(), 132 AudioManager.FLAG_ALLOW_RINGER_MODES); 133 } 134 135 // Recover the original volume per attributes 136 restoreAllVolumes(); 137 } 138 resetVolumeIndex(int indexMin, int indexMax)139 public static int resetVolumeIndex(int indexMin, int indexMax) { 140 return (indexMax + indexMin) / 2; 141 } 142 incrementVolumeIndex(int index, int indexMin, int indexMax)143 public static int incrementVolumeIndex(int index, int indexMin, int indexMax) { 144 return (index + 1 > indexMax) ? resetVolumeIndex(indexMin, indexMax) : ++index; 145 } 146 } 147