• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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 android.car.media.CarAudioManager.PRIMARY_AUDIO_ZONE;
20 import static android.media.AudioManager.GET_DEVICES_INPUTS;
21 import static android.media.AudioManager.GET_DEVICES_OUTPUTS;
22 
23 import static com.android.car.audio.CarAudioDeviceInfoTestUtils.MEDIA_TEST_DEVICE;
24 import static com.android.car.audio.CarAudioDeviceInfoTestUtils.NAVIGATION_TEST_DEVICE;
25 import static com.android.car.audio.CarAudioDeviceInfoTestUtils.PRIMARY_ZONE_MICROPHONE_DEVICE;
26 import static com.android.car.audio.CarAudioDeviceInfoTestUtils.SECONDARY_ZONE_BUS_1000_INPUT_DEVICE;
27 import static com.android.car.audio.CarAudioTestUtils.GAINS;
28 import static com.android.car.audio.CarAudioTestUtils.SECONDARY_ZONE_ID;
29 import static com.android.car.audio.CarAudioTestUtils.TEST_CREATED_CAR_AUDIO_CONTEXT;
30 import static com.android.car.audio.CarAudioTestUtils.createAudioPort;
31 import static com.android.car.audio.CarAudioTestUtils.createAudioPortDeviceExt;
32 import static com.android.car.audio.CarAudioTestUtils.createPrimaryAudioZone;
33 import static com.android.car.audio.CarAudioTestUtils.createSecondaryAudioZone;
34 import static com.android.car.audio.CoreAudioRoutingUtils.getCoreAudioZone;
35 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
36 
37 import static com.google.common.truth.Truth.assertWithMessage;
38 
39 import static org.junit.Assert.assertThrows;
40 import static org.mockito.Mockito.when;
41 
42 import android.car.test.mocks.AbstractExtendedMockitoTestCase;
43 import android.hardware.automotive.audiocontrol.AudioDeviceConfiguration;
44 import android.hardware.automotive.audiocontrol.AudioZone;
45 import android.hardware.automotive.audiocontrol.RoutingDeviceConfiguration;
46 import android.media.AudioDeviceAttributes;
47 import android.media.audio.common.AudioDeviceType;
48 import android.media.audio.common.AudioPort;
49 import android.media.audio.common.AudioPortDeviceExt;
50 
51 import com.android.car.audio.hal.AudioControlWrapper;
52 import com.android.car.internal.util.LocalLog;
53 
54 import org.junit.Before;
55 import org.junit.Test;
56 import org.junit.runner.RunWith;
57 import org.mockito.Mock;
58 import org.mockito.junit.MockitoJUnitRunner;
59 
60 import java.util.ArrayList;
61 import java.util.List;
62 
63 @RunWith(MockitoJUnitRunner.class)
64 public final class CarAudioZonesHelperAudioControlHALUnitTest
65         extends AbstractExtendedMockitoTestCase {
66 
67     private static final int TEST_PRIMARY_ZONE_OCCUPANT_ID = 1;
68     private static final int TEST_SECONDARY_ZONE_OCCUPANT_ID = 2;
69 
70     @Mock
71     private CarAudioSettings mCarAudioSettings;
72     @Mock
73     private AudioManagerWrapper mAudioManager;
74     @Mock
75     private LocalLog mServiceLog;
76     @Mock
77     private AudioControlWrapper mAudioControlWrapper;
78     private boolean mUseAudioFadeManager = true;
79 
80     private final List<AudioZone> mHALAudioZones = new ArrayList<>();
81 
82     private final CarAudioDeviceInfoTestUtils mDeviceTestUtils = new CarAudioDeviceInfoTestUtils();
83     private final AudioDeviceConfiguration mAudioDeviceConfig = new AudioDeviceConfiguration();
84     private final List<AudioPort> mMirrorPorts = new ArrayList<>();
85 
86     @Override
clearInlineMocks(String when)87     protected void clearInlineMocks(String when) {
88         super.clearInlineMocks(when);
89     }
90 
91     @Override
onSessionBuilder(CustomMockitoSessionBuilder session)92     protected void onSessionBuilder(CustomMockitoSessionBuilder session) {
93         session.spyStatic(AudioManagerWrapper.class);
94     }
95 
96     @Before
setUp()97     public void setUp() {
98         doReturn(CoreAudioRoutingUtils.getProductStrategies())
99                 .when(AudioManagerWrapper::getAudioProductStrategies);
100 
101         var outputDevice = mDeviceTestUtils.generateOutputDeviceInfos();
102         var inputDevices = mDeviceTestUtils.generateInputDeviceInfos();
103         when(mAudioManager.getDevices(GET_DEVICES_OUTPUTS)).thenReturn(outputDevice);
104         when(mAudioManager.getDevices(GET_DEVICES_INPUTS)).thenReturn(inputDevices);
105 
106         when(mAudioControlWrapper.supportsFeature(
107                 AudioControlWrapper.AUDIOCONTROL_FEATURE_AUDIO_CONFIGURATION)).thenReturn(true);
108         when(mAudioControlWrapper.getCarAudioZones()).thenReturn(mHALAudioZones);
109         mAudioDeviceConfig.routingConfig = RoutingDeviceConfiguration.DYNAMIC_AUDIO_ROUTING;
110         when(mAudioControlWrapper.getAudioDeviceConfiguration()).thenReturn(mAudioDeviceConfig);
111         when(mAudioControlWrapper.getOutputMirroringDevices()).thenReturn(mMirrorPorts);
112     }
113 
114     @Test
constructor_withNullAudioControlHAL()115     public void constructor_withNullAudioControlHAL() {
116         AudioControlWrapper audioControl = null;
117 
118         var thrown = assertThrows(NullPointerException.class,
119                 () -> new CarAudioZonesHelperAudioControlHAL(audioControl, mAudioManager,
120                         mCarAudioSettings, mServiceLog, mUseAudioFadeManager));
121 
122         expectWithMessage("Exception for null audio control HAL").that(thrown)
123                 .hasMessageThat().contains("Audio control HAL");
124     }
125 
126     @Test
constructor_withNullAudioManager()127     public void constructor_withNullAudioManager() {
128         AudioManagerWrapper audioManager = null;
129 
130         var thrown = assertThrows(NullPointerException.class,
131                 () -> new CarAudioZonesHelperAudioControlHAL(mAudioControlWrapper, audioManager,
132                         mCarAudioSettings, mServiceLog, mUseAudioFadeManager));
133 
134         expectWithMessage("Exception for null audio manager").that(thrown)
135                 .hasMessageThat().contains("Audio manager");
136     }
137 
138     @Test
constructor_withNullAudioSettings()139     public void constructor_withNullAudioSettings() {
140         CarAudioSettings audioSettings = null;
141 
142         var thrown = assertThrows(NullPointerException.class,
143                 () -> new CarAudioZonesHelperAudioControlHAL(mAudioControlWrapper, mAudioManager,
144                         audioSettings, mServiceLog, mUseAudioFadeManager));
145 
146         expectWithMessage("Exception for null car audio settings").that(thrown)
147                 .hasMessageThat().contains("Car audio settings");
148     }
149 
150     @Test
constructor_withNullServiceLogs()151     public void constructor_withNullServiceLogs() {
152         LocalLog serviceLogs = null;
153 
154         var thrown = assertThrows(NullPointerException.class,
155                 () -> new CarAudioZonesHelperAudioControlHAL(mAudioControlWrapper, mAudioManager,
156                         mCarAudioSettings, serviceLogs, mUseAudioFadeManager));
157 
158         expectWithMessage("Exception for null car audio logs").that(thrown)
159                 .hasMessageThat().contains("Car audio log");
160     }
161 
162     @Test
loadAudioZones_withUnsupportedOperationFromHal()163     public void loadAudioZones_withUnsupportedOperationFromHal() {
164         when(mAudioControlWrapper.supportsFeature(
165                 AudioControlWrapper.AUDIOCONTROL_FEATURE_AUDIO_CONFIGURATION)).thenReturn(false);
166         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
167 
168         var audioZones = helper.loadAudioZones();
169 
170         expectWithMessage("Loaded audio zones with unsupported feature from HAL")
171                 .that(audioZones.size()).isEqualTo(0);
172     }
173 
174     @Test
loadAudioZones_withDefaultDeviceConfig()175     public void loadAudioZones_withDefaultDeviceConfig() {
176         mAudioDeviceConfig.routingConfig = RoutingDeviceConfiguration.DEFAULT_AUDIO_ROUTING;
177         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
178 
179         var audioZones = helper.loadAudioZones();
180 
181         expectWithMessage("Loaded audio zones with default audio routing")
182                 .that(audioZones.size()).isEqualTo(0);
183     }
184 
185     @Test
loadAudioZones_withNullZonesFromHal()186     public void loadAudioZones_withNullZonesFromHal() {
187         when(mAudioControlWrapper.getCarAudioZones()).thenReturn(null);
188         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
189 
190         var audioZones = helper.loadAudioZones();
191 
192         expectWithMessage("Loaded audio zones with null audio zones from HAL")
193                 .that(audioZones.size()).isEqualTo(0);
194     }
195 
196     @Test
loadAudioZones_withEmptyZonesFromHal()197     public void loadAudioZones_withEmptyZonesFromHal() {
198         mHALAudioZones.clear();
199         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
200 
201         var audioZones = helper.loadAudioZones();
202 
203         expectWithMessage("Loaded audio zones with null audio zones from HAL")
204                 .that(audioZones.size()).isEqualTo(0);
205     }
206 
207     @Test
loadAudioZones_withNullZoneInZonesFromHal()208     public void loadAudioZones_withNullZoneInZonesFromHal() {
209         mHALAudioZones.add(null);
210         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
211 
212         var audioZones = helper.loadAudioZones();
213 
214         expectWithMessage("Loaded audio zones with null audio zone in audio zones from HAL")
215                 .that(audioZones.size()).isEqualTo(0);
216     }
217 
218     @Test
loadAudioZones_withRepeatingZonesFromHal()219     public void loadAudioZones_withRepeatingZonesFromHal() {
220         mHALAudioZones.add(createPrimaryAudioZone());
221         mHALAudioZones.add(createPrimaryAudioZone());
222         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
223 
224         var audioZones = helper.loadAudioZones();
225 
226         expectWithMessage("Loaded audio zones with repeating audio zones from HAL")
227                 .that(audioZones.size()).isEqualTo(0);
228     }
229 
230     @Test
loadAudioZones_withValidPrimaryZonesFromHal()231     public void loadAudioZones_withValidPrimaryZonesFromHal() {
232         mHALAudioZones.add(createPrimaryAudioZone());
233         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
234 
235         var audioZones = helper.loadAudioZones();
236 
237         expectWithMessage("Loaded audio zones with valid primary zone from HAL")
238                 .that(audioZones.size()).isEqualTo(1);
239         var primaryZone = audioZones.get(PRIMARY_AUDIO_ZONE);
240         assertWithMessage("Loaded primary audio zone").that(primaryZone).isNotNull();
241         expectWithMessage("Loaded primary audio zone configs")
242                 .that(primaryZone.getAllCarAudioZoneConfigs()).hasSize(3);
243         var inputAddresses = primaryZone.getInputAudioDevices().stream()
244                 .map(AudioDeviceAttributes::getAddress).toList();
245         expectWithMessage("Loaded primary zone input devices").that(inputAddresses)
246                 .containsExactly(PRIMARY_ZONE_MICROPHONE_DEVICE,
247                         SECONDARY_ZONE_BUS_1000_INPUT_DEVICE);
248     }
249 
250     @Test
loadAudioZones_withValidSecondaryZoneFromHal()251     public void loadAudioZones_withValidSecondaryZoneFromHal() {
252         mHALAudioZones.add(createPrimaryAudioZone());
253         mHALAudioZones.add(createSecondaryAudioZone());
254         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
255 
256         var audioZones = helper.loadAudioZones();
257 
258         expectWithMessage("Loaded audio zones with valid secondary zone from HAL")
259                 .that(audioZones.size()).isEqualTo(2);
260         var secondaryZone = audioZones.get(SECONDARY_ZONE_ID);
261         assertWithMessage("Loaded secondary audio zone").that(secondaryZone).isNotNull();
262         expectWithMessage("Loaded secondary audio zone configs")
263                 .that(secondaryZone.getAllCarAudioZoneConfigs()).hasSize(2);
264     }
265 
266     @Test
loadAudioZones_withoutPrimaryZoneFromHal()267     public void loadAudioZones_withoutPrimaryZoneFromHal() {
268         mHALAudioZones.add(createSecondaryAudioZone());
269         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
270 
271         var audioZones = helper.loadAudioZones();
272 
273         expectWithMessage("Loaded audio zones without primary zone")
274                 .that(audioZones.size()).isEqualTo(0);
275     }
276 
277     @Test
loadAudioZones_withInvalidUseCoreVolumeConfiguration()278     public void loadAudioZones_withInvalidUseCoreVolumeConfiguration() {
279         mHALAudioZones.add(createPrimaryAudioZone());
280         mAudioDeviceConfig.useCoreAudioVolume = true;
281         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
282 
283         var audioZones = helper.loadAudioZones();
284 
285         expectWithMessage("Loaded audio zones with invalid use core volume configuration")
286                 .that(audioZones.size()).isEqualTo(0);
287     }
288 
289     @Test
loadAudioZones_withCoreAudioRoutingAndValidPrimaryZonesFromHal()290     public void loadAudioZones_withCoreAudioRoutingAndValidPrimaryZonesFromHal() {
291         mHALAudioZones.add(getCoreAudioZone());
292         mAudioDeviceConfig.routingConfig =
293                 RoutingDeviceConfiguration.CONFIGURABLE_AUDIO_ENGINE_ROUTING;
294         mAudioDeviceConfig.useCoreAudioVolume = true;
295         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
296 
297         var audioZones = helper.loadAudioZones();
298 
299         expectWithMessage("Loaded audio zones with core audio routing")
300                 .that(audioZones.size()).isEqualTo(1);
301         var primaryZone = audioZones.get(PRIMARY_AUDIO_ZONE);
302         assertWithMessage("Loaded primary audio zone with core audio routing")
303                 .that(primaryZone).isNotNull();
304         expectWithMessage("Loaded primary audio zone configs with core audio routing")
305                 .that(primaryZone.getAllCarAudioZoneConfigs()).hasSize(1);
306     }
307 
308     @Test
getCarAudioZoneIdToOccupantZoneIdMapping_withPrimaryZoneMapped()309     public void getCarAudioZoneIdToOccupantZoneIdMapping_withPrimaryZoneMapped() {
310         var primaryZone = createPrimaryAudioZone();
311         primaryZone.occupantZoneId = TEST_PRIMARY_ZONE_OCCUPANT_ID;
312         mHALAudioZones.add(primaryZone);
313         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
314         helper.loadAudioZones();
315 
316         var audioZoneIdToOccupantZoneId = helper.getCarAudioZoneIdToOccupantZoneIdMapping();
317 
318         expectWithMessage("Loaded audio zones to occupant zone mapping")
319                 .that(audioZoneIdToOccupantZoneId.size()).isEqualTo(1);
320         expectWithMessage("Loaded primary occupant zone mapping").that(audioZoneIdToOccupantZoneId
321                 .get(PRIMARY_AUDIO_ZONE)).isEqualTo(TEST_PRIMARY_ZONE_OCCUPANT_ID);
322     }
323 
324     @Test
getCarAudioZoneIdToOccupantZoneIdMapping_withPrimaryAndSecondaryZoneMapped()325     public void getCarAudioZoneIdToOccupantZoneIdMapping_withPrimaryAndSecondaryZoneMapped() {
326         var primaryZone = createPrimaryAudioZone();
327         primaryZone.occupantZoneId = TEST_PRIMARY_ZONE_OCCUPANT_ID;
328         var secondaryZone = createSecondaryAudioZone();
329         secondaryZone.occupantZoneId = TEST_SECONDARY_ZONE_OCCUPANT_ID;
330         mHALAudioZones.add(primaryZone);
331         mHALAudioZones.add(secondaryZone);
332         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
333         helper.loadAudioZones();
334 
335         var audioZoneIdToOccupantZoneId = helper.getCarAudioZoneIdToOccupantZoneIdMapping();
336 
337         expectWithMessage("Loaded audio zones to occupant zone mapping with primary and secondary"
338                 + " zones").that(audioZoneIdToOccupantZoneId.size()).isEqualTo(2);
339         expectWithMessage("Loaded primary occupant zone with both primary and secondary zones")
340                 .that(audioZoneIdToOccupantZoneId.get(PRIMARY_AUDIO_ZONE))
341                 .isEqualTo(TEST_PRIMARY_ZONE_OCCUPANT_ID);
342         expectWithMessage("Loaded secondary  occupant zone mapping with both primary and secondary"
343                 + " zones").that(audioZoneIdToOccupantZoneId.get(SECONDARY_ZONE_ID))
344                 .isEqualTo(TEST_SECONDARY_ZONE_OCCUPANT_ID);
345     }
346 
347     @Test
getCarAudioZoneIdToOccupantZoneIdMapping_withLoadFailures()348     public void getCarAudioZoneIdToOccupantZoneIdMapping_withLoadFailures() {
349         var secondaryZone = createSecondaryAudioZone();
350         secondaryZone.occupantZoneId = TEST_SECONDARY_ZONE_OCCUPANT_ID;
351         mHALAudioZones.add(secondaryZone);
352         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
353         helper.loadAudioZones();
354 
355         var audioZoneIdToOccupantZoneId = helper.getCarAudioZoneIdToOccupantZoneIdMapping();
356 
357         expectWithMessage("Loaded audio zones to occupant zone mapping with load zones failure")
358                 .that(audioZoneIdToOccupantZoneId.size()).isEqualTo(0);
359     }
360 
361     @Test
getCarAudioContext_withPrimaryZoneFromHal()362     public void getCarAudioContext_withPrimaryZoneFromHal() {
363         mHALAudioZones.add(createPrimaryAudioZone());
364         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
365         helper.loadAudioZones();
366 
367         var carAudioContext = helper.getCarAudioContext();
368 
369         expectWithMessage("Loaded car audio context with primary zone")
370                 .that(carAudioContext).isEqualTo(TEST_CREATED_CAR_AUDIO_CONTEXT);
371     }
372 
373     @Test
getCarAudioContext_withoutPrimaryZoneFromHal()374     public void getCarAudioContext_withoutPrimaryZoneFromHal() {
375         mHALAudioZones.add(createSecondaryAudioZone());
376         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
377         helper.loadAudioZones();
378 
379         var carAudioContext = helper.getCarAudioContext();
380 
381         expectWithMessage("Loaded car audio context without primary zone")
382                 .that(carAudioContext).isNull();
383     }
384 
385     @Test
getCarAudioContext_withoutCallingLoadZonesFirst()386     public void getCarAudioContext_withoutCallingLoadZonesFirst() {
387         mHALAudioZones.add(createPrimaryAudioZone());
388         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
389 
390         var carAudioContext = helper.getCarAudioContext();
391 
392         expectWithMessage("Loaded car audio context without initializing helper")
393                 .that(carAudioContext).isNull();
394     }
395 
396     @Test
useCoreAudioRouting_withoutCallingLoadZonesFirst()397     public void useCoreAudioRouting_withoutCallingLoadZonesFirst() {
398         mHALAudioZones.add(createPrimaryAudioZone());
399         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
400 
401         expectWithMessage("Loaded car audio routing without initializing helper")
402                 .that(helper.useCoreAudioRouting()).isFalse();
403     }
404 
405     @Test
useCoreAudioRouting_withUseDynamicRoutingFromHal()406     public void useCoreAudioRouting_withUseDynamicRoutingFromHal() {
407         mAudioDeviceConfig.routingConfig = RoutingDeviceConfiguration.DYNAMIC_AUDIO_ROUTING;
408         mHALAudioZones.add(createSecondaryAudioZone());
409         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
410         helper.loadAudioZones();
411 
412         expectWithMessage("Loaded car audio routing with dynamic audio routing")
413                 .that(helper.useCoreAudioRouting()).isFalse();
414     }
415 
416     @Test
useCoreAudioRouting_withCoreAudioRoutingFromHal()417     public void useCoreAudioRouting_withCoreAudioRoutingFromHal() {
418         mHALAudioZones.add(getCoreAudioZone());
419         mAudioDeviceConfig.routingConfig =
420                 RoutingDeviceConfiguration.CONFIGURABLE_AUDIO_ENGINE_ROUTING;
421         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
422         helper.loadAudioZones();
423 
424         expectWithMessage("Loaded car audio routing with core audio routing")
425                 .that(helper.useCoreAudioRouting()).isTrue();
426     }
427 
428     @Test
useCoreAudioRouting_withCoreAudioRoutingFromHalAndLoadFailure()429     public void useCoreAudioRouting_withCoreAudioRoutingFromHalAndLoadFailure() {
430         mHALAudioZones.add(createSecondaryAudioZone());
431         mAudioDeviceConfig.routingConfig =
432                 RoutingDeviceConfiguration.CONFIGURABLE_AUDIO_ENGINE_ROUTING;
433         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
434         helper.loadAudioZones();
435 
436         expectWithMessage("Loaded car audio routing with core audio routing and load failure")
437                 .that(helper.useCoreAudioRouting()).isFalse();
438     }
439 
440     @Test
useCoreAudioVolume_withoutCallingLoadZonesFirst()441     public void useCoreAudioVolume_withoutCallingLoadZonesFirst() {
442         mHALAudioZones.add(createPrimaryAudioZone());
443         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
444 
445         expectWithMessage("Loaded car audio volume without initializing helper")
446                 .that(helper.useCoreAudioVolume()).isFalse();
447     }
448 
449     @Test
useCoreAudioVolume_withoutUseCoreVolumeFromHal()450     public void useCoreAudioVolume_withoutUseCoreVolumeFromHal() {
451         mAudioDeviceConfig.useCoreAudioVolume = false;
452         mHALAudioZones.add(createSecondaryAudioZone());
453         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
454         helper.loadAudioZones();
455 
456         expectWithMessage("Loaded car audio volume without use core volume")
457                 .that(helper.useCoreAudioVolume()).isFalse();
458     }
459 
460     @Test
useCoreAudioVolume_withUseCoreVolumeFromHal()461     public void useCoreAudioVolume_withUseCoreVolumeFromHal() {
462         mAudioDeviceConfig.useCoreAudioVolume = true;
463         mHALAudioZones.add(getCoreAudioZone());
464         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
465         helper.loadAudioZones();
466 
467         expectWithMessage("Loaded car audio volume with use core volume")
468                 .that(helper.useCoreAudioVolume()).isTrue();
469     }
470 
471     @Test
useCoreAudioVolume_withUseCoreVolumeFromHalAndLoadFailure()472     public void useCoreAudioVolume_withUseCoreVolumeFromHalAndLoadFailure() {
473         mAudioDeviceConfig.useCoreAudioVolume = true;
474         mHALAudioZones.add(createSecondaryAudioZone());
475         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
476         helper.loadAudioZones();
477 
478         expectWithMessage("Loaded car audio volume with use core volume and load failure")
479                 .that(helper.useCoreAudioVolume()).isFalse();
480     }
481 
482     @Test
useVolumeGroupMuting_withoutCallingLoadZonesFirst()483     public void useVolumeGroupMuting_withoutCallingLoadZonesFirst() {
484         mHALAudioZones.add(createPrimaryAudioZone());
485         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
486 
487         expectWithMessage("Loaded car audio volume muting without initializing helper")
488                 .that(helper.useVolumeGroupMuting()).isFalse();
489     }
490 
491     @Test
useVolumeGroupMuting_withoutUseVolumeGroupMutingFromHal()492     public void useVolumeGroupMuting_withoutUseVolumeGroupMutingFromHal() {
493         mAudioDeviceConfig.useCarVolumeGroupMuting = false;
494         mHALAudioZones.add(createPrimaryAudioZone());
495         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
496         helper.loadAudioZones();
497 
498         expectWithMessage("Loaded car audio volume muting without use volume muting")
499                 .that(helper.useVolumeGroupMuting()).isFalse();
500     }
501 
502     @Test
useVolumeGroupMuting_withUseVolumeGroupMutingFromHal()503     public void useVolumeGroupMuting_withUseVolumeGroupMutingFromHal() {
504         mAudioDeviceConfig.useCarVolumeGroupMuting = true;
505         mHALAudioZones.add(createPrimaryAudioZone());
506         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
507         helper.loadAudioZones();
508 
509         expectWithMessage("Loaded car audio volume muting with use volume muting")
510                 .that(helper.useVolumeGroupMuting()).isTrue();
511     }
512 
513     @Test
useVolumeGroupMuting_withUseVolumeGroupMutingFromHalAndLoadFailure()514     public void useVolumeGroupMuting_withUseVolumeGroupMutingFromHalAndLoadFailure() {
515         mAudioDeviceConfig.useCarVolumeGroupMuting = true;
516         mHALAudioZones.add(createSecondaryAudioZone());
517         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
518         helper.loadAudioZones();
519 
520         expectWithMessage("Loaded car audio volume muting with use volume muting and load failure")
521                 .that(helper.useVolumeGroupMuting()).isFalse();
522     }
523 
524     @Test
useHalDuckingSignalOrDefault_withoutCallingLoadZonesFirst()525     public void useHalDuckingSignalOrDefault_withoutCallingLoadZonesFirst() {
526         mAudioDeviceConfig.useHalDuckingSignals = true;
527         mHALAudioZones.add(createPrimaryAudioZone());
528         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
529 
530         boolean useHalDucking = helper.useHalDuckingSignalOrDefault(
531                 /* unusedDefaultUseHalDuckingSignal= */ true);
532 
533         expectWithMessage("Loaded HAL ducking without initializing helper").that(useHalDucking)
534                 .isFalse();
535     }
536 
537     @Test
useHalDuckingSignalOrDefault_withoutUseHalDuckingFromHal()538     public void useHalDuckingSignalOrDefault_withoutUseHalDuckingFromHal() {
539         mAudioDeviceConfig.useHalDuckingSignals = false;
540         mHALAudioZones.add(createPrimaryAudioZone());
541         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
542         helper.loadAudioZones();
543 
544         boolean useHalDucking = helper.useHalDuckingSignalOrDefault(
545                 /* unusedDefaultUseHalDuckingSignal= */ true);
546 
547         expectWithMessage("Loaded HAL ducking without use HAL ducking").that(useHalDucking)
548                 .isFalse();
549     }
550 
551     @Test
useHalDuckingSignalOrDefault_withUseHalDuckingFromHal()552     public void useHalDuckingSignalOrDefault_withUseHalDuckingFromHal() {
553         mAudioDeviceConfig.useHalDuckingSignals = true;
554         mHALAudioZones.add(createPrimaryAudioZone());
555         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
556         helper.loadAudioZones();
557 
558         boolean useHalDucking = helper.useHalDuckingSignalOrDefault(
559                 /* unusedDefaultUseHalDuckingSignal= */ true);
560 
561         expectWithMessage("Loaded HAL ducking with use HAL ducking").that(useHalDucking).isTrue();
562     }
563 
564     @Test
useHalDuckingSignalOrDefault_withUseHalDuckingFromHalAndOverwriteFromParameter()565     public void useHalDuckingSignalOrDefault_withUseHalDuckingFromHalAndOverwriteFromParameter() {
566         mAudioDeviceConfig.useHalDuckingSignals = true;
567         mHALAudioZones.add(createPrimaryAudioZone());
568         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
569         helper.loadAudioZones();
570 
571         boolean useHalDucking = helper.useHalDuckingSignalOrDefault(
572                 /* unusedDefaultUseHalDuckingSignal= */ false);
573 
574         expectWithMessage("Loaded HAL ducking with use HAL ducking and false overwritten from "
575                 + "parameter").that(useHalDucking).isTrue();
576     }
577 
578     @Test
useHalDuckingSignalOrDefault_withUseHalDuckingFromHalAndLoadFailure()579     public void useHalDuckingSignalOrDefault_withUseHalDuckingFromHalAndLoadFailure() {
580         mAudioDeviceConfig.useHalDuckingSignals = true;
581         mHALAudioZones.add(createSecondaryAudioZone());
582         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
583         helper.loadAudioZones();
584 
585         boolean useHalDucking = helper.useHalDuckingSignalOrDefault(
586                 /* unusedDefaultUseHalDuckingSignal= */ true);
587 
588         expectWithMessage("Loaded HAL ducking with use HAL ducking and load failure")
589                 .that(useHalDucking).isFalse();
590     }
591 
592     @Test
getMirrorDeviceInfos_withNullPortList()593     public void getMirrorDeviceInfos_withNullPortList() {
594         when(mAudioControlWrapper.getOutputMirroringDevices()).thenReturn(null);
595         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
596 
597         expectWithMessage("Converted output mirror devices for null ports list")
598                 .that(helper.getMirrorDeviceInfos()).isEmpty();
599     }
600 
601     @Test
getMirrorDeviceInfos_withEmptyPortList()602     public void getMirrorDeviceInfos_withEmptyPortList() {
603         mMirrorPorts.clear();
604         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
605 
606         expectWithMessage("Converted output mirror devices for empty ports list")
607                 .that(helper.getMirrorDeviceInfos()).isEmpty();
608     }
609 
610     @Test
getMirrorDeviceInfos_withValidPortList()611     public void getMirrorDeviceInfos_withValidPortList() {
612         AudioPortDeviceExt navPortDevice =
613                 createAudioPortDeviceExt(AudioDeviceType.OUT_BUS, "", NAVIGATION_TEST_DEVICE);
614         AudioPort navPort = createAudioPort(2, "nav port", GAINS, navPortDevice);
615         AudioPortDeviceExt mediaPortDevice =
616                 createAudioPortDeviceExt(AudioDeviceType.OUT_BUS, "", MEDIA_TEST_DEVICE);
617         AudioPort mediaPort = createAudioPort(1, "media port", GAINS, mediaPortDevice);
618         mMirrorPorts.add(mediaPort);
619         mMirrorPorts.add(navPort);
620         CarAudioZonesHelperAudioControlHAL helper = createAudioZonesHelper();
621 
622         var mirroringDevices = helper.getMirrorDeviceInfos();
623 
624         expectWithMessage("Converted output mirror devices for valid ports list")
625                 .that(mirroringDevices).hasSize(2);
626         var addresses = mirroringDevices.stream().map(CarAudioDeviceInfo::getAddress).toList();
627         expectWithMessage("Converted output mirror device addresses").that(addresses)
628                 .containsExactly(NAVIGATION_TEST_DEVICE, MEDIA_TEST_DEVICE);
629     }
630 
createAudioZonesHelper()631     private CarAudioZonesHelperAudioControlHAL createAudioZonesHelper() {
632         return new CarAudioZonesHelperAudioControlHAL(mAudioControlWrapper, mAudioManager,
633                 mCarAudioSettings, mServiceLog, mUseAudioFadeManager);
634     }
635 }
636