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