• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertNotEquals;
21 import static org.testng.Assert.assertThrows;
22 
23 import android.media.AudioAttributes;
24 import android.media.AudioManager;
25 import android.media.AudioSystem;
26 import android.media.audiopolicy.AudioProductStrategy;
27 import android.media.audiopolicy.AudioVolumeGroup;
28 import android.util.Log;
29 
30 import com.google.common.primitives.Ints;
31 
32 import java.util.List;
33 
34 public class AudioManagerTest extends AudioVolumesTestBase {
35     private static final String TAG = "AudioManagerTest";
36 
37     //-----------------------------------------------------------------
38     // Test getAudioProductStrategies and validate strategies
39     //-----------------------------------------------------------------
testGetAndValidateProductStrategies()40     public void testGetAndValidateProductStrategies() throws Exception {
41         List<AudioProductStrategy> audioProductStrategies =
42                 mAudioManager.getAudioProductStrategies();
43         assertTrue(audioProductStrategies.size() > 0);
44 
45         List<AudioVolumeGroup> audioVolumeGroups = mAudioManager.getAudioVolumeGroups();
46         assertTrue(audioVolumeGroups.size() > 0);
47 
48         // Validate Audio Product Strategies
49         for (final AudioProductStrategy audioProductStrategy : audioProductStrategies) {
50             AudioAttributes attributes = audioProductStrategy.getAudioAttributes();
51             int strategyStreamType =
52                     audioProductStrategy.getLegacyStreamTypeForAudioAttributes(attributes);
53 
54             assertTrue("Strategy shall support the attributes retrieved from its getter API",
55                     audioProductStrategy.supportsAudioAttributes(attributes));
56 
57             int volumeGroupId =
58                     audioProductStrategy.getVolumeGroupIdForAudioAttributes(attributes);
59 
60             // A strategy must be associated to a volume group
61             assertNotEquals("strategy not assigned to any volume group",
62                     volumeGroupId, AudioVolumeGroup.DEFAULT_VOLUME_GROUP);
63 
64             // Valid Group ?
65             AudioVolumeGroup audioVolumeGroup = null;
66             for (final AudioVolumeGroup avg : audioVolumeGroups) {
67                 if (avg.getId() == volumeGroupId) {
68                     audioVolumeGroup = avg;
69                     break;
70                 }
71             }
72             assertNotNull("Volume Group not found", audioVolumeGroup);
73 
74             // Cross check: the group shall have at least one aa / stream types following the
75             // considered strategy
76             boolean strategyAttributesSupported = false;
77             for (final AudioAttributes aa : audioVolumeGroup.getAudioAttributes()) {
78                 if (audioProductStrategy.supportsAudioAttributes(aa)) {
79                     strategyAttributesSupported = true;
80                     break;
81                 }
82             }
83             assertTrue("Volume Group and Strategy mismatching", strategyAttributesSupported);
84 
85             // Some Product strategy may not have corresponding stream types as they intends
86             // to address volume setting per attributes to avoid adding new stream type
87             // and going on deprecating the stream type even for volume
88             if (strategyStreamType != AudioSystem.STREAM_DEFAULT) {
89                 boolean strategStreamTypeSupported = false;
90                 for (final int vgStreamType : audioVolumeGroup.getLegacyStreamTypes()) {
91                     if (vgStreamType == strategyStreamType) {
92                         strategStreamTypeSupported = true;
93                         break;
94                     }
95                 }
96                 assertTrue("Volume Group and Strategy mismatching", strategStreamTypeSupported);
97             }
98         }
99     }
100 
101     //-----------------------------------------------------------------
102     // Test getAudioVolumeGroups and validate volume groups
103     //-----------------------------------------------------------------
104 
testGetAndValidateVolumeGroups()105     public void testGetAndValidateVolumeGroups() throws Exception {
106         List<AudioVolumeGroup> audioVolumeGroups = mAudioManager.getAudioVolumeGroups();
107         assertTrue(audioVolumeGroups.size() > 0);
108 
109         List<AudioProductStrategy> audioProductStrategies =
110                 mAudioManager.getAudioProductStrategies();
111         assertTrue(audioProductStrategies.size() > 0);
112 
113         // Validate Audio Volume Groups, check all
114         for (final AudioVolumeGroup audioVolumeGroup : audioVolumeGroups) {
115             List<AudioAttributes> avgAttributes = audioVolumeGroup.getAudioAttributes();
116             int[] avgStreamTypes = audioVolumeGroup.getLegacyStreamTypes();
117 
118             // for each volume group attributes, find the matching product strategy and ensure
119             // it is linked the considered volume group
120             for (final AudioAttributes aa : avgAttributes) {
121                 if (aa.equals(sDefaultAttributes)) {
122                     // Some volume groups may not have valid attributes, used for internal
123                     // volume management like patch/rerouting
124                     // so bailing out strategy retrieval from attributes
125                     continue;
126                 }
127                 boolean isVolumeGroupAssociatedToStrategy = false;
128                 for (final AudioProductStrategy strategy : audioProductStrategies) {
129                     int groupId = strategy.getVolumeGroupIdForAudioAttributes(aa);
130                     if (groupId != AudioVolumeGroup.DEFAULT_VOLUME_GROUP) {
131 
132                         assertEquals("Volume Group ID (" + audioVolumeGroup.toString()
133                                 + "), and Volume group ID associated to Strategy ("
134                                 + strategy.toString() + ") both supporting attributes "
135                                 + aa.toString() + " are mismatching",
136                                 audioVolumeGroup.getId(), groupId);
137                         isVolumeGroupAssociatedToStrategy = true;
138                         break;
139                     }
140                 }
141                 assertTrue("Volume Group (" + audioVolumeGroup.toString()
142                         + ") has no associated strategy for attributes " + aa.toString(),
143                         isVolumeGroupAssociatedToStrategy);
144             }
145 
146             // for each volume group stream type, find the matching product strategy and ensure
147             // it is linked the considered volume group
148             for (final int avgStreamType : avgStreamTypes) {
149                 if (avgStreamType == AudioSystem.STREAM_DEFAULT) {
150                     // Some Volume Groups may not have corresponding stream types as they
151                     // intends to address volume setting per attributes to avoid adding new
152                     //  stream type and going on deprecating the stream type even for volume
153                     // so bailing out strategy retrieval from stream type
154                     continue;
155                 }
156                 boolean isVolumeGroupAssociatedToStrategy = false;
157                 for (final AudioProductStrategy strategy : audioProductStrategies) {
158                     Log.i(TAG, "strategy:" + strategy.toString());
159                     int groupId = strategy.getVolumeGroupIdForLegacyStreamType(avgStreamType);
160                     if (groupId != AudioVolumeGroup.DEFAULT_VOLUME_GROUP) {
161 
162                         assertEquals("Volume Group ID (" + audioVolumeGroup.toString()
163                                 + "), and Volume group ID associated to Strategy ("
164                                 + strategy.toString() + ") both supporting stream "
165                                 + AudioSystem.streamToString(avgStreamType) + "("
166                                 + avgStreamType + ") are mismatching",
167                                 audioVolumeGroup.getId(), groupId);
168                         isVolumeGroupAssociatedToStrategy = true;
169                         break;
170                     }
171                 }
172                 assertTrue("Volume Group (" + audioVolumeGroup.toString()
173                         + ") has no associated strategy for stream "
174                         + AudioSystem.streamToString(avgStreamType) + "(" + avgStreamType + ")",
175                         isVolumeGroupAssociatedToStrategy);
176             }
177         }
178     }
179 
180     //-----------------------------------------------------------------
181     // Test Volume per Attributes setter/getters
182     //-----------------------------------------------------------------
testSetGetVolumePerAttributesWithInvalidAttributes()183     public void testSetGetVolumePerAttributesWithInvalidAttributes() throws Exception {
184         AudioAttributes nullAttributes = null;
185 
186         assertThrows(NullPointerException.class,
187                 () -> mAudioManager.getMaxVolumeIndexForAttributes(nullAttributes));
188 
189         assertThrows(NullPointerException.class,
190                 () -> mAudioManager.getMinVolumeIndexForAttributes(nullAttributes));
191 
192         assertThrows(NullPointerException.class,
193                 () -> mAudioManager.getVolumeIndexForAttributes(nullAttributes));
194 
195         assertThrows(NullPointerException.class,
196                 () -> mAudioManager.setVolumeIndexForAttributes(
197                         nullAttributes, 0 /*index*/, 0/*flags*/));
198     }
199 
testSetGetVolumePerAttributes()200     public void testSetGetVolumePerAttributes() throws Exception {
201         for (int usage : AudioAttributes.SDK_USAGES) {
202             if (usage == AudioAttributes.USAGE_UNKNOWN) {
203                 continue;
204             }
205             AudioAttributes aaForUsage = new AudioAttributes.Builder().setUsage(usage).build();
206             int indexMin = 0;
207             int indexMax = 0;
208             int index = 0;
209             Exception ex = null;
210 
211             try {
212                 indexMax = mAudioManager.getMaxVolumeIndexForAttributes(aaForUsage);
213             } catch (Exception e) {
214                 ex = e; // unexpected
215             }
216             assertNull("Exception was thrown for valid attributes", ex);
217             ex = null;
218             try {
219                 indexMin = mAudioManager.getMinVolumeIndexForAttributes(aaForUsage);
220             } catch (Exception e) {
221                 ex = e; // unexpected
222             }
223             assertNull("Exception was thrown for valid attributes", ex);
224             ex = null;
225             try {
226                 index = mAudioManager.getVolumeIndexForAttributes(aaForUsage);
227             } catch (Exception e) {
228                 ex = e; // unexpected
229             }
230             assertNull("Exception was thrown for valid attributes", ex);
231             ex = null;
232             try {
233                 mAudioManager.setVolumeIndexForAttributes(aaForUsage, indexMin, 0/*flags*/);
234             } catch (Exception e) {
235                 ex = e; // unexpected
236             }
237             assertNull("Exception was thrown for valid attributes", ex);
238 
239             index = mAudioManager.getVolumeIndexForAttributes(aaForUsage);
240             assertEquals(index, indexMin);
241 
242             mAudioManager.setVolumeIndexForAttributes(aaForUsage, indexMax, 0/*flags*/);
243             index = mAudioManager.getVolumeIndexForAttributes(aaForUsage);
244             assertEquals(index, indexMax);
245         }
246     }
247 
248     //-----------------------------------------------------------------
249     // Test register/unregister VolumeGroupCallback
250     //-----------------------------------------------------------------
testVolumeGroupCallback()251     public void testVolumeGroupCallback() throws Exception {
252         List<AudioVolumeGroup> audioVolumeGroups = mAudioManager.getAudioVolumeGroups();
253         assertTrue(audioVolumeGroups.size() > 0);
254 
255         AudioVolumeGroupCallbackHelper vgCbReceiver = new AudioVolumeGroupCallbackHelper();
256         mAudioManager.registerVolumeGroupCallback(mContext.getMainExecutor(), vgCbReceiver);
257 
258         final List<Integer> publicStreams = Ints.asList(AudioManager.getPublicStreamTypes());
259         try {
260             // Validate Audio Volume Groups callback reception
261             for (final AudioVolumeGroup audioVolumeGroup : audioVolumeGroups) {
262                 int volumeGroupId = audioVolumeGroup.getId();
263 
264                 // Set the receiver to filter only the current group callback
265                 vgCbReceiver.setExpectedVolumeGroup(volumeGroupId);
266 
267                 List<AudioAttributes> avgAttributes = audioVolumeGroup.getAudioAttributes();
268                 int[] avgStreamTypes = audioVolumeGroup.getLegacyStreamTypes();
269 
270                 int index = 0;
271                 int indexMax = 0;
272                 int indexMin = 0;
273 
274                 // Set the volume per attributes (if valid) and wait the callback
275                 for (final AudioAttributes aa : avgAttributes) {
276                     if (aa.equals(sDefaultAttributes)) {
277                         // Some volume groups may not have valid attributes, used for internal
278                         // volume management like patch/rerouting
279                         // so bailing out strategy retrieval from attributes
280                         continue;
281                     }
282                     index = mAudioManager.getVolumeIndexForAttributes(aa);
283                     indexMax = mAudioManager.getMaxVolumeIndexForAttributes(aa);
284                     indexMin = mAudioManager.getMinVolumeIndexForAttributes(aa);
285                     index = incrementVolumeIndex(index, indexMin, indexMax);
286 
287                     vgCbReceiver.setExpectedVolumeGroup(volumeGroupId);
288                     mAudioManager.setVolumeIndexForAttributes(aa, index, 0/*flags*/);
289                     assertTrue(vgCbReceiver.waitForExpectedVolumeGroupChanged(
290                             AudioVolumeGroupCallbackHelper.ASYNC_TIMEOUT_MS));
291 
292                     int readIndex = mAudioManager.getVolumeIndexForAttributes(aa);
293                     assertEquals(readIndex, index);
294                 }
295                 // Set the volume per stream type (if valid) and wait the callback
296                 for (final int avgStreamType : avgStreamTypes) {
297                     if (avgStreamType == AudioSystem.STREAM_DEFAULT) {
298                         // Some Volume Groups may not have corresponding stream types as they
299                         // intends to address volume setting per attributes to avoid adding new
300                         // stream type and going on deprecating the stream type even for volume
301                         // so bailing out strategy retrieval from stream type
302                         continue;
303                     }
304                     if (!publicStreams.contains(avgStreamType)
305                             || avgStreamType == AudioManager.STREAM_ACCESSIBILITY) {
306                         // Limit scope of test to public stream that do not require any
307                         // permission (e.g. Changing ACCESSIBILITY is subject to permission).
308                         continue;
309                     }
310                     index = mAudioManager.getStreamVolume(avgStreamType);
311                     indexMax = mAudioManager.getStreamMaxVolume(avgStreamType);
312                     indexMin = mAudioManager.getStreamMinVolumeInt(avgStreamType);
313                     index = incrementVolumeIndex(index, indexMin, indexMax);
314 
315                     vgCbReceiver.setExpectedVolumeGroup(volumeGroupId);
316                     mAudioManager.setStreamVolume(avgStreamType, index, 0/*flags*/);
317                     assertTrue(vgCbReceiver.waitForExpectedVolumeGroupChanged(
318                             AudioVolumeGroupCallbackHelper.ASYNC_TIMEOUT_MS));
319 
320                     int readIndex = mAudioManager.getStreamVolume(avgStreamType);
321                     assertEquals(index, readIndex);
322                 }
323             }
324         } finally {
325             mAudioManager.unregisterVolumeGroupCallback(vgCbReceiver);
326         }
327     }
328 }
329