• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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.car.audio;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import static org.mockito.Mockito.verify;
22 import static org.mockito.Mockito.when;
23 import static org.testng.Assert.expectThrows;
24 
25 import android.annotation.UserIdInt;
26 import android.os.UserHandle;
27 import android.util.SparseBooleanArray;
28 import android.util.SparseIntArray;
29 
30 import org.junit.Before;
31 import org.junit.Test;
32 import org.junit.runner.RunWith;
33 import org.mockito.Mock;
34 import org.mockito.Mockito;
35 import org.mockito.junit.MockitoJUnitRunner;
36 
37 import java.util.List;
38 
39 @RunWith(MockitoJUnitRunner.class)
40 public class CarVolumeGroupUnitTest {
41     private static final int ZONE_ID = 0;
42     private static final int GROUP_ID = 0;
43     private static final int STEP_VALUE = 2;
44     private static final int MIN_GAIN = 3;
45     private static final int MAX_GAIN = 10;
46     private static final int DEFAULT_GAIN = 5;
47     private static final int DEFAULT_GAIN_INDEX = (DEFAULT_GAIN - MIN_GAIN) / STEP_VALUE;
48     private static final int MIN_GAIN_INDEX = 0;
49     private static final int MAX_GAIN_INDEX = (MAX_GAIN - MIN_GAIN) / STEP_VALUE;
50     private static final int TEST_GAIN_INDEX = 2;
51     private static final int TEST_USER_10 = 10;
52     private static final int TEST_USER_11 = 11;
53     private static final String MEDIA_DEVICE_ADDRESS = "music";
54     private static final String NAVIGATION_DEVICE_ADDRESS = "navigation";
55     private static final String OTHER_ADDRESS = "other_address";
56 
57     private CarAudioDeviceInfo mMediaDeviceInfo;
58     private CarAudioDeviceInfo mNavigationDeviceInfo;
59 
60     @Mock
61     CarAudioSettings mSettingsMock;
62 
63     @Before
setUp()64     public void setUp() {
65         mMediaDeviceInfo = new InfoBuilder(MEDIA_DEVICE_ADDRESS).build();
66         mNavigationDeviceInfo = new InfoBuilder(NAVIGATION_DEVICE_ADDRESS).build();
67     }
68 
69     @Test
setDeviceInfoForContext_associatesDeviceAddresses()70     public void setDeviceInfoForContext_associatesDeviceAddresses() {
71         CarVolumeGroup.Builder builder = getBuilder();
72 
73         builder.setDeviceInfoForContext(CarAudioContext.MUSIC, mMediaDeviceInfo);
74         builder.setDeviceInfoForContext(CarAudioContext.NAVIGATION, mNavigationDeviceInfo);
75         CarVolumeGroup carVolumeGroup = builder.build();
76 
77         assertThat(carVolumeGroup.getAddresses()).containsExactly(MEDIA_DEVICE_ADDRESS,
78                 NAVIGATION_DEVICE_ADDRESS);
79     }
80 
81     @Test
setDeviceInfoForContext_associatesContexts()82     public void setDeviceInfoForContext_associatesContexts() {
83         CarVolumeGroup.Builder builder = getBuilder();
84 
85         builder.setDeviceInfoForContext(CarAudioContext.MUSIC, mMediaDeviceInfo);
86         builder.setDeviceInfoForContext(CarAudioContext.NAVIGATION, mNavigationDeviceInfo);
87         CarVolumeGroup carVolumeGroup = builder.build();
88 
89         assertThat(carVolumeGroup.getContexts()).asList().containsExactly(CarAudioContext.MUSIC,
90                 CarAudioContext.NAVIGATION);
91     }
92 
93     @Test
setDeviceInfoForContext_withDifferentStepSize_throws()94     public void setDeviceInfoForContext_withDifferentStepSize_throws() {
95         CarVolumeGroup.Builder builder = getBuilder();
96         builder.setDeviceInfoForContext(CarAudioContext.MUSIC, mMediaDeviceInfo);
97         CarAudioDeviceInfo differentStepValueDevice = new InfoBuilder(NAVIGATION_DEVICE_ADDRESS)
98                 .setStepValue(mMediaDeviceInfo.getStepValue() + 1).build();
99 
100         IllegalArgumentException thrown = expectThrows(IllegalArgumentException.class,
101                 () -> builder.setDeviceInfoForContext(CarAudioContext.NAVIGATION,
102                         differentStepValueDevice));
103 
104         assertThat(thrown).hasMessageThat()
105                 .contains("Gain controls within one group must have same step value");
106     }
107 
108     @Test
setDeviceInfoForContext_withSameContext_throws()109     public void setDeviceInfoForContext_withSameContext_throws() {
110         CarVolumeGroup.Builder builder = getBuilder();
111         builder.setDeviceInfoForContext(CarAudioContext.MUSIC, mMediaDeviceInfo);
112 
113         IllegalArgumentException thrown = expectThrows(IllegalArgumentException.class,
114                 () -> builder.setDeviceInfoForContext(CarAudioContext.MUSIC,
115                         mNavigationDeviceInfo));
116 
117         assertThat(thrown).hasMessageThat()
118                 .contains("has already been set to");
119     }
120 
121     @Test
setDeviceInfoForContext_withFirstCall_setsMinGain()122     public void setDeviceInfoForContext_withFirstCall_setsMinGain() {
123         CarVolumeGroup.Builder builder = getBuilder();
124 
125         builder.setDeviceInfoForContext(CarAudioContext.MUSIC, mMediaDeviceInfo);
126 
127         assertThat(builder.mMinGain).isEqualTo(mMediaDeviceInfo.getMinGain());
128     }
129 
130     @Test
setDeviceInfoForContext_withFirstCall_setsMaxGain()131     public void setDeviceInfoForContext_withFirstCall_setsMaxGain() {
132         CarVolumeGroup.Builder builder = getBuilder();
133 
134         builder.setDeviceInfoForContext(CarAudioContext.MUSIC, mMediaDeviceInfo);
135 
136         assertThat(builder.mMaxGain).isEqualTo(mMediaDeviceInfo.getMaxGain());
137     }
138 
139     @Test
setDeviceInfoForContext_withFirstCall_setsDefaultGain()140     public void setDeviceInfoForContext_withFirstCall_setsDefaultGain() {
141         CarVolumeGroup.Builder builder = getBuilder();
142 
143         builder.setDeviceInfoForContext(CarAudioContext.MUSIC, mMediaDeviceInfo);
144 
145         assertThat(builder.mDefaultGain).isEqualTo(mMediaDeviceInfo.getDefaultGain());
146     }
147 
148     @Test
setDeviceInfoForContext_SecondCallWithSmallerMinGain_updatesMinGain()149     public void setDeviceInfoForContext_SecondCallWithSmallerMinGain_updatesMinGain() {
150         CarVolumeGroup.Builder builder = getBuilder();
151         builder.setDeviceInfoForContext(CarAudioContext.MUSIC, mMediaDeviceInfo);
152         CarAudioDeviceInfo secondInfo = new InfoBuilder(NAVIGATION_DEVICE_ADDRESS)
153                 .setMinGain(mMediaDeviceInfo.getMinGain() - 1).build();
154 
155         builder.setDeviceInfoForContext(CarAudioContext.NAVIGATION, secondInfo);
156 
157         assertThat(builder.mMinGain).isEqualTo(secondInfo.getMinGain());
158     }
159 
160     @Test
setDeviceInfoForContext_SecondCallWithLargerMinGain_keepsFirstMinGain()161     public void setDeviceInfoForContext_SecondCallWithLargerMinGain_keepsFirstMinGain() {
162         CarVolumeGroup.Builder builder = getBuilder();
163         builder.setDeviceInfoForContext(CarAudioContext.MUSIC, mMediaDeviceInfo);
164         CarAudioDeviceInfo secondInfo = new InfoBuilder(NAVIGATION_DEVICE_ADDRESS)
165                 .setMinGain(mMediaDeviceInfo.getMinGain() + 1).build();
166 
167         builder.setDeviceInfoForContext(CarAudioContext.NAVIGATION, secondInfo);
168 
169         assertThat(builder.mMinGain).isEqualTo(mMediaDeviceInfo.getMinGain());
170     }
171 
172     @Test
setDeviceInfoForContext_SecondCallWithLargerMaxGain_updatesMaxGain()173     public void setDeviceInfoForContext_SecondCallWithLargerMaxGain_updatesMaxGain() {
174         CarVolumeGroup.Builder builder = getBuilder();
175         builder.setDeviceInfoForContext(CarAudioContext.MUSIC, mMediaDeviceInfo);
176         CarAudioDeviceInfo secondInfo = new InfoBuilder(NAVIGATION_DEVICE_ADDRESS)
177                 .setMaxGain(mMediaDeviceInfo.getMaxGain() + 1).build();
178 
179         builder.setDeviceInfoForContext(CarAudioContext.NAVIGATION, secondInfo);
180 
181         assertThat(builder.mMaxGain).isEqualTo(secondInfo.getMaxGain());
182     }
183 
184     @Test
setDeviceInfoForContext_SecondCallWithSmallerMaxGain_keepsFirstMaxGain()185     public void setDeviceInfoForContext_SecondCallWithSmallerMaxGain_keepsFirstMaxGain() {
186         CarVolumeGroup.Builder builder = getBuilder();
187         builder.setDeviceInfoForContext(CarAudioContext.MUSIC, mMediaDeviceInfo);
188         CarAudioDeviceInfo secondInfo = new InfoBuilder(NAVIGATION_DEVICE_ADDRESS)
189                 .setMaxGain(mMediaDeviceInfo.getMaxGain() - 1).build();
190 
191         builder.setDeviceInfoForContext(CarAudioContext.NAVIGATION, secondInfo);
192 
193         assertThat(builder.mMaxGain).isEqualTo(mMediaDeviceInfo.getMaxGain());
194     }
195 
196     @Test
setDeviceInfoForContext_SecondCallWithLargerDefaultGain_updatesDefaultGain()197     public void setDeviceInfoForContext_SecondCallWithLargerDefaultGain_updatesDefaultGain() {
198         CarVolumeGroup.Builder builder = getBuilder();
199         builder.setDeviceInfoForContext(CarAudioContext.MUSIC, mMediaDeviceInfo);
200         CarAudioDeviceInfo secondInfo = new InfoBuilder(NAVIGATION_DEVICE_ADDRESS)
201                 .setDefaultGain(mMediaDeviceInfo.getDefaultGain() + 1).build();
202 
203         builder.setDeviceInfoForContext(CarAudioContext.NAVIGATION, secondInfo);
204 
205         assertThat(builder.mDefaultGain).isEqualTo(secondInfo.getDefaultGain());
206     }
207 
208     @Test
setDeviceInfoForContext_SecondCallWithSmallerDefaultGain_keepsFirstDefaultGain()209     public void setDeviceInfoForContext_SecondCallWithSmallerDefaultGain_keepsFirstDefaultGain() {
210         CarVolumeGroup.Builder builder = getBuilder();
211         builder.setDeviceInfoForContext(CarAudioContext.MUSIC, mMediaDeviceInfo);
212         CarAudioDeviceInfo secondInfo = new InfoBuilder(NAVIGATION_DEVICE_ADDRESS)
213                 .setDefaultGain(mMediaDeviceInfo.getDefaultGain() - 1).build();
214 
215         builder.setDeviceInfoForContext(CarAudioContext.NAVIGATION, secondInfo);
216 
217         assertThat(builder.mDefaultGain).isEqualTo(mMediaDeviceInfo.getDefaultGain());
218     }
219 
220     @Test
builderBuild_withNoCallToSetDeviceInfoForContext_throws()221     public void builderBuild_withNoCallToSetDeviceInfoForContext_throws() {
222         CarVolumeGroup.Builder builder = getBuilder();
223 
224         Exception e = expectThrows(IllegalArgumentException.class, builder::build);
225 
226         assertThat(e).hasMessageThat().isEqualTo(
227                 "setDeviceInfoForContext has to be called at least once before building");
228     }
229 
230     @Test
builderBuild_withNoStoredGain_usesDefaultGain()231     public void builderBuild_withNoStoredGain_usesDefaultGain() {
232         CarVolumeGroup.Builder builder = getBuilder().setDeviceInfoForContext(CarAudioContext.MUSIC,
233                 mMediaDeviceInfo);
234         when(mSettingsMock.getStoredVolumeGainIndexForUser(UserHandle.USER_CURRENT, ZONE_ID,
235                 GROUP_ID)).thenReturn(-1);
236 
237 
238         CarVolumeGroup carVolumeGroup = builder.build();
239 
240         assertThat(carVolumeGroup.getCurrentGainIndex()).isEqualTo(DEFAULT_GAIN_INDEX);
241     }
242 
243     @Test
builderBuild_withTooLargeStoredGain_usesDefaultGain()244     public void builderBuild_withTooLargeStoredGain_usesDefaultGain() {
245         CarVolumeGroup.Builder builder = getBuilder().setDeviceInfoForContext(CarAudioContext.MUSIC,
246                 mMediaDeviceInfo);
247         when(mSettingsMock.getStoredVolumeGainIndexForUser(UserHandle.USER_CURRENT, ZONE_ID,
248                 GROUP_ID)).thenReturn(MAX_GAIN_INDEX + 1);
249 
250         CarVolumeGroup carVolumeGroup = builder.build();
251 
252         assertThat(carVolumeGroup.getCurrentGainIndex()).isEqualTo(DEFAULT_GAIN_INDEX);
253     }
254 
255     @Test
builderBuild_withTooSmallStoredGain_usesDefaultGain()256     public void builderBuild_withTooSmallStoredGain_usesDefaultGain() {
257         CarVolumeGroup.Builder builder = getBuilder().setDeviceInfoForContext(CarAudioContext.MUSIC,
258                 mMediaDeviceInfo);
259         when(mSettingsMock.getStoredVolumeGainIndexForUser(UserHandle.USER_CURRENT, ZONE_ID,
260                 GROUP_ID)).thenReturn(MIN_GAIN_INDEX - 1);
261 
262         CarVolumeGroup carVolumeGroup = builder.build();
263 
264         assertThat(carVolumeGroup.getCurrentGainIndex()).isEqualTo(DEFAULT_GAIN_INDEX);
265     }
266 
267     @Test
builderBuild_withValidStoredGain_usesStoredGain()268     public void builderBuild_withValidStoredGain_usesStoredGain() {
269         CarVolumeGroup.Builder builder = getBuilder().setDeviceInfoForContext(CarAudioContext.MUSIC,
270                 mMediaDeviceInfo);
271         when(mSettingsMock.getStoredVolumeGainIndexForUser(UserHandle.USER_CURRENT, ZONE_ID,
272                 GROUP_ID)).thenReturn(MAX_GAIN_INDEX - 1);
273 
274         CarVolumeGroup carVolumeGroup = builder.build();
275 
276         assertThat(carVolumeGroup.getCurrentGainIndex()).isEqualTo(MAX_GAIN_INDEX - 1);
277     }
278 
279     @Test
getAddressForContext_withSupportedContext_returnsAddress()280     public void getAddressForContext_withSupportedContext_returnsAddress() {
281         CarVolumeGroup carVolumeGroup = getCarVolumeGroupWithMusicBound();
282 
283         assertThat(carVolumeGroup.getAddressForContext(CarAudioContext.MUSIC))
284                 .isEqualTo(mMediaDeviceInfo.getAddress());
285     }
286 
287     @Test
getAddressForContext_withUnsupportedContext_returnsNull()288     public void getAddressForContext_withUnsupportedContext_returnsNull() {
289         CarVolumeGroup carVolumeGroup = getCarVolumeGroupWithMusicBound();
290 
291         assertThat(carVolumeGroup.getAddressForContext(CarAudioContext.NAVIGATION)).isNull();
292     }
293 
294     @Test
isMuted_whenDefault_returnsFalse()295     public void isMuted_whenDefault_returnsFalse() {
296         CarVolumeGroup carVolumeGroup = getCarVolumeGroupWithMusicBound();
297 
298         assertThat(carVolumeGroup.isMuted()).isFalse();
299     }
300 
301     @Test
isMuted_afterMuting_returnsTrue()302     public void isMuted_afterMuting_returnsTrue() {
303         CarVolumeGroup carVolumeGroup = getCarVolumeGroupWithMusicBound();
304 
305         carVolumeGroup.setMute(true);
306 
307         assertThat(carVolumeGroup.isMuted()).isTrue();
308     }
309 
310     @Test
isMuted_afterUnMuting_returnsFalse()311     public void isMuted_afterUnMuting_returnsFalse() {
312         CarVolumeGroup carVolumeGroup = getCarVolumeGroupWithMusicBound();
313 
314         carVolumeGroup.setMute(false);
315 
316         assertThat(carVolumeGroup.isMuted()).isFalse();
317     }
318 
319     @Test
setMute_withMutedState_storesValueToSetting()320     public void setMute_withMutedState_storesValueToSetting() {
321         CarAudioSettings settings = new SettingsBuilder(0, 0)
322                 .setMuteForUser10(false)
323                 .setIsPersistVolumeGroupEnabled(true)
324                 .build();
325         CarVolumeGroup carVolumeGroup = getCarVolumeGroupWithNavigationBound(settings, true);
326         carVolumeGroup.loadVolumesSettingsForUser(TEST_USER_10);
327 
328         carVolumeGroup.setMute(true);
329 
330         verify(settings)
331                 .storeVolumeGroupMuteForUser(TEST_USER_10, 0, 0, true);
332     }
333 
334     @Test
setMute_withUnMutedState_storesValueToSetting()335     public void setMute_withUnMutedState_storesValueToSetting() {
336         CarAudioSettings settings = new SettingsBuilder(0, 0)
337                 .setMuteForUser10(false)
338                 .setIsPersistVolumeGroupEnabled(true)
339                 .build();
340         CarVolumeGroup carVolumeGroup = getCarVolumeGroupWithNavigationBound(settings, true);
341         carVolumeGroup.loadVolumesSettingsForUser(TEST_USER_10);
342 
343         carVolumeGroup.setMute(false);
344 
345         verify(settings)
346                 .storeVolumeGroupMuteForUser(TEST_USER_10, 0, 0, false);
347     }
348 
349     @Test
getContextsForAddress_returnsContextsBoundToThatAddress()350     public void getContextsForAddress_returnsContextsBoundToThatAddress() {
351         CarVolumeGroup carVolumeGroup = testVolumeGroupSetup();
352 
353         List<Integer> contextsList = carVolumeGroup.getContextsForAddress(MEDIA_DEVICE_ADDRESS);
354 
355         assertThat(contextsList).containsExactly(CarAudioContext.MUSIC,
356                 CarAudioContext.CALL, CarAudioContext.CALL_RING);
357     }
358 
359     @Test
getContextsForAddress_returnsEmptyArrayIfAddressNotBound()360     public void getContextsForAddress_returnsEmptyArrayIfAddressNotBound() {
361         CarVolumeGroup carVolumeGroup = testVolumeGroupSetup();
362 
363         List<Integer> contextsList = carVolumeGroup.getContextsForAddress(OTHER_ADDRESS);
364 
365         assertThat(contextsList).isEmpty();
366     }
367 
368     @Test
getCarAudioDeviceInfoForAddress_returnsExpectedDevice()369     public void getCarAudioDeviceInfoForAddress_returnsExpectedDevice() {
370         CarVolumeGroup carVolumeGroup = testVolumeGroupSetup();
371 
372         CarAudioDeviceInfo actualDevice = carVolumeGroup.getCarAudioDeviceInfoForAddress(
373                 MEDIA_DEVICE_ADDRESS);
374 
375         assertThat(actualDevice).isEqualTo(mMediaDeviceInfo);
376     }
377 
378     @Test
getCarAudioDeviceInfoForAddress_returnsNullIfAddressNotBound()379     public void getCarAudioDeviceInfoForAddress_returnsNullIfAddressNotBound() {
380         CarVolumeGroup carVolumeGroup = testVolumeGroupSetup();
381 
382         CarAudioDeviceInfo actualDevice = carVolumeGroup.getCarAudioDeviceInfoForAddress(
383                 OTHER_ADDRESS);
384 
385         assertThat(actualDevice).isNull();
386     }
387 
388     @Test
setCurrentGainIndex_setsGainOnAllBoundDevices()389     public void setCurrentGainIndex_setsGainOnAllBoundDevices() {
390         CarVolumeGroup carVolumeGroup = testVolumeGroupSetup();
391 
392         carVolumeGroup.setCurrentGainIndex(TEST_GAIN_INDEX);
393 
394         verify(mMediaDeviceInfo).setCurrentGain(7);
395         verify(mNavigationDeviceInfo).setCurrentGain(7);
396     }
397 
398     @Test
setCurrentGainIndex_updatesCurrentGainIndex()399     public void setCurrentGainIndex_updatesCurrentGainIndex() {
400         CarVolumeGroup carVolumeGroup = testVolumeGroupSetup();
401 
402         carVolumeGroup.setCurrentGainIndex(TEST_GAIN_INDEX);
403 
404         assertThat(carVolumeGroup.getCurrentGainIndex()).isEqualTo(TEST_GAIN_INDEX);
405     }
406 
407     @Test
setCurrentGainIndex_checksNewGainIsAboveMin()408     public void setCurrentGainIndex_checksNewGainIsAboveMin() {
409         CarVolumeGroup carVolumeGroup = testVolumeGroupSetup();
410 
411         IllegalArgumentException thrown = expectThrows(IllegalArgumentException.class,
412                 () -> carVolumeGroup.setCurrentGainIndex(MIN_GAIN_INDEX - 1));
413         assertThat(thrown).hasMessageThat()
414                 .contains("Gain out of range (" + MIN_GAIN + ":" + MAX_GAIN + ")");
415     }
416 
417     @Test
setCurrentGainIndex_checksNewGainIsBelowMax()418     public void setCurrentGainIndex_checksNewGainIsBelowMax() {
419         CarVolumeGroup carVolumeGroup = testVolumeGroupSetup();
420 
421         IllegalArgumentException thrown = expectThrows(IllegalArgumentException.class,
422                 () -> carVolumeGroup.setCurrentGainIndex(MAX_GAIN_INDEX + 1));
423         assertThat(thrown).hasMessageThat()
424                 .contains("Gain out of range (" + MIN_GAIN + ":" + MAX_GAIN + ")");
425     }
426 
427     @Test
setCurrentGainIndex_setsCurrentGainIndexForUser()428     public void setCurrentGainIndex_setsCurrentGainIndexForUser() {
429         CarAudioSettings settings = new SettingsBuilder(0, 0)
430                 .setGainIndexForUser(TEST_USER_11)
431                 .build();
432         CarVolumeGroup carVolumeGroup = getCarVolumeGroupWithNavigationBound(settings, false);
433         carVolumeGroup.loadVolumesSettingsForUser(TEST_USER_11);
434 
435         carVolumeGroup.setCurrentGainIndex(MIN_GAIN);
436 
437         verify(settings).storeVolumeGainIndexForUser(TEST_USER_11, 0, 0, MIN_GAIN);
438     }
439 
440     @Test
setCurrentGainIndex_setsCurrentGainIndexForDefaultUser()441     public void setCurrentGainIndex_setsCurrentGainIndexForDefaultUser() {
442         CarAudioSettings settings = new SettingsBuilder(0, 0)
443                 .setGainIndexForUser(UserHandle.USER_CURRENT)
444                 .build();
445         CarVolumeGroup carVolumeGroup = getCarVolumeGroupWithNavigationBound(settings, false);
446 
447         carVolumeGroup.setCurrentGainIndex(MIN_GAIN);
448 
449         verify(settings)
450                 .storeVolumeGainIndexForUser(UserHandle.USER_CURRENT, 0, 0, MIN_GAIN);
451     }
452 
453     @Test
loadVolumesSettingsForUser_withMutedState_loadsMuteStateForUser()454     public void loadVolumesSettingsForUser_withMutedState_loadsMuteStateForUser() {
455         CarVolumeGroup carVolumeGroup = getVolumeGroupWithMuteAndNavBound(true, true, true);
456 
457         carVolumeGroup.loadVolumesSettingsForUser(TEST_USER_10);
458 
459         assertThat(carVolumeGroup.isMuted()).isTrue();
460     }
461 
462     @Test
loadVolumesSettingsForUser_withDisabledUseVolumeGroupMute_doesNotLoadMute()463     public void loadVolumesSettingsForUser_withDisabledUseVolumeGroupMute_doesNotLoadMute() {
464         CarVolumeGroup carVolumeGroup = getVolumeGroupWithMuteAndNavBound(true, true, false);
465 
466         carVolumeGroup.loadVolumesSettingsForUser(TEST_USER_10);
467 
468         assertThat(carVolumeGroup.isMuted()).isFalse();
469     }
470 
471     @Test
loadVolumesSettingsForUser_withUnMutedState_loadsMuteStateForUser()472     public void loadVolumesSettingsForUser_withUnMutedState_loadsMuteStateForUser() {
473         CarVolumeGroup carVolumeGroup = getVolumeGroupWithMuteAndNavBound(false, true, true);
474 
475         carVolumeGroup.loadVolumesSettingsForUser(TEST_USER_10);
476 
477         assertThat(carVolumeGroup.isMuted()).isFalse();
478     }
479 
480     @Test
loadVolumesSettingsForUser_withMutedStateAndNoPersist_returnsDefaultMuteState()481     public void loadVolumesSettingsForUser_withMutedStateAndNoPersist_returnsDefaultMuteState() {
482         CarVolumeGroup carVolumeGroup = getVolumeGroupWithMuteAndNavBound(true, false, true);
483 
484         carVolumeGroup.loadVolumesSettingsForUser(TEST_USER_10);
485 
486         assertThat(carVolumeGroup.isMuted()).isFalse();
487     }
488 
489     @Test
hasCriticalAudioContexts_withoutCriticalContexts_returnsFalse()490     public void hasCriticalAudioContexts_withoutCriticalContexts_returnsFalse() {
491         CarVolumeGroup carVolumeGroup = getCarVolumeGroupWithMusicBound();
492 
493         assertThat(carVolumeGroup.hasCriticalAudioContexts()).isFalse();
494     }
495 
496     @Test
hasCriticalAudioContexts_withCriticalContexts_returnsTrue()497     public void hasCriticalAudioContexts_withCriticalContexts_returnsTrue() {
498         CarVolumeGroup carVolumeGroup = getBuilder()
499                 .setDeviceInfoForContext(CarAudioContext.EMERGENCY, mMediaDeviceInfo)
500                 .build();
501 
502         assertThat(carVolumeGroup.hasCriticalAudioContexts()).isTrue();
503     }
504 
getCarVolumeGroupWithMusicBound()505     private CarVolumeGroup getCarVolumeGroupWithMusicBound() {
506         return getBuilder()
507                 .setDeviceInfoForContext(CarAudioContext.MUSIC, mMediaDeviceInfo)
508                 .build();
509     }
510 
getCarVolumeGroupWithNavigationBound(CarAudioSettings settings, boolean useCarVolumeGroupMute)511     private CarVolumeGroup getCarVolumeGroupWithNavigationBound(CarAudioSettings settings,
512             boolean useCarVolumeGroupMute) {
513         return new CarVolumeGroup.Builder(0, 0, settings, useCarVolumeGroupMute)
514                 .setDeviceInfoForContext(CarAudioContext.NAVIGATION, mNavigationDeviceInfo)
515                 .build();
516     }
517 
getVolumeGroupWithMuteAndNavBound(boolean isMuted, boolean persistMute, boolean useCarVolumeGroupMute)518     CarVolumeGroup getVolumeGroupWithMuteAndNavBound(boolean isMuted, boolean persistMute,
519             boolean useCarVolumeGroupMute) {
520         CarAudioSettings settings = new SettingsBuilder(0, 0)
521                 .setMuteForUser10(isMuted)
522                 .setIsPersistVolumeGroupEnabled(persistMute)
523                 .build();
524         return getCarVolumeGroupWithNavigationBound(settings, useCarVolumeGroupMute);
525     }
526 
testVolumeGroupSetup()527     private CarVolumeGroup testVolumeGroupSetup() {
528         CarVolumeGroup.Builder builder = getBuilder();
529 
530         builder.setDeviceInfoForContext(CarAudioContext.MUSIC, mMediaDeviceInfo);
531         builder.setDeviceInfoForContext(CarAudioContext.CALL, mMediaDeviceInfo);
532         builder.setDeviceInfoForContext(CarAudioContext.CALL_RING, mMediaDeviceInfo);
533 
534         builder.setDeviceInfoForContext(CarAudioContext.NAVIGATION, mNavigationDeviceInfo);
535         builder.setDeviceInfoForContext(CarAudioContext.ALARM, mNavigationDeviceInfo);
536         builder.setDeviceInfoForContext(CarAudioContext.NOTIFICATION, mNavigationDeviceInfo);
537 
538         return builder.build();
539     }
540 
getBuilder()541     CarVolumeGroup.Builder getBuilder() {
542         return new CarVolumeGroup.Builder(ZONE_ID, GROUP_ID, mSettingsMock, true);
543     }
544 
545     private static final class SettingsBuilder {
546         private final SparseIntArray mStoredGainIndexes = new SparseIntArray();
547         private final SparseBooleanArray mStoreMuteStates = new SparseBooleanArray();
548         private final int mZoneId;
549         private final int mGroupId;
550 
551         private boolean mPersistMute;
552 
SettingsBuilder(int zoneId, int groupId)553         SettingsBuilder(int zoneId, int groupId) {
554             mZoneId = zoneId;
555             mGroupId = groupId;
556         }
557 
setGainIndexForUser(@serIdInt int userId)558         SettingsBuilder setGainIndexForUser(@UserIdInt int userId) {
559             mStoredGainIndexes.put(userId, TEST_GAIN_INDEX);
560             return this;
561         }
562 
setMuteForUser10(boolean mute)563         SettingsBuilder setMuteForUser10(boolean mute) {
564             mStoreMuteStates.put(CarVolumeGroupUnitTest.TEST_USER_10, mute);
565             return this;
566         }
567 
setIsPersistVolumeGroupEnabled(boolean persistMute)568         SettingsBuilder setIsPersistVolumeGroupEnabled(boolean persistMute) {
569             mPersistMute = persistMute;
570             return this;
571         }
572 
build()573         CarAudioSettings build() {
574             CarAudioSettings settingsMock = Mockito.mock(CarAudioSettings.class);
575             for (int storeIndex = 0; storeIndex < mStoredGainIndexes.size(); storeIndex++) {
576                 int gainUserId = mStoredGainIndexes.keyAt(storeIndex);
577                 when(settingsMock
578                         .getStoredVolumeGainIndexForUser(gainUserId, mZoneId,
579                                 mGroupId)).thenReturn(
580                         mStoredGainIndexes.get(gainUserId, DEFAULT_GAIN));
581             }
582             for (int muteIndex = 0; muteIndex < mStoreMuteStates.size(); muteIndex++) {
583                 int muteUserId = mStoreMuteStates.keyAt(muteIndex);
584                 when(settingsMock.getVolumeGroupMuteForUser(muteUserId, mZoneId, mGroupId))
585                         .thenReturn(mStoreMuteStates.get(muteUserId, false));
586                 when(settingsMock.isPersistVolumeGroupMuteEnabled(muteUserId))
587                         .thenReturn(mPersistMute);
588             }
589             return settingsMock;
590         }
591     }
592 
593     private static final class InfoBuilder {
594         private final String mAddress;
595 
596         private int mStepValue = STEP_VALUE;
597         private int mDefaultGain = DEFAULT_GAIN;
598         private int mMinGain = MIN_GAIN;
599         private int mMaxGain = MAX_GAIN;
600 
InfoBuilder(String address)601         InfoBuilder(String address) {
602             mAddress = address;
603         }
604 
setStepValue(int stepValue)605         InfoBuilder setStepValue(int stepValue) {
606             mStepValue = stepValue;
607             return this;
608         }
609 
setDefaultGain(int defaultGain)610         InfoBuilder setDefaultGain(int defaultGain) {
611             mDefaultGain = defaultGain;
612             return this;
613         }
614 
setMinGain(int minGain)615         InfoBuilder setMinGain(int minGain) {
616             mMinGain = minGain;
617             return this;
618         }
619 
setMaxGain(int maxGain)620         InfoBuilder setMaxGain(int maxGain) {
621             mMaxGain = maxGain;
622             return this;
623         }
624 
build()625         CarAudioDeviceInfo build() {
626             CarAudioDeviceInfo infoMock = Mockito.mock(CarAudioDeviceInfo.class);
627             when(infoMock.getStepValue()).thenReturn(mStepValue);
628             when(infoMock.getDefaultGain()).thenReturn(mDefaultGain);
629             when(infoMock.getMaxGain()).thenReturn(mMaxGain);
630             when(infoMock.getMinGain()).thenReturn(mMinGain);
631             when(infoMock.getAddress()).thenReturn(mAddress);
632             return infoMock;
633         }
634     }
635 }
636